From 33065932f99f3caa436b19d6ae7d3590d8b35047 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 7 Oct 2008 22:04:00 +0000 Subject: [PATCH 001/252] First sketching draft code. Left Click and drag for continuous strokes, left click for exact points, Right click to end strokes. The view can be manipulated while drawing a stroke (between exact point). Sketching is turned on all the time, this is mainly useful for testing, do not use seriously, nothing is saved, it gives memory errors on exit, yada yada --- source/blender/include/BDR_sketch.h | 29 ++ source/blender/include/BIF_sketch.h | 28 ++ source/blender/src/drawview.c | 3 + source/blender/src/editarmature_sketch.c | 475 +++++++++++++++++++++++ source/blender/src/space.c | 6 + 5 files changed, 541 insertions(+) create mode 100644 source/blender/include/BDR_sketch.h create mode 100644 source/blender/include/BIF_sketch.h create mode 100644 source/blender/src/editarmature_sketch.c diff --git a/source/blender/include/BDR_sketch.h b/source/blender/include/BDR_sketch.h new file mode 100644 index 00000000000..1de53ea2d27 --- /dev/null +++ b/source/blender/include/BDR_sketch.h @@ -0,0 +1,29 @@ +/** + * $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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BDR_SKETCH_H +#define BDR_SKETCH_H + +void BDR_queueDrawSketch(); +void BDR_drawSketch(); + +#endif /* BDR_SKETCH_H */ diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h new file mode 100644 index 00000000000..41fac3da845 --- /dev/null +++ b/source/blender/include/BIF_sketch.h @@ -0,0 +1,28 @@ +/** + * $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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BIF_SKETCH_H +#define BIF_SKETCH_H + +int BIF_paintSketch(); + +#endif /* BIF_SKETCH_H */ diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 8f2623575aa..7223de049f7 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -143,6 +143,7 @@ #include "BDR_vpaint.h" #include "BDR_sculptmode.h" #include "BDR_gpencil.h" +#include "BDR_sketch.h" #include "BSE_drawview.h" #include "BSE_filesel.h" @@ -3264,6 +3265,8 @@ void drawview3dspace(ScrArea *sa, void *spacedata) /* draw grease-pencil stuff */ if (v3d->flag2 & V3D_DISPGP) draw_gpencil_3dview(sa, 1); + + BDR_drawSketch(); persp(PERSP_WIN); // set ortho diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c new file mode 100644 index 00000000000..f449dc727b6 --- /dev/null +++ b/source/blender/src/editarmature_sketch.c @@ -0,0 +1,475 @@ +/** + * $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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_utildefines.h" + +#include "BSE_view.h" + +#include "BIF_gl.h" +#include "BIF_resources.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "BIF_mywindow.h" + +#include "mydevice.h" + +typedef enum SK_PType +{ + PT_CONTINUOUS, + PT_EXACT, +} SK_PType; + +typedef struct SK_Point +{ + float p[3]; + SK_PType type; +} SK_Point; + +typedef struct SK_Stroke +{ + struct SK_Stroke *next, *prev; + + SK_Point *points; + int nb_points; + int buf_size; +} SK_Stroke; + +#define SK_Stroke_BUFFER_INIT_SIZE 20 + +typedef struct SK_DrawData +{ + short mval[2]; + short previous_mval[2]; + SK_PType type; +} SK_DrawData; + +typedef struct SK_Sketch +{ + ListBase strokes; + SK_Stroke *active_stroke; +} SK_Sketch; + +SK_Sketch *GLOBAL_sketch = NULL; + +/**************************************************************/ + +SK_Sketch* sk_createSketch() +{ + SK_Sketch *sketch; + + sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch"); + + sketch->active_stroke = NULL; + + sketch->strokes.first = NULL; + sketch->strokes.last = NULL; + + return sketch; +} + +void sk_allocStrokeBuffer(SK_Stroke *stk) +{ + stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer"); +} + +SK_Stroke* sk_createStroke() +{ + SK_Stroke *stk; + + stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke"); + + stk->nb_points = 0; + stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE; + + sk_allocStrokeBuffer(stk); + + return stk; +} + +void sk_shrinkStrokeBuffer(SK_Stroke *stk) +{ + if (stk->nb_points < stk->buf_size) + { + SK_Point *old_points = stk->points; + + stk->buf_size = stk->nb_points; + + sk_allocStrokeBuffer(stk); + + memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); + + MEM_freeN(old_points); + } +} + +void sk_growStrokeBuffer(SK_Stroke *stk) +{ + if (stk->nb_points == stk->buf_size) + { + SK_Point *old_points = stk->points; + + stk->buf_size *= 2; + + sk_allocStrokeBuffer(stk); + + memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); + + MEM_freeN(old_points); + } +} + +void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt) +{ + sk_growStrokeBuffer(stk); + + memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point)); + + stk->nb_points++; +} + +/* Apply reverse Chaikin filter to simplify the polyline + * */ +void sk_filterStroke(SK_Stroke *stk) +{ + SK_Point *old_points = stk->points; + int nb_points = stk->nb_points; + int i, j; + + sk_allocStrokeBuffer(stk); + stk->nb_points = 0; + + for (i = 0, j = 0; i < nb_points; i++) + { + if (i - j == 3) + { + SK_Point pt; + float vec[3]; + + pt.type = PT_CONTINUOUS; + pt.p[0] = 0; + pt.p[1] = 0; + pt.p[2] = 0; + + VECCOPY(vec, old_points[j].p); + VecMulf(vec, -0.25); + VecAddf(pt.p, pt.p, vec); + + VECCOPY(vec, old_points[j+1].p); + VecMulf(vec, 0.75); + VecAddf(pt.p, pt.p, vec); + + VECCOPY(vec, old_points[j+2].p); + VecMulf(vec, 0.75); + VecAddf(pt.p, pt.p, vec); + + VECCOPY(vec, old_points[j+3].p); + VecMulf(vec, -0.25); + VecAddf(pt.p, pt.p, vec); + + sk_appendStrokePoint(stk, &pt); + + j += 2; + } + + if (old_points[i].type == PT_EXACT) + { + sk_appendStrokePoint(stk, old_points + i); + j = i; + } + } + + MEM_freeN(old_points); + + sk_shrinkStrokeBuffer(stk); +} + +SK_Point *sk_lastStrokePoint(SK_Stroke *stk) +{ + SK_Point *pt = NULL; + + if (stk->nb_points > 0) + { + pt = stk->points + (stk->nb_points - 1); + } + + return pt; +} + +void sk_drawStroke(SK_Stroke *stk) +{ + int i; + + glColor3f(1, 0.5, 0); + glBegin(GL_LINE_STRIP); + + for (i = 0; i < stk->nb_points; i++) + { + glVertex3fv(stk->points[i].p); + } + + glEnd(); + + glColor3f(0, 0, 0); + glBegin(GL_POINTS); + + for (i = 0; i < stk->nb_points; i++) + { + if (stk->points[i].type == PT_EXACT) + { + glVertex3fv(stk->points[i].p); + } + } + + glEnd(); + + glColor3f(1, 1, 1); + glBegin(GL_POINTS); + + for (i = 0; i < stk->nb_points; i++) + { + if (stk->points[i].type == PT_CONTINUOUS) + { + glVertex3fv(stk->points[i].p); + } + } + + glEnd(); +} + +void sk_startStroke(SK_Sketch *sketch) +{ + SK_Stroke *stk = sk_createStroke(); + + BLI_addtail(&sketch->strokes, stk); + sketch->active_stroke = stk; +} + +void sk_endStroke(SK_Sketch *sketch) +{ + sk_shrinkStrokeBuffer(sketch->active_stroke); + sketch->active_stroke = NULL; +} + +void sk_projectPaintData(SK_Stroke *stk, SK_DrawData *dd, float vec[3]) +{ + /* copied from grease pencil, need fixing */ + SK_Point *last = sk_lastStrokePoint(stk); + short cval[2]; + //float *fp = give_cursor(); + float fp[3] = {0, 0, 0}; + float dvec[3]; + + if (last != NULL) + { + VECCOPY(fp, last->p); + } + + /* method taken from editview.c - mouse_cursor() */ + project_short_noclip(fp, cval); + window_to_3d(dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]); + VecSubf(vec, fp, dvec); +} + +void sk_addStrokePoint(SK_Stroke *stk, SK_DrawData *dd) +{ + SK_Point pt; + + pt.type = dd->type; + + sk_projectPaintData(stk, dd, pt.p); + + sk_appendStrokePoint(stk, &pt); + + dd->type = PT_CONTINUOUS; + + dd->previous_mval[0] = dd->mval[0]; + dd->previous_mval[1] = dd->mval[1]; +} + +void sk_endContinuousStroke(SK_Stroke *stk) +{ + stk->points[stk->nb_points - 1].type = PT_EXACT; +} + +int sk_stroke_filtermval(SK_DrawData *dd) +{ + int retval = 0; + if (dd->mval[0] != dd->previous_mval[0] || dd->mval[1] != dd->previous_mval[1]) + { + retval = 1; + } + + return retval; +} + +void sk_initDrawData(SK_DrawData *dd) +{ + getmouseco_areawin(dd->mval); + dd->previous_mval[0] = -1; + dd->previous_mval[1] = -1; + dd->type = PT_EXACT; +} + +/********************************************/ + +void sk_queueRedrawSketch(SK_Sketch *sketch) +{ + if (sketch->active_stroke != NULL) + { + SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); + + if (last != NULL) + { + allqueue(REDRAWVIEW3D, 0); + } + } +} + +void sk_drawSketch(SK_Sketch *sketch) +{ + SK_Stroke *stk; + + glDisable(GL_DEPTH_TEST); + + glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE)); + glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE)); + + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + sk_drawStroke(stk); + } + + if (sketch->active_stroke != NULL) + { + SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); + + if (last != NULL) + { + SK_DrawData dd; + float vec[3]; + + sk_initDrawData(&dd); + sk_projectPaintData(sketch->active_stroke, &dd, vec); + + glEnable(GL_LINE_STIPPLE); + glColor3f(1, 0.5, 0); + glBegin(GL_LINE_STRIP); + + glVertex3fv(last->p); + glVertex3fv(vec); + + glEnd(); + + glDisable(GL_LINE_STIPPLE); + + } + } + + glLineWidth(1.0); + glPointSize(1.0); + + glEnable(GL_DEPTH_TEST); +} + +int sk_paint(SK_Sketch *sketch, short mbut) +{ + int retval = 1; + + if (mbut == LEFTMOUSE) + { + SK_DrawData dd; + if (sketch->active_stroke == NULL) + { + sk_startStroke(sketch); + } + + sk_initDrawData(&dd); + + /* paint loop */ + do { + /* get current user input */ + getmouseco_areawin(dd.mval); + + /* only add current point to buffer if mouse moved (otherwise wait until it does) */ + if (sk_stroke_filtermval(&dd)) { + sk_addStrokePoint(sketch->active_stroke, &dd); + + force_draw(0); + } + else + BIF_wait_for_statechange(); + + /* do mouse checking at the end, so don't check twice, and potentially + * miss a short tap + */ + } while (get_mbut() & LEFTMOUSE); + + sk_endContinuousStroke(sketch->active_stroke); + } + else if (mbut == RIGHTMOUSE) + { + if (sketch->active_stroke != NULL) + { + sk_filterStroke(sketch->active_stroke); + sk_endStroke(sketch); + } + } + + return retval; +} + + +void BDR_drawSketch() +{ + if (GLOBAL_sketch != NULL) + { + sk_drawSketch(GLOBAL_sketch); + } +} + +int BIF_paintSketch(short mbut) +{ + if (GLOBAL_sketch == NULL) + { + GLOBAL_sketch = sk_createSketch(); + } + + return sk_paint(GLOBAL_sketch, mbut); +} + +void BDR_queueDrawSketch() +{ + if (GLOBAL_sketch != NULL) + { + sk_queueRedrawSketch(GLOBAL_sketch); + } +} diff --git a/source/blender/src/space.c b/source/blender/src/space.c index cb838dc0b26..17e96c00f79 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -139,6 +139,7 @@ #include "BIF_toolbox.h" #include "BIF_usiblender.h" #include "BIF_previewrender.h" +#include "BIF_sketch.h" #include "BSE_edit.h" #include "BSE_view.h" @@ -163,6 +164,7 @@ #include "BDR_sculptmode.h" #include "BDR_unwrapper.h" #include "BDR_gpencil.h" +#include "BDR_sketch.h" #include "BLO_readfile.h" /* for BLO_blendhandle_close */ @@ -1254,11 +1256,13 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) return; /* return if event was processed (swallowed) by handler(s) */ } + if(BIF_paintSketch(LEFTMOUSE)) return; if(gpencil_do_paint(sa, L_MOUSE)) return; if(BIF_do_manipulator(sa)) return; } else if(event==RIGHTMOUSE) { if(gpencil_do_paint(sa, R_MOUSE)) return; + if(BIF_paintSketch(RIGHTMOUSE)) return; } /* swap mouse buttons based on user preference */ @@ -1301,6 +1305,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } } + + BDR_queueDrawSketch(); /* Handle retopo painting */ if(retopo_mesh_paint_check()) { From b613eb2e217a8a97bc531f5a261c937665d3ab2c Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 8 Oct 2008 20:54:19 +0000 Subject: [PATCH 002/252] Sketching snapping. Hold Ctrl to snap to an exact point (black dots). Continuous strokes are extrapolated between the depth difference of both end points when snapping. --- source/blender/src/editarmature_sketch.c | 212 +++++++++++++++++++++-- 1 file changed, 200 insertions(+), 12 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index f449dc727b6..b3945ecf30e 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -26,11 +26,13 @@ #include "DNA_listBase.h" #include "DNA_scene_types.h" +#include "DNA_view3d_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BKE_utildefines.h" +#include "BKE_global.h" #include "BSE_view.h" @@ -80,8 +82,27 @@ typedef struct SK_Sketch SK_Sketch *GLOBAL_sketch = NULL; +/******************** PROTOTYPES ******************************/ + +void sk_freeStroke(SK_Stroke *stk); +void sk_freeSketch(SK_Sketch *sketch); + /**************************************************************/ +void sk_freeSketch(SK_Sketch *sketch) +{ + SK_Stroke *stk, *next; + + for (stk = sketch->strokes.first; stk; stk = next) + { + next = stk->next; + + sk_freeStroke(stk); + } + + MEM_freeN(sketch); +} + SK_Sketch* sk_createSketch() { SK_Sketch *sketch; @@ -101,6 +122,12 @@ void sk_allocStrokeBuffer(SK_Stroke *stk) stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer"); } +void sk_freeStroke(SK_Stroke *stk) +{ + MEM_freeN(stk->points); + MEM_freeN(stk); +} + SK_Stroke* sk_createStroke() { SK_Stroke *stk; @@ -251,18 +278,65 @@ void sk_drawStroke(SK_Stroke *stk) glEnd(); - glColor3f(1, 1, 1); - glBegin(GL_POINTS); +// glColor3f(1, 1, 1); +// glBegin(GL_POINTS); +// +// for (i = 0; i < stk->nb_points; i++) +// { +// if (stk->points[i].type == PT_CONTINUOUS) +// { +// glVertex3fv(stk->points[i].p); +// } +// } +// +// glEnd(); +} +SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist) +{ + SK_Point *pt = NULL; + int i; + for (i = 0; i < stk->nb_points; i++) { - if (stk->points[i].type == PT_CONTINUOUS) + if (stk->points[i].type == PT_EXACT) { - glVertex3fv(stk->points[i].p); + short pval[2]; + int pdist; + + project_short_noclip(stk->points[i].p, pval); + + pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); + + if (pdist < *dist) + { + *dist = pdist; + pt = stk->points + i; + } } } + + return pt; +} - glEnd(); + +SK_Point *sk_snapPoint(SK_Sketch *sketch, short mval[2], int min_dist) +{ + SK_Point *pt = NULL; + SK_Stroke *stk; + int dist = min_dist; + + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + SK_Point *spt = sk_snapPointStroke(stk, mval, &dist); + + if (spt != NULL) + { + pt = spt; + } + } + + return pt; } void sk_startStroke(SK_Sketch *sketch) @@ -293,13 +367,93 @@ void sk_projectPaintData(SK_Stroke *stk, SK_DrawData *dd, float vec[3]) VECCOPY(fp, last->p); } + initgrabz(fp[0], fp[1], fp[2]); + /* method taken from editview.c - mouse_cursor() */ project_short_noclip(fp, cval); window_to_3d(dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]); VecSubf(vec, fp, dvec); } -void sk_addStrokePoint(SK_Stroke *stk, SK_DrawData *dd) +void sk_updateDrawData(SK_DrawData *dd) +{ + dd->type = PT_CONTINUOUS; + + dd->previous_mval[0] = dd->mval[0]; + dd->previous_mval[1] = dd->mval[1]; +} + +float sk_distanceDepth(float p1[3], float p2[3]) +{ + float vec[3]; + float distance; + + VecSubf(vec, p1, p2); + + Projf(vec, vec, G.vd->viewinv[2]); + + distance = VecLength(vec); + + if (Inpf(G.vd->viewinv[2], vec) > 0) + { + distance *= -1; + } + + return distance; +} + +void sk_addStrokeSnapPoint(SK_Stroke *stk, SK_DrawData *dd, SK_Point *snap_pt) +{ + SK_Point pt; + float distance; + float length; + int i, j, total; + + pt.type = PT_EXACT; + + sk_projectPaintData(stk, dd, pt.p); + + sk_appendStrokePoint(stk, &pt); + + /* update all previous point to give smooth Z progresion */ + total = 0; + length = 0; + for (i = stk->nb_points - 2; i > 0; i--) + { + length += VecLenf(stk->points[i].p, stk->points[i + 1].p); + total++; + if (stk->points[i].type == PT_EXACT) + { + break; + } + } + + if (total > 1) + { + float progress = length - VecLenf(stk->points[stk->nb_points - 2].p, stk->points[stk->nb_points - 1].p); + + distance = sk_distanceDepth(snap_pt->p, stk->points[i].p); + + for (j = 1, i = stk->nb_points - 2; j < total; j++, i--) + { + float ray_start[3], ray_normal[3]; + float delta = VecLenf(stk->points[i].p, stk->points[i - 1].p); + short pval[2]; + + project_short_noclip(stk->points[i].p, pval); + viewray(pval, ray_start, ray_normal); + + VecMulf(ray_normal, distance * progress / length); + VecAddf(stk->points[i].p, stk->points[i].p, ray_normal); + + progress -= delta ; + } + } + + VECCOPY(stk->points[stk->nb_points - 1].p, snap_pt->p); +} + +void sk_addStrokeDrawPoint(SK_Stroke *stk, SK_DrawData *dd) { SK_Point pt; @@ -308,11 +462,6 @@ void sk_addStrokePoint(SK_Stroke *stk, SK_DrawData *dd) sk_projectPaintData(stk, dd, pt.p); sk_appendStrokePoint(stk, &pt); - - dd->type = PT_CONTINUOUS; - - dd->previous_mval[0] = dd->mval[0]; - dd->previous_mval[1] = dd->mval[1]; } void sk_endContinuousStroke(SK_Stroke *stk) @@ -391,6 +540,20 @@ void sk_drawSketch(SK_Sketch *sketch) glDisable(GL_LINE_STIPPLE); + if (G.qual & LR_CTRLKEY) + { + SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, 30); + + if (snap_pt != NULL) + { + glColor3f(0, 0.5, 1); + glBegin(GL_POINTS); + + glVertex3fv(snap_pt->p); + + glEnd(); + } + } } } @@ -421,12 +584,36 @@ int sk_paint(SK_Sketch *sketch, short mbut) /* only add current point to buffer if mouse moved (otherwise wait until it does) */ if (sk_stroke_filtermval(&dd)) { - sk_addStrokePoint(sketch->active_stroke, &dd); + if (G.qual & LR_CTRLKEY) + { + SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, 30); + + if (snap_pt != NULL) + { + sk_addStrokeSnapPoint(sketch->active_stroke, &dd, snap_pt); + } + else + { + sk_addStrokeDrawPoint(sketch->active_stroke, &dd); + } + } + else + { + sk_addStrokeDrawPoint(sketch->active_stroke, &dd); + } + sk_updateDrawData(&dd); force_draw(0); } else + { BIF_wait_for_statechange(); + } + + while( qtest() ) { + short event, val; + event = extern_qread(&val); + } /* do mouse checking at the end, so don't check twice, and potentially * miss a short tap @@ -441,6 +628,7 @@ int sk_paint(SK_Sketch *sketch, short mbut) { sk_filterStroke(sketch->active_stroke); sk_endStroke(sketch); + allqueue(REDRAWVIEW3D, 0); } } From bf3e539865ca209ac04617cf5a448cfe8e66ac89 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 9 Oct 2008 20:45:33 +0000 Subject: [PATCH 003/252] Sketching embedding. Hold down Shift to embed points inside a mesh (or on a mesh, if there's no volume). Done by gathering all the ray hits under mouse, sorting by depth and using the first two. Eventually could probably use hardware based depth peeling. Ray hit method could use bvh or some other accelerator too. Eventually, will have a mechanism to keep consistent depth while painting continuous lines (painting over a partly obscured mesh shouldn't jump to the top one). --- source/blender/src/editarmature_sketch.c | 252 +++++++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index b3945ecf30e..8fb74b4916c 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -27,12 +27,17 @@ #include "DNA_listBase.h" #include "DNA_scene_types.h" #include "DNA_view3d_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BKE_utildefines.h" #include "BKE_global.h" +#include "BKE_DerivedMesh.h" +#include "BKE_object.h" +#include "BKE_anim.h" #include "BSE_view.h" @@ -42,6 +47,7 @@ #include "BIF_space.h" #include "BIF_mywindow.h" +#include "blendef.h" #include "mydevice.h" typedef enum SK_PType @@ -87,6 +93,209 @@ SK_Sketch *GLOBAL_sketch = NULL; void sk_freeStroke(SK_Stroke *stk); void sk_freeSketch(SK_Sketch *sketch); +/******************** PEELING *********************************/ + +typedef struct SK_DepthPeel +{ + struct SK_DepthPeel *next, *prev; + + float depth; + float p[3]; + float no[3]; +} SK_DepthPeel; + +int cmpPeel(void *arg1, void *arg2) +{ + SK_DepthPeel *p1 = arg1; + SK_DepthPeel *p2 = arg2; + int val = 0; + + if (p1->depth < p2->depth) + { + val = -1; + } + else if (p1->depth > p2->depth) + { + val = 1; + } + + return val; +} + +void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3]) +{ + SK_DepthPeel *peel = MEM_callocN(sizeof(SK_DepthPeel), "DepthPeel"); + + peel->depth = depth; + VECCOPY(peel->p, p); + VECCOPY(peel->no, no); + + BLI_addtail(depth_peels, peel); +} + +int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels) +{ + int retval = 0; + int totvert = dm->getNumVerts(dm); + int totface = dm->getNumFaces(dm); + + if (totvert > 0) { + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_start_local[3], ray_normal_local[3]; + int test = 1; + + Mat4Invert(imat, obmat); + + Mat3CpyMat4(timat, imat); + Mat3Transp(timat); + + VECCOPY(ray_start_local, ray_start); + VECCOPY(ray_normal_local, ray_normal); + + Mat4MulVecfl(imat, ray_start_local); + Mat4Mul3Vecfl(imat, ray_normal_local); + + + /* If number of vert is more than an arbitrary limit, + * test against boundbox first + * */ + if (totface > 16) { + struct BoundBox *bb = object_get_boundbox(ob); + test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local); + } + + if (test == 1) { + MVert *verts = dm->getVertArray(dm); + MFace *faces = dm->getFaceArray(dm); + int i; + + for( i = 0; i < totface; i++) { + MFace *f = faces + i; + float lambda; + int result; + + + result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL); + + if (result) { + float location[3], normal[3]; + float intersect[3]; + float new_depth; + + VECCOPY(intersect, ray_normal_local); + VecMulf(intersect, lambda); + VecAddf(intersect, intersect, ray_start_local); + + VECCOPY(location, intersect); + + if (f->v4) + CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); + else + CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + Mat3MulVecfl(timat, normal); + Normalize(normal); + + addDepthPeel(depth_peels, new_depth, location, normal); + } + + if (f->v4 && result == 0) + { + result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL); + + if (result) { + float location[3], normal[3]; + float intersect[3]; + float new_depth; + + VECCOPY(intersect, ray_normal_local); + VecMulf(intersect, lambda); + VecAddf(intersect, intersect, ray_start_local); + + VECCOPY(location, intersect); + + if (f->v4) + CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); + else + CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + Mat3MulVecfl(timat, normal); + Normalize(normal); + + addDepthPeel(depth_peels, new_depth, location, normal); + } + } + } + } + } + + return retval; +} + +int peelObjects(ListBase *depth_peels, short mval[2]) +{ + Base *base; + int retval = 0; + float ray_start[3], ray_normal[3]; + + viewray(mval, ray_start, ray_normal); + + base= FIRSTBASE; + for ( base = FIRSTBASE; base != NULL; base = base->next ) { + if ( BASE_SELECTABLE(base) ) { + Object *ob = base->object; + + if (ob->transflag & OB_DUPLI) + { + DupliObject *dupli_ob; + ListBase *lb = object_duplilist(G.scene, ob); + + for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) + { + Object *ob = dupli_ob->ob; + + if (ob->type == OB_MESH) { + DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + int val; + + val = peelDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, depth_peels); + + retval = retval || val; + + dm->release(dm); + } + } + + free_object_duplilist(lb); + } + + if (ob->type == OB_MESH) { + DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + int val; + + val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); + + retval = retval || val; + + dm->release(dm); + } + } + } + + BLI_sortlist(depth_peels, cmpPeel); + + return retval; +} + /**************************************************************/ void sk_freeSketch(SK_Sketch *sketch) @@ -464,6 +673,45 @@ void sk_addStrokeDrawPoint(SK_Stroke *stk, SK_DrawData *dd) sk_appendStrokePoint(stk, &pt); } +void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) +{ + SK_DepthPeel *p1, *p2; + ListBase depth_peels; + + depth_peels.first = depth_peels.last = NULL; + + peelObjects(&depth_peels, dd->mval); + + p1 = depth_peels.first; + + if (p1) + { + SK_Point pt; + + pt.type = dd->type; + + p2 = p1->next; + + if (p2) + { + VecAddf(pt.p, p1->p, p2->p); + VecMulf(pt.p, 0.5f); + } + else + { + VECCOPY(pt.p, p1->p); + } + + sk_appendStrokePoint(stk, &pt); + } + else + { + sk_addStrokeDrawPoint(stk, dd); + } + + BLI_freelistN(&depth_peels); +} + void sk_endContinuousStroke(SK_Stroke *stk) { stk->points[stk->nb_points - 1].type = PT_EXACT; @@ -597,6 +845,10 @@ int sk_paint(SK_Sketch *sketch, short mbut) sk_addStrokeDrawPoint(sketch->active_stroke, &dd); } } + else if (G.qual & LR_SHIFTKEY) + { + sk_addStrokeEmbedPoint(sketch->active_stroke, &dd); + } else { sk_addStrokeDrawPoint(sketch->active_stroke, &dd); From 915377060f1d90edc67372912982f41132806830 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 9 Oct 2008 21:39:26 +0000 Subject: [PATCH 004/252] - Filter continuous strokes as they are drawn instead of only when ending a line. - Pair depth hits per object, to stay consistent if you have an object instead another one (say, if you're drawing on a coat and at one point the hand starts, you don't want to pair the first hit on the coat with the first hit on the hand). --- source/blender/src/editarmature_sketch.c | 56 +++++++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 8fb74b4916c..da996e00d0f 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -102,6 +102,7 @@ typedef struct SK_DepthPeel float depth; float p[3]; float no[3]; + Object *ob; } SK_DepthPeel; int cmpPeel(void *arg1, void *arg2) @@ -122,11 +123,12 @@ int cmpPeel(void *arg1, void *arg2) return val; } -void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3]) +void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob) { SK_DepthPeel *peel = MEM_callocN(sizeof(SK_DepthPeel), "DepthPeel"); peel->depth = depth; + peel->ob = ob; VECCOPY(peel->p, p); VECCOPY(peel->no, no); @@ -201,7 +203,7 @@ int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta Mat3MulVecfl(timat, normal); Normalize(normal); - addDepthPeel(depth_peels, new_depth, location, normal); + addDepthPeel(depth_peels, new_depth, location, normal, ob); } if (f->v4 && result == 0) @@ -231,7 +233,7 @@ int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta Mat3MulVecfl(timat, normal); Normalize(normal); - addDepthPeel(depth_peels, new_depth, location, normal); + addDepthPeel(depth_peels, new_depth, location, normal, ob); } } } @@ -394,16 +396,28 @@ void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt) /* Apply reverse Chaikin filter to simplify the polyline * */ -void sk_filterStroke(SK_Stroke *stk) +void sk_filterStroke(SK_Stroke *stk, int start, int end) { SK_Point *old_points = stk->points; int nb_points = stk->nb_points; int i, j; + if (start == -1) + { + start = 0; + end = stk->nb_points - 1; + } + sk_allocStrokeBuffer(stk); stk->nb_points = 0; - for (i = 0, j = 0; i < nb_points; i++) + /* adding points before range */ + for (i = 0; i < start; i++) + { + sk_appendStrokePoint(stk, old_points + i); + } + + for (i = start, j = start; i <= end; i++) { if (i - j == 3) { @@ -436,6 +450,7 @@ void sk_filterStroke(SK_Stroke *stk) j += 2; } + /* this might be uneeded when filtering last continuous stroke */ if (old_points[i].type == PT_EXACT) { sk_appendStrokePoint(stk, old_points + i); @@ -443,11 +458,34 @@ void sk_filterStroke(SK_Stroke *stk) } } + /* adding points after range */ + for (i = end + 1; i < nb_points; i++) + { + sk_appendStrokePoint(stk, old_points + i); + } + MEM_freeN(old_points); sk_shrinkStrokeBuffer(stk); } +void sk_filterLastContinuousStroke(SK_Stroke *stk) +{ + int start, end; + + end = stk->nb_points -1; + + for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--) + { + /* nothing to do here*/ + } + + if (end - start > 1) + { + sk_filterStroke(stk, start, end); + } +} + SK_Point *sk_lastStrokePoint(SK_Stroke *stk) { SK_Point *pt = NULL; @@ -690,7 +728,11 @@ void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) pt.type = dd->type; - p2 = p1->next; + for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + { + /* nothing to do here */ + } + if (p2) { @@ -873,12 +915,12 @@ int sk_paint(SK_Sketch *sketch, short mbut) } while (get_mbut() & LEFTMOUSE); sk_endContinuousStroke(sketch->active_stroke); + sk_filterLastContinuousStroke(sketch->active_stroke); } else if (mbut == RIGHTMOUSE) { if (sketch->active_stroke != NULL) { - sk_filterStroke(sketch->active_stroke); sk_endStroke(sketch); allqueue(REDRAWVIEW3D, 0); } From de4ed8ed5690d3c64edbc82f3959109d8d28476d Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 10 Oct 2008 02:59:09 +0000 Subject: [PATCH 005/252] Stroke embedding. When doing continuous strokes, use the depth hit closests to last, so you can start on a limb and then continue drawing inside it even if things overlap. --- source/blender/src/editarmature_sketch.c | 84 +++++++++++++++++------- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index da996e00d0f..77826e317f8 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -103,6 +103,7 @@ typedef struct SK_DepthPeel float p[3]; float no[3]; Object *ob; + int flag; } SK_DepthPeel; int cmpPeel(void *arg1, void *arg2) @@ -133,6 +134,8 @@ void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], O VECCOPY(peel->no, no); BLI_addtail(depth_peels, peel); + + peel->flag = 0; } int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels) @@ -713,43 +716,80 @@ void sk_addStrokeDrawPoint(SK_Stroke *stk, SK_DrawData *dd) void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) { - SK_DepthPeel *p1, *p2; ListBase depth_peels; + SK_DepthPeel *p1, *p2; + SK_Point *last_pt = NULL; + float dist = FLT_MAX; + float p[3]; depth_peels.first = depth_peels.last = NULL; peelObjects(&depth_peels, dd->mval); - p1 = depth_peels.first; - if (p1) + if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) + { + last_pt = stk->points + (stk->nb_points - 1); + } + + + for (p1 = depth_peels.first; p1; p1 = p1->next) + { + if (p1->flag == 0) + { + float vec[3]; + float new_dist; + + p1->flag = 0; + + for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + { + /* nothing to do here */ + } + + + if (p2) + { + p2->flag = 1; + + VecAddf(vec, p1->p, p2->p); + VecMulf(vec, 0.5f); + } + else + { + VECCOPY(vec, p1->p); + } + + if (last_pt == NULL) + { + VECCOPY(p, vec); + break; + } + + new_dist = VecLenf(last_pt->p, vec); + + if (new_dist < dist) + { + VECCOPY(p, vec); + dist = new_dist; + } + } + } + + if (dist == FLT_MAX) + { + sk_addStrokeDrawPoint(stk, dd); + } + else { SK_Point pt; pt.type = dd->type; - - for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) - { - /* nothing to do here */ - } + VECCOPY(pt.p, p); - if (p2) - { - VecAddf(pt.p, p1->p, p2->p); - VecMulf(pt.p, 0.5f); - } - else - { - VECCOPY(pt.p, p1->p); - } - sk_appendStrokePoint(stk, &pt); } - else - { - sk_addStrokeDrawPoint(stk, dd); - } BLI_freelistN(&depth_peels); } From 2cfd53a76db4ff46d8038e6e14a6f2a736699acb Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 10 Oct 2008 13:36:05 +0000 Subject: [PATCH 006/252] Continuous Embedded Stroke: First point was incorrectly embedded because of missing variable assign. --- source/blender/src/editarmature_sketch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 77826e317f8..b8979c682cc 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -763,6 +763,7 @@ void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) if (last_pt == NULL) { VECCOPY(p, vec); + dist = 0; break; } From 69cf55a7d4c3686d13deaaa00d9d036ad058d41c Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 10 Oct 2008 20:23:49 +0000 Subject: [PATCH 007/252] Sketch Embed: fix bug when used in edit mode. It's not supposed to be used in mesh edit mode, but at least now it doesn't crash. --- source/blender/src/editarmature_sketch.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index b8979c682cc..21dbad003aa 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -284,11 +284,22 @@ int peelObjects(ListBase *depth_peels, short mval[2]) } if (ob->type == OB_MESH) { - DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + DerivedMesh *dm = NULL; int val; - - val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); - + + if (ob != G.obedit) + { + dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + + val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); + } + else + { + dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); + + val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); + } + retval = retval || val; dm->release(dm); From 0de38996399ead639c0696e832fc20ffab8e362c Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sat, 11 Oct 2008 19:53:39 +0000 Subject: [PATCH 008/252] Bone sketching clean up Armature edit mode only (panel accessible in Armature header menu) Can be turned on or off Ctrl also snaps to edit bones' head and tail --- source/blender/blenkernel/BKE_global.h | 2 + source/blender/include/BIF_space.h | 1 + source/blender/src/drawview.c | 31 +++++++++ source/blender/src/editarmature_sketch.c | 83 +++++++++++++++++++++--- source/blender/src/header_view3d.c | 4 ++ 5 files changed, 113 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 3a2dca525b8..35f97e5a0ce 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -151,6 +151,8 @@ typedef struct Global { /* confusing... G.f and G.flags */ int flags; + + int bone_sketching; /* regroup with edbo into an EditArmature struct */ } Global; diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h index c7d0f4a1ada..a52b499e936 100644 --- a/source/blender/include/BIF_space.h +++ b/source/blender/include/BIF_space.h @@ -54,6 +54,7 @@ struct SpaceOops; #define VIEW3D_HANDLER_MULTIRES 5 #define VIEW3D_HANDLER_TRANSFORM 6 #define VIEW3D_HANDLER_GREASEPENCIL 7 +#define VIEW3D_HANDLER_BONESKETCH 8 /* ipo handler codes */ #define IPO_HANDLER_PROPERTIES 20 diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 7223de049f7..ce69c63ead2 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2268,6 +2268,34 @@ static void view3d_panel_transform_spaces(short cntrl) if(yco < 0) uiNewPanelHeight(block, height-yco); } +static void view3d_panel_bonesketch_spaces(short cntrl) +{ + uiBlock *block; +// uiBut *but; + int xco = 20, yco = 70, height = 140; +// int index; + + /* replace with check call to sketching lib */ + if (G.obedit && G.obedit->type == OB_ARMATURE) + { + block= uiNewBlock(&curarea->uiblocks, "view3d_panel_transform", UI_EMBOSS, UI_HELV, curarea->win); + uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); + uiSetPanelHandler(VIEW3D_HANDLER_TRANSFORM); // for close and esc + + if(uiNewPanel(curarea, block, "Bone Sketching", "View3d", 10, 230, 318, height)==0) return; + + uiNewPanelHeight(block, height); + + uiBlockBeginAlign(block); + + /* use real flag instead of 1 */ + uiDefButBitI(block, TOG, 1, B_REDR, "Use Bone Sketching", 10, 225, 150, 20, &G.bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + + uiBlockEndAlign(block); + + if(yco < 0) uiNewPanelHeight(block, height-yco); + } +} static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT { @@ -2659,6 +2687,9 @@ static void view3d_blockhandlers(ScrArea *sa) case VIEW3D_HANDLER_GREASEPENCIL: view3d_panel_gpencil(v3d->blockhandler[a+1]); break; + case VIEW3D_HANDLER_BONESKETCH: + view3d_panel_bonesketch_spaces(v3d->blockhandler[a+1]); + break; } /* clear action value for event */ v3d->blockhandler[a+1]= 0; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 21dbad003aa..8e542885d82 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -29,6 +29,7 @@ #include "DNA_view3d_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "DNA_armature_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -46,6 +47,7 @@ #include "BIF_screen.h" #include "BIF_space.h" #include "BIF_mywindow.h" +#include "BIF_editarmature.h" #include "blendef.h" #include "mydevice.h" @@ -87,6 +89,7 @@ typedef struct SK_Sketch } SK_Sketch; SK_Sketch *GLOBAL_sketch = NULL; +SK_Point boneSnap; /******************** PROTOTYPES ******************************/ @@ -580,6 +583,47 @@ SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist) return pt; } +SK_Point *sk_snapPointArmature(ListBase *ebones, short mval[2], int *dist) +{ + SK_Point *pt = NULL; + EditBone *bone; + + for (bone = ebones->first; bone; bone = bone->next) + { + short pval[2]; + int pdist; + + if ((bone->flag & BONE_CONNECTED) == 0) + { + project_short_noclip(bone->head, pval); + + pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); + + if (pdist < *dist) + { + *dist = pdist; + pt = &boneSnap; + VECCOPY(pt->p, bone->head); + pt->type = PT_EXACT; + } + } + + + project_short_noclip(bone->tail, pval); + + pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); + + if (pdist < *dist) + { + *dist = pdist; + pt = &boneSnap; + VECCOPY(pt->p, bone->tail); + pt->type = PT_EXACT; + } + } + + return pt; +} SK_Point *sk_snapPoint(SK_Sketch *sketch, short mval[2], int min_dist) { @@ -597,6 +641,16 @@ SK_Point *sk_snapPoint(SK_Sketch *sketch, short mval[2], int min_dist) } } + /* check on bones */ + { + SK_Point *spt = sk_snapPointArmature(&G.edbo, mval, &dist); + + if (spt != NULL) + { + pt = spt; + } + } + return pt; } @@ -984,26 +1038,39 @@ int sk_paint(SK_Sketch *sketch, short mbut) void BDR_drawSketch() { - if (GLOBAL_sketch != NULL) + if (G.bone_sketching & 1) { - sk_drawSketch(GLOBAL_sketch); + if (GLOBAL_sketch != NULL) + { + sk_drawSketch(GLOBAL_sketch); + } } } int BIF_paintSketch(short mbut) { - if (GLOBAL_sketch == NULL) + if (G.bone_sketching & 1) { - GLOBAL_sketch = sk_createSketch(); + if (GLOBAL_sketch == NULL) + { + GLOBAL_sketch = sk_createSketch(); + } + + return sk_paint(GLOBAL_sketch, mbut); + } + else + { + return 0; } - - return sk_paint(GLOBAL_sketch, mbut); } void BDR_queueDrawSketch() { - if (GLOBAL_sketch != NULL) + if (G.bone_sketching & 1) { - sk_queueRedrawSketch(GLOBAL_sketch); + if (GLOBAL_sketch != NULL) + { + sk_queueRedrawSketch(GLOBAL_sketch); + } } } diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 4cef7a1cb3e..bf907b11f54 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -3951,6 +3951,9 @@ static void do_view3d_edit_armaturemenu(void *arg, int event) case 22: /* separate */ separate_armature(); break; + case 23: /* bone sketching panel */ + add_blockhandler(curarea, VIEW3D_HANDLER_BONESKETCH, UI_PNL_UNSTOW); + break; } allqueue(REDRAWVIEW3D, 0); @@ -4027,6 +4030,7 @@ static uiBlock *view3d_edit_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_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Bone Sketching|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 23, ""); uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, view3d_edit_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, ""); uiDefIconTextBlockBut(block, view3d_edit_snapmenu, NULL, ICON_RIGHTARROW_THIN, "Snap", 0, yco-=20, 120, 19, ""); From 6d7353321e86cfed77ee389adaee1904a704bbb9 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 12 Oct 2008 17:33:03 +0000 Subject: [PATCH 009/252] First draft for converting sketches to armature. - New Convert button in the bone sketching float panel - Only adds straight bones between exact points (not continuous strokes) for now. --- source/blender/include/BIF_editarmature.h | 1 + source/blender/include/BIF_sketch.h | 1 + source/blender/src/drawview.c | 12 ++++- source/blender/src/editarmature.c | 17 +++--- source/blender/src/editarmature_sketch.c | 64 +++++++++++++++++++++++ 5 files changed, 87 insertions(+), 8 deletions(-) diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index d390b96f61f..7211d71fcb6 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -68,6 +68,7 @@ typedef struct EditBone } EditBone; +EditBone *addEditBone(char *name, struct ListBase *ebones, struct bArmature *arm); void adduplicate_armature(void); void addvert_armature(void); diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h index 41fac3da845..e3fb2ea1cfd 100644 --- a/source/blender/include/BIF_sketch.h +++ b/source/blender/include/BIF_sketch.h @@ -24,5 +24,6 @@ #define BIF_SKETCH_H int BIF_paintSketch(); +void BIF_convertSketch(); #endif /* BIF_SKETCH_H */ diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index ce69c63ead2..3c6cef21f5a 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -130,6 +130,7 @@ #include "BIF_resources.h" #include "BIF_retopo.h" #include "BIF_screen.h" +#include "BIF_sketch.h" #include "BIF_space.h" #ifdef WITH_VERSE @@ -2268,11 +2269,16 @@ static void view3d_panel_transform_spaces(short cntrl) if(yco < 0) uiNewPanelHeight(block, height-yco); } +static void convert_sketch_armature(void *arg1, void *arg2) +{ + BIF_convertSketch(); +} + static void view3d_panel_bonesketch_spaces(short cntrl) { uiBlock *block; -// uiBut *but; - int xco = 20, yco = 70, height = 140; + uiBut *but; + int yco = 70, height = 140; // int index; /* replace with check call to sketching lib */ @@ -2290,6 +2296,8 @@ static void view3d_panel_bonesketch_spaces(short cntrl) /* use real flag instead of 1 */ uiDefButBitI(block, TOG, 1, B_REDR, "Use Bone Sketching", 10, 225, 150, 20, &G.bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + but = uiDefBut(block, BUT, B_REDR, "Convert Sketch", 10,205,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); + uiButSetFunc(but, convert_sketch_armature, NULL, NULL); uiBlockEndAlign(block); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index d5e5b5a1c4a..2ab58512657 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -1969,17 +1969,14 @@ void undo_push_armature(char *name) /* **************** END EditMode stuff ********************** */ /* *************** Adding stuff in editmode *************** */ -/* default bone add, returns it selected, but without tail set */ -static EditBone *add_editbone(char *name) +EditBone *addEditBone(char *name, ListBase *ebones, bArmature *arm) { - bArmature *arm= G.obedit->data; - EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone"); BLI_strncpy(bone->name, name, 32); - unique_editbone_name(&G.edbo, bone->name); + unique_editbone_name(ebones, bone->name); - BLI_addtail(&G.edbo, bone); + BLI_addtail(ebones, bone); bone->flag |= BONE_TIPSEL; bone->weight= 1.0F; @@ -1996,6 +1993,14 @@ static EditBone *add_editbone(char *name) return bone; } +/* default bone add, returns it selected, but without tail set */ +static EditBone *add_editbone(char *name) +{ + bArmature *arm= G.obedit->data; + + return addEditBone(name, &G.edbo, arm); +} + static void add_primitive_bone(Object *ob, short newob) { float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3]; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 8e542885d82..e51fb92b4f4 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -883,7 +883,60 @@ void sk_initDrawData(SK_DrawData *dd) dd->previous_mval[1] = -1; dd->type = PT_EXACT; } +/********************************************/ +void sk_convertStroke(SK_Stroke *stk) +{ + bArmature *arm= G.obedit->data; + SK_Point *head; + EditBone *parent = NULL; + int i; + + head = NULL; + + for (i = 0; i < stk->nb_points; i++) + { + SK_Point *pt = stk->points + i; + + if (pt->type == PT_EXACT) + { + if (head == NULL) + { + head = pt; + } + else + { + EditBone *bone; + + bone = addEditBone("Bone", &G.edbo, arm); + + VECCOPY(bone->head, head->p); + VECCOPY(bone->tail, pt->p); + + if (parent != NULL) + { + bone->parent = parent; + bone->flag |= BONE_CONNECTED; + } + + parent = bone; + head = pt; + } + } + } +} + +void sk_convert(SK_Sketch *sketch) +{ + SK_Stroke *stk; + + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + sk_convertStroke(stk); + } + + BLI_freelistN(&sketch->strokes); +} /********************************************/ void sk_queueRedrawSketch(SK_Sketch *sketch) @@ -1047,6 +1100,17 @@ void BDR_drawSketch() } } +void BIF_convertSketch() +{ + if (G.bone_sketching & 1) + { + if (GLOBAL_sketch != NULL) + { + sk_convert(GLOBAL_sketch); + } + } +} + int BIF_paintSketch(short mbut) { if (G.bone_sketching & 1) From 4e7b736097551e75c5b8369b395d8e4a314260e5 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 12 Oct 2008 17:54:47 +0000 Subject: [PATCH 010/252] Multiply by armature inverse matrix to make sure converted bones are where they should be. --- source/blender/src/editarmature_sketch.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index e51fb92b4f4..f5c1c67a5db 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -890,10 +890,13 @@ void sk_convertStroke(SK_Stroke *stk) bArmature *arm= G.obedit->data; SK_Point *head; EditBone *parent = NULL; + float invmat[4][4]; /* move in caller function */ int i; head = NULL; + Mat4Invert(invmat, G.obedit->obmat); + for (i = 0; i < stk->nb_points; i++) { SK_Point *pt = stk->points + i; @@ -913,6 +916,9 @@ void sk_convertStroke(SK_Stroke *stk) VECCOPY(bone->head, head->p); VECCOPY(bone->tail, pt->p); + Mat4MulVecfl(invmat, bone->head); + Mat4MulVecfl(invmat, bone->tail); + if (parent != NULL) { bone->parent = parent; From af73c8ef420a1de075f6dd8c57db3ffeeaa96ff1 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 13 Oct 2008 23:41:38 +0000 Subject: [PATCH 011/252] Skeleton Sketching - Delete Sketch button - During continuous strokes, when moving out from and back into an embeding, interpolate depth of the stroke like is done when snapping --- source/blender/include/BIF_sketch.h | 1 + source/blender/src/drawview.c | 9 ++- source/blender/src/editarmature_sketch.c | 90 +++++++++++++++++++----- 3 files changed, 80 insertions(+), 20 deletions(-) diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h index e3fb2ea1cfd..cc8e7a2e256 100644 --- a/source/blender/include/BIF_sketch.h +++ b/source/blender/include/BIF_sketch.h @@ -25,5 +25,6 @@ int BIF_paintSketch(); void BIF_convertSketch(); +void BIF_deleteSketch(); #endif /* BIF_SKETCH_H */ diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 3c6cef21f5a..6da77baefe6 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2269,6 +2269,11 @@ static void view3d_panel_transform_spaces(short cntrl) if(yco < 0) uiNewPanelHeight(block, height-yco); } +static void delete_sketch_armature(void *arg1, void *arg2) +{ + BIF_deleteSketch(); +} + static void convert_sketch_armature(void *arg1, void *arg2) { BIF_convertSketch(); @@ -2296,8 +2301,10 @@ static void view3d_panel_bonesketch_spaces(short cntrl) /* use real flag instead of 1 */ uiDefButBitI(block, TOG, 1, B_REDR, "Use Bone Sketching", 10, 225, 150, 20, &G.bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); - but = uiDefBut(block, BUT, B_REDR, "Convert Sketch", 10,205,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); + but = uiDefBut(block, BUT, B_REDR, "Convert", 10,205,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); uiButSetFunc(but, convert_sketch_armature, NULL, NULL); + but = uiDefBut(block, BUT, B_REDR, "Delete", 10,185,150,20, 0, 0, 0, 0, 0, "Delete sketch"); + uiButSetFunc(but, delete_sketch_armature, NULL, NULL); uiBlockEndAlign(block); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index f5c1c67a5db..0a611c4b0fc 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -58,10 +58,18 @@ typedef enum SK_PType PT_EXACT, } SK_PType; +typedef enum Method +{ + PT_EMBED, + PT_SNAP, + PT_PROJECT, +} SK_PMode; + typedef struct SK_Point { float p[3]; SK_PType type; + SK_PMode mode; } SK_Point; typedef struct SK_Stroke @@ -717,14 +725,38 @@ float sk_distanceDepth(float p1[3], float p2[3]) return distance; } +void sk_interpolateDepth(SK_Stroke *stk, int start, int end, float length, float distance) +{ + float progress = 0; + int i; + + progress = VecLenf(stk->points[start].p, stk->points[start - 1].p); + + for (i = start; i <= end; i++) + { + float ray_start[3], ray_normal[3]; + float delta = VecLenf(stk->points[i].p, stk->points[i + 1].p); + short pval[2]; + + project_short_noclip(stk->points[i].p, pval); + viewray(pval, ray_start, ray_normal); + + VecMulf(ray_normal, distance * progress / length); + VecAddf(stk->points[i].p, stk->points[i].p, ray_normal); + + progress += delta ; + } +} + void sk_addStrokeSnapPoint(SK_Stroke *stk, SK_DrawData *dd, SK_Point *snap_pt) { SK_Point pt; float distance; float length; - int i, j, total; + int i, total; pt.type = PT_EXACT; + pt.mode = PT_SNAP; sk_projectPaintData(stk, dd, pt.p); @@ -745,24 +777,9 @@ void sk_addStrokeSnapPoint(SK_Stroke *stk, SK_DrawData *dd, SK_Point *snap_pt) if (total > 1) { - float progress = length - VecLenf(stk->points[stk->nb_points - 2].p, stk->points[stk->nb_points - 1].p); - distance = sk_distanceDepth(snap_pt->p, stk->points[i].p); - for (j = 1, i = stk->nb_points - 2; j < total; j++, i--) - { - float ray_start[3], ray_normal[3]; - float delta = VecLenf(stk->points[i].p, stk->points[i - 1].p); - short pval[2]; - - project_short_noclip(stk->points[i].p, pval); - viewray(pval, ray_start, ray_normal); - - VecMulf(ray_normal, distance * progress / length); - VecAddf(stk->points[i].p, stk->points[i].p, ray_normal); - - progress -= delta ; - } + sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance); } VECCOPY(stk->points[stk->nb_points - 1].p, snap_pt->p); @@ -773,6 +790,7 @@ void sk_addStrokeDrawPoint(SK_Stroke *stk, SK_DrawData *dd) SK_Point pt; pt.type = dd->type; + pt.mode = PT_PROJECT; sk_projectPaintData(stk, dd, pt.p); @@ -849,12 +867,37 @@ void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) else { SK_Point pt; + float length, distance; + int total; + int i; pt.type = dd->type; + pt.mode = PT_EMBED; - VECCOPY(pt.p, p); - + sk_projectPaintData(stk, dd, pt.p); sk_appendStrokePoint(stk, &pt); + + /* update all previous point to give smooth Z progresion */ + total = 0; + length = 0; + for (i = stk->nb_points - 2; i > 0; i--) + { + length += VecLenf(stk->points[i].p, stk->points[i + 1].p); + total++; + if (stk->points[i].mode == PT_EMBED || stk->points[i].type == PT_EXACT) + { + break; + } + } + + if (total > 1) + { + distance = sk_distanceDepth(p, stk->points[i].p); + + sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance); + } + + VECCOPY(stk->points[stk->nb_points - 1].p, p); } BLI_freelistN(&depth_peels); @@ -1106,6 +1149,15 @@ void BDR_drawSketch() } } +void BIF_deleteSketch() +{ + if (GLOBAL_sketch != NULL) + { + sk_freeSketch(GLOBAL_sketch); + GLOBAL_sketch = NULL; + } +} + void BIF_convertSketch() { if (G.bone_sketching & 1) From e9b40803543f5ef894520f3449cc3598e01efbab Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 14 Oct 2008 01:25:30 +0000 Subject: [PATCH 012/252] Embed point looks at last point, whether it was part of a continuous stroke or not (gives better results for poly lines) Stroke selection (LMB and Shift-LMB). Selected strokes drawn in red. Eventually convert and delete will work on selection. --- source/blender/include/BDR_sketch.h | 1 + source/blender/src/editarmature_sketch.c | 101 +++++++++++++++++++++-- source/blender/src/view.c | 9 +- 3 files changed, 102 insertions(+), 9 deletions(-) diff --git a/source/blender/include/BDR_sketch.h b/source/blender/include/BDR_sketch.h index 1de53ea2d27..55d6e1d80cf 100644 --- a/source/blender/include/BDR_sketch.h +++ b/source/blender/include/BDR_sketch.h @@ -25,5 +25,6 @@ void BDR_queueDrawSketch(); void BDR_drawSketch(); +void BDR_drawSketchNames(); #endif /* BDR_SKETCH_H */ diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 0a611c4b0fc..3a70a13feea 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -79,6 +79,7 @@ typedef struct SK_Stroke SK_Point *points; int nb_points; int buf_size; + int selected; } SK_Stroke; #define SK_Stroke_BUFFER_INIT_SIZE 20 @@ -370,6 +371,7 @@ SK_Stroke* sk_createStroke() stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke"); + stk->selected = 0; stk->nb_points = 0; stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE; @@ -523,11 +525,23 @@ SK_Point *sk_lastStrokePoint(SK_Stroke *stk) return pt; } -void sk_drawStroke(SK_Stroke *stk) +void sk_drawStroke(SK_Stroke *stk, int id) { int i; - glColor3f(1, 0.5, 0); + if (id != -1) + { + glLoadName(id); + } + + if (stk->selected) + { + glColor3f(1, 0, 0); + } + else + { + glColor3f(1, 0.5, 0); + } glBegin(GL_LINE_STRIP); for (i = 0; i < stk->nb_points; i++) @@ -810,7 +824,7 @@ void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) peelObjects(&depth_peels, dd->mval); - if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) + if (stk->nb_points > 0) // && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) { last_pt = stk->points + (stk->nb_points - 1); } @@ -988,6 +1002,51 @@ void sk_convert(SK_Sketch *sketch) } /********************************************/ +void sk_selectStroke(SK_Sketch *sketch) +{ + SK_Stroke *stk = NULL; + unsigned int buffer[MAXPICKBUF]; + short hits, mval[2]; + + persp(PERSP_VIEW); + + getmouseco_areawin(mval); + hits = view3d_opengl_select(buffer, MAXPICKBUF, mval[0]-5, mval[1]-5, mval[0]+5, mval[1]+5); + if(hits==0) + hits = view3d_opengl_select(buffer, MAXPICKBUF, mval[0]-12, mval[1]-12, mval[0]+12, mval[1]+12); + + if (hits>0) + { + int besthitresult = -1; + + if(hits == 1) { + besthitresult = buffer[3]; + } + else { + besthitresult = buffer[3]; + /* loop and get best hit */ + } + + if (besthitresult != -1) + { + SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult); + + selected_stk->selected ^= 1; + + if ((G.qual & LR_SHIFTKEY) == 0) + { + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + if (stk != selected_stk) + { + stk->selected = 0; + } + } + } + } + } +} + void sk_queueRedrawSketch(SK_Sketch *sketch) { if (sketch->active_stroke != NULL) @@ -1001,7 +1060,7 @@ void sk_queueRedrawSketch(SK_Sketch *sketch) } } -void sk_drawSketch(SK_Sketch *sketch) +void sk_drawSketch(SK_Sketch *sketch, int with_names) { SK_Stroke *stk; @@ -1009,10 +1068,21 @@ void sk_drawSketch(SK_Sketch *sketch) glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE)); glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE)); - - for (stk = sketch->strokes.first; stk; stk = stk->next) + + if (with_names) { - sk_drawStroke(stk); + int id; + for (id = 0, stk = sketch->strokes.first; stk; id++, stk = stk->next) + { + sk_drawStroke(stk, id); + } + } + else + { + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + sk_drawStroke(stk, -1); + } } if (sketch->active_stroke != NULL) @@ -1132,11 +1202,26 @@ int sk_paint(SK_Sketch *sketch, short mbut) sk_endStroke(sketch); allqueue(REDRAWVIEW3D, 0); } + else + { + sk_selectStroke(sketch); + allqueue(REDRAWVIEW3D, 0); + } } return retval; } +void BDR_drawSketchNames() +{ + if (G.bone_sketching & 1) + { + if (GLOBAL_sketch != NULL) + { + sk_drawSketch(GLOBAL_sketch, 1); + } + } +} void BDR_drawSketch() { @@ -1144,7 +1229,7 @@ void BDR_drawSketch() { if (GLOBAL_sketch != NULL) { - sk_drawSketch(GLOBAL_sketch); + sk_drawSketch(GLOBAL_sketch, 0); } } } diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 6f558152ac7..1480dd557e3 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -1883,7 +1883,14 @@ short view3d_opengl_select(unsigned int *buffer, unsigned int bufsize, short x1 draw_object(BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); } else if ((G.obedit && G.obedit->type==OB_ARMATURE)) { - draw_object(BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); + if (G.bone_sketching & 1) + { + BDR_drawSketchNames(); + } + else + { + draw_object(BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); + } } else { Base *base; From 718c0d5d70c233e3d12899f32631144d2362cf16 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 14 Oct 2008 20:03:21 +0000 Subject: [PATCH 013/252] Convert and Delete only selected strokes. Convert no longer remove converted strokes. Akey -> select all/deselect all strokes --- source/blender/blenkernel/BKE_global.h | 3 - source/blender/include/BIF_sketch.h | 4 +- source/blender/makesdna/DNA_scene_types.h | 8 +- source/blender/src/drawview.c | 2 +- source/blender/src/editarmature_sketch.c | 174 ++++++++++++++++------ source/blender/src/space.c | 11 +- source/blender/src/view.c | 3 +- 7 files changed, 153 insertions(+), 52 deletions(-) diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 35f97e5a0ce..bb474d3f8c8 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -151,9 +151,6 @@ typedef struct Global { /* confusing... G.f and G.flags */ int flags; - - int bone_sketching; /* regroup with edbo into an EditArmature struct */ - } Global; /* **************** GLOBAL ********************* */ diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h index cc8e7a2e256..1861a938685 100644 --- a/source/blender/include/BIF_sketch.h +++ b/source/blender/include/BIF_sketch.h @@ -23,8 +23,10 @@ #ifndef BIF_SKETCH_H #define BIF_SKETCH_H -int BIF_paintSketch(); +int BIF_paintSketch(short mbut); void BIF_convertSketch(); void BIF_deleteSketch(); +void BIF_selectAllSketch(int mode); /* -1: deselect, 0: select, 1: toggle */ +int BIF_validSketchMode(); #endif /* BIF_SKETCH_H */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index a5eaf222941..3dec57680c7 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -438,9 +438,12 @@ typedef struct ToolSettings { char skgen_postpro_passes; char skgen_subdivisions[3]; + /* Skeleton Sketching */ + char bone_sketching; + /* Alt+RMB option */ char edge_mode; - char pad3[4]; + char pad3[3]; } ToolSettings; /* Used by all brushes to store their properties, which can be directly set @@ -854,6 +857,9 @@ typedef struct Scene { #define SKGEN_AVERAGE 1 #define SKGEN_SHARPEN 2 +/* toolsettings->bone_sketching */ +#define BONE_SKETCHING 1 + #ifdef __cplusplus } #endif diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 6da77baefe6..74b12a5b6e8 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2300,7 +2300,7 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockBeginAlign(block); /* use real flag instead of 1 */ - uiDefButBitI(block, TOG, 1, B_REDR, "Use Bone Sketching", 10, 225, 150, 20, &G.bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, 225, 150, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); but = uiDefBut(block, BUT, B_REDR, "Convert", 10,205,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); uiButSetFunc(but, convert_sketch_armature, NULL, NULL); but = uiDefBut(block, BUT, B_REDR, "Delete", 10,185,150,20, 0, 0, 0, 0, 0, "Delete sketch"); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 3a70a13feea..1682108d060 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -48,6 +48,7 @@ #include "BIF_space.h" #include "BIF_mywindow.h" #include "BIF_editarmature.h" +#include "BIF_sketch.h" #include "blendef.h" #include "mydevice.h" @@ -100,6 +101,8 @@ typedef struct SK_Sketch SK_Sketch *GLOBAL_sketch = NULL; SK_Point boneSnap; +#define SNAP_MIN_DISTANCE 12 + /******************** PROTOTYPES ******************************/ void sk_freeStroke(SK_Stroke *stk); @@ -762,13 +765,18 @@ void sk_interpolateDepth(SK_Stroke *stk, int start, int end, float length, float } } -void sk_addStrokeSnapPoint(SK_Stroke *stk, SK_DrawData *dd, SK_Point *snap_pt) +int sk_addStrokeSnapPoint(SK_Stroke *stk, SK_DrawData *dd, SK_Point *snap_pt) { SK_Point pt; float distance; float length; int i, total; + if (snap_pt == NULL) + { + return 0; + } + pt.type = PT_EXACT; pt.mode = PT_SNAP; @@ -797,9 +805,11 @@ void sk_addStrokeSnapPoint(SK_Stroke *stk, SK_DrawData *dd, SK_Point *snap_pt) } VECCOPY(stk->points[stk->nb_points - 1].p, snap_pt->p); + + return 1; } -void sk_addStrokeDrawPoint(SK_Stroke *stk, SK_DrawData *dd) +int sk_addStrokeDrawPoint(SK_Stroke *stk, SK_DrawData *dd) { SK_Point pt; @@ -809,15 +819,18 @@ void sk_addStrokeDrawPoint(SK_Stroke *stk, SK_DrawData *dd) sk_projectPaintData(stk, dd, pt.p); sk_appendStrokePoint(stk, &pt); + + return 1; } -void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) +int sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) { ListBase depth_peels; SK_DepthPeel *p1, *p2; SK_Point *last_pt = NULL; float dist = FLT_MAX; float p[3]; + int point_added = 0; depth_peels.first = depth_peels.last = NULL; @@ -874,11 +887,7 @@ void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) } } - if (dist == FLT_MAX) - { - sk_addStrokeDrawPoint(stk, dd); - } - else + if (dist != FLT_MAX) { SK_Point pt; float length, distance; @@ -912,9 +921,13 @@ void sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) } VECCOPY(stk->points[stk->nb_points - 1].p, p); + + point_added = 1; } BLI_freelistN(&depth_peels); + + return point_added; } void sk_endContinuousStroke(SK_Stroke *stk) @@ -995,16 +1008,68 @@ void sk_convert(SK_Sketch *sketch) for (stk = sketch->strokes.first; stk; stk = stk->next) { - sk_convertStroke(stk); + if (stk->selected == 1) + { + sk_convertStroke(stk); + } } - - BLI_freelistN(&sketch->strokes); } /********************************************/ -void sk_selectStroke(SK_Sketch *sketch) +void sk_deleteStrokes(SK_Sketch *sketch) +{ + SK_Stroke *stk, *next; + + for (stk = sketch->strokes.first; stk; stk = next) + { + next = stk->next; + + if (stk->selected == 1) + { + BLI_remlink(&sketch->strokes, stk); + sk_freeStroke(stk); + } + } +} + +void sk_selectAllSketch(SK_Sketch *sketch, int mode) { SK_Stroke *stk = NULL; + + if (mode == -1) + { + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + stk->selected = 0; + } + } + else if (mode == 0) + { + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + stk->selected = 1; + } + } + else if (mode == 1) + { + int selected = 1; + + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + selected &= stk->selected; + } + + selected ^= 1; + + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + stk->selected = selected; + } + } +} + +void sk_selectStroke(SK_Sketch *sketch) +{ unsigned int buffer[MAXPICKBUF]; short hits, mval[2]; @@ -1031,18 +1096,18 @@ void sk_selectStroke(SK_Sketch *sketch) { SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult); - selected_stk->selected ^= 1; - if ((G.qual & LR_SHIFTKEY) == 0) { - for (stk = sketch->strokes.first; stk; stk = stk->next) - { - if (stk != selected_stk) - { - stk->selected = 0; - } - } + sk_selectAllSketch(sketch, -1); + + selected_stk->selected = 1; } + else + { + selected_stk->selected ^= 1; + } + + } } } @@ -1110,7 +1175,7 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) if (G.qual & LR_CTRLKEY) { - SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, 30); + SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, SNAP_MIN_DISTANCE); if (snap_pt != NULL) { @@ -1152,26 +1217,22 @@ int sk_paint(SK_Sketch *sketch, short mbut) /* only add current point to buffer if mouse moved (otherwise wait until it does) */ if (sk_stroke_filtermval(&dd)) { + int point_added = 0; + if (G.qual & LR_CTRLKEY) { - SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, 30); - - if (snap_pt != NULL) - { - sk_addStrokeSnapPoint(sketch->active_stroke, &dd, snap_pt); - } - else - { - sk_addStrokeDrawPoint(sketch->active_stroke, &dd); - } + SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, SNAP_MIN_DISTANCE); + point_added = sk_addStrokeSnapPoint(sketch->active_stroke, &dd, snap_pt); } - else if (G.qual & LR_SHIFTKEY) + + if (point_added == 0 && G.qual & LR_SHIFTKEY) { - sk_addStrokeEmbedPoint(sketch->active_stroke, &dd); + point_added = sk_addStrokeEmbedPoint(sketch->active_stroke, &dd); } - else + + if (point_added == 0) { - sk_addStrokeDrawPoint(sketch->active_stroke, &dd); + point_added = sk_addStrokeDrawPoint(sketch->active_stroke, &dd); } sk_updateDrawData(&dd); @@ -1214,7 +1275,7 @@ int sk_paint(SK_Sketch *sketch, short mbut) void BDR_drawSketchNames() { - if (G.bone_sketching & 1) + if (BIF_validSketchMode()) { if (GLOBAL_sketch != NULL) { @@ -1225,7 +1286,7 @@ void BDR_drawSketchNames() void BDR_drawSketch() { - if (G.bone_sketching & 1) + if (BIF_validSketchMode()) { if (GLOBAL_sketch != NULL) { @@ -1236,16 +1297,15 @@ void BDR_drawSketch() void BIF_deleteSketch() { - if (GLOBAL_sketch != NULL) + if (BIF_validSketchMode()) { - sk_freeSketch(GLOBAL_sketch); - GLOBAL_sketch = NULL; + sk_deleteStrokes(GLOBAL_sketch); } } void BIF_convertSketch() { - if (G.bone_sketching & 1) + if (BIF_validSketchMode()) { if (GLOBAL_sketch != NULL) { @@ -1256,7 +1316,7 @@ void BIF_convertSketch() int BIF_paintSketch(short mbut) { - if (G.bone_sketching & 1) + if (BIF_validSketchMode()) { if (GLOBAL_sketch == NULL) { @@ -1273,7 +1333,7 @@ int BIF_paintSketch(short mbut) void BDR_queueDrawSketch() { - if (G.bone_sketching & 1) + if (BIF_validSketchMode()) { if (GLOBAL_sketch != NULL) { @@ -1281,3 +1341,29 @@ void BDR_queueDrawSketch() } } } + +void BIF_selectAllSketch(int mode) +{ + if (BIF_validSketchMode()) + { + if (GLOBAL_sketch != NULL) + { + sk_selectAllSketch(GLOBAL_sketch, mode); + allqueue(REDRAWVIEW3D, 0); + } + } +} + +int BIF_validSketchMode() +{ + if (G.obedit && + G.obedit->type == OB_ARMATURE && + G.scene->toolsettings->bone_sketching & BONE_SKETCHING) + { + return 1; + } + else + { + return 0; + } +} diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 17e96c00f79..99939d87b30 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1899,7 +1899,16 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.obedit->type==OB_LATTICE) deselectall_Latt(); else if(G.obedit->type==OB_ARMATURE) - deselectall_armature(1, 1); /* 1 == toggle */ + { + if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING) + { + BIF_selectAllSketch(1); + } + else + { + deselectall_armature(1, 1); /* 1 == toggle */ + } + } } else if (ob && (ob->flag & OB_POSEMODE)){ deselectall_posearmature(ob, 1, 1); diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 1480dd557e3..c045703104a 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -83,6 +83,7 @@ #include "BDR_drawobject.h" /* For draw_object */ #include "BDR_editface.h" /* For minmax_tface */ #include "BDR_sculptmode.h" +#include "BDR_sketch.h" #include "mydevice.h" #include "blendef.h" @@ -1883,7 +1884,7 @@ short view3d_opengl_select(unsigned int *buffer, unsigned int bufsize, short x1 draw_object(BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); } else if ((G.obedit && G.obedit->type==OB_ARMATURE)) { - if (G.bone_sketching & 1) + if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING) { BDR_drawSketchNames(); } From 9dec209b7e23078a25a54df3673702a006e84762 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 15 Oct 2008 19:31:32 +0000 Subject: [PATCH 014/252] Subdivision schemes for continuous strokes: Subdivide in equal length bones Subdivide by correlation (linearity limits) Code borrowed in parts from the skeleton generator. Will be eventually reuse code more efficiently. --- source/blender/src/drawview.c | 10 + source/blender/src/editarmature_sketch.c | 233 ++++++++++++++++++++++- 2 files changed, 235 insertions(+), 8 deletions(-) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 74b12a5b6e8..386cf30b61f 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2305,6 +2305,16 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiButSetFunc(but, convert_sketch_armature, NULL, NULL); but = uiDefBut(block, BUT, B_REDR, "Delete", 10,185,150,20, 0, 0, 0, 0, 0, "Delete sketch"); uiButSetFunc(but, delete_sketch_armature, NULL, NULL); + + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + + uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_DIFF, "Length", 10, 155, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs in bones of equal length"); + uiDefButF(block, NUM, B_DIFF, "L:", 70, 155, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); + + uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_DIFF, "Correlation", 10, 135, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation"); + uiDefButF(block, NUM, B_DIFF, "T:", 70, 135, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); uiBlockEndAlign(block); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 1682108d060..1e633b9b0c0 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -21,6 +21,7 @@ */ #include +#include #include "MEM_guardedalloc.h" @@ -837,7 +838,7 @@ int sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) peelObjects(&depth_peels, dd->mval); - if (stk->nb_points > 0) // && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) + if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) { last_pt = stk->points + (stk->nb_points - 1); } @@ -955,12 +956,202 @@ void sk_initDrawData(SK_DrawData *dd) } /********************************************/ +float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], float n[3]) +{ + int len = 2 + abs(end - start); + + if (len > 2) + { + float avg_t = 0.0f; + float s_t = 0.0f; + float s_xyz = 0.0f; + int i; + + /* First pass, calculate average */ + for (i = start; i <= end; i++) + { + float v[3]; + + VecSubf(v, stk->points[i].p, v0); + avg_t += Inpf(v, n); + } + + avg_t /= Inpf(n, n); + avg_t += 1.0f; /* adding start (0) and end (1) values */ + avg_t /= len; + + /* Second pass, calculate s_xyz and s_t */ + for (i = start; i <= end; i++) + { + float v[3], d[3]; + float dt; + + VecSubf(v, stk->points[i].p, v0); + Projf(d, v, n); + VecSubf(v, v, d); + + dt = VecLength(d) - avg_t; + + s_t += dt * dt; + s_xyz += Inpf(v, v); + } + + /* adding start(0) and end(1) values to s_t */ + s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t); + + return 1.0f - s_xyz / s_t; + } + else + { + return 1.0f; + } +} + +EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, float invmat[][4]) +{ + bArmature *arm= G.obedit->data; + EditBone *lastBone = NULL; + float n[3]; + float CORRELATION_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit; + + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) + { + EditBone *child = NULL; + EditBone *parent = NULL; + int boneStart = start; + int i; + + parent = addEditBone("Bone", &G.edbo, arm); + VECCOPY(parent->head, stk->points[start].p); + Mat4MulVecfl(invmat, parent->head); + + for (i = start + 1; i < end; i++) + { + /* Calculate normal */ + VecSubf(n, stk->points[i].p, parent->head); + + if (calcStrokeCorrelation(stk, boneStart, i, parent->head, n) < CORRELATION_THRESHOLD) + { + VECCOPY(parent->tail, stk->points[i - 1].p); + + child = addEditBone("Bone", &G.edbo, arm); + VECCOPY(child->head, parent->tail); + Mat4MulVecfl(invmat, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED; + + parent = child; // new child is next parent + boneStart = i; // start next bone from current index + } + } + + VECCOPY(parent->tail, stk->points[end].p); + Mat4MulVecfl(invmat, parent->tail); + lastBone = parent; + } + + return lastBone; +} + +EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float invmat[][4]) +{ + bArmature *arm= G.obedit->data; + EditBone *lastBone = NULL; + + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + { + EditBone *child = NULL; + EditBone *parent = NULL; + float lengthLimit = G.scene->toolsettings->skgen_length_limit; + int i; + int same = 0; + + parent = addEditBone("Bone", &G.edbo, arm); + VECCOPY(parent->head, stk->points[start].p); + + i = start + 1; + while (i < end) + { + float *vec0 = stk->points[i - 1].p; + float *vec1 = stk->points[i].p; + + /* If lengthLimit hits the current segment */ + if (VecLenf(vec1, parent->head) > lengthLimit) + { + if (same == 0) + { + float dv[3], off[3]; + float a, b, c, f; + + /* Solve quadratic distance equation */ + VecSubf(dv, vec1, vec0); + a = Inpf(dv, dv); + + VecSubf(off, vec0, parent->head); + b = 2 * Inpf(dv, off); + + c = Inpf(off, off) - (lengthLimit * lengthLimit); + + f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a); + + //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); + + if (isnan(f) == 0 && f < 1.0f) + { + VECCOPY(parent->tail, dv); + VecMulf(parent->tail, f); + VecAddf(parent->tail, parent->tail, vec0); + } + else + { + VECCOPY(parent->tail, vec1); + } + } + else + { + float dv[3]; + + VecSubf(dv, vec1, vec0); + Normalize(dv); + + VECCOPY(parent->tail, dv); + VecMulf(parent->tail, lengthLimit); + VecAddf(parent->tail, parent->tail, parent->head); + } + + /* put head in correct space */ + Mat4MulVecfl(invmat, parent->head); + + child = addEditBone("Bone", &G.edbo, arm); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED; + + parent = child; // new child is next parent + + same = 1; // mark as same + } + else + { + i++; + same = 0; // Reset same + } + } + VECCOPY(parent->tail, stk->points[end].p); + Mat4MulVecfl(invmat, parent->tail); + lastBone = parent; + } + + return lastBone; +} + void sk_convertStroke(SK_Stroke *stk) { bArmature *arm= G.obedit->data; SK_Point *head; EditBone *parent = NULL; float invmat[4][4]; /* move in caller function */ + int head_index = 0; int i; head = NULL; @@ -975,27 +1166,53 @@ void sk_convertStroke(SK_Stroke *stk) { if (head == NULL) { + head_index = i; head = pt; } else { - EditBone *bone; + EditBone *bone = NULL; + EditBone *new_parent; - bone = addEditBone("Bone", &G.edbo, arm); + if (i - head_index > 1) + { + bone = subdivideStrokeByCorrelation(stk, head_index, i, invmat); + + if (bone == NULL) + { + bone = subdivideStrokeByLength(stk, head_index, i, invmat); + } + } - VECCOPY(bone->head, head->p); - VECCOPY(bone->tail, pt->p); + if (bone == NULL) + { + bone = addEditBone("Bone", &G.edbo, arm); + + VECCOPY(bone->head, head->p); + VECCOPY(bone->tail, pt->p); + + Mat4MulVecfl(invmat, bone->head); + Mat4MulVecfl(invmat, bone->tail); + } - Mat4MulVecfl(invmat, bone->head); - Mat4MulVecfl(invmat, bone->tail); + new_parent = bone; + bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + /* move to end of chain */ + while (bone->parent != NULL) + { + bone = bone->parent; + bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; + } + if (parent != NULL) { bone->parent = parent; bone->flag |= BONE_CONNECTED; } - parent = bone; + parent = new_parent; + head_index = i; head = pt; } } From 005d7a2a9b4a60095df83c486e831cdf85f997a0 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 15 Oct 2008 21:25:42 +0000 Subject: [PATCH 015/252] Color fade out to indicate the direction of a stroke. --- source/blender/src/editarmature_sketch.c | 73 +++++++++++++++--------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 1e633b9b0c0..2367660d48c 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -536,37 +536,58 @@ void sk_drawStroke(SK_Stroke *stk, int id) if (id != -1) { glLoadName(id); - } - - if (stk->selected) - { - glColor3f(1, 0, 0); - } - else - { - glColor3f(1, 0.5, 0); - } - glBegin(GL_LINE_STRIP); - - for (i = 0; i < stk->nb_points; i++) - { - glVertex3fv(stk->points[i].p); - } - - glEnd(); - - glColor3f(0, 0, 0); - glBegin(GL_POINTS); - - for (i = 0; i < stk->nb_points; i++) - { - if (stk->points[i].type == PT_EXACT) + + glBegin(GL_LINE_STRIP); + + for (i = 0; i < stk->nb_points; i++) { glVertex3fv(stk->points[i].p); } + + glEnd(); + } + else + { + float r, g, b; + + if (stk->selected) + { + r = 1; + g = 0; + b = 0; + } + else + { + r = 1; + g = 0.5; + b = 0; + } + + glBegin(GL_LINE_STRIP); - glEnd(); + for (i = 0; i < stk->nb_points; i++) + { + float f = (float)i / (float)stk->nb_points; + glColor3f(r + (1 - r) * f, g + (1 - g) * f, b + (1 - b) * f); + glVertex3fv(stk->points[i].p); + } + + glEnd(); + + glColor3f(0, 0, 0); + glBegin(GL_POINTS); + + for (i = 0; i < stk->nb_points; i++) + { + if (stk->points[i].type == PT_EXACT) + { + glVertex3fv(stk->points[i].p); + } + } + + glEnd(); + } // glColor3f(1, 1, 1); // glBegin(GL_POINTS); From 265dc12d0ae2c7d0fc78e6b1898133c71a708df4 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 16 Oct 2008 21:48:35 +0000 Subject: [PATCH 016/252] First draft for sketching gestures. Destures are done with RMB drag ESC can now also be used to end a polyline. --- source/blender/include/BIF_sketch.h | 1 + source/blender/src/editarmature_sketch.c | 126 +++++++++++++++++++---- source/blender/src/space.c | 6 +- 3 files changed, 111 insertions(+), 22 deletions(-) diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h index 1861a938685..b9fd5d35d7b 100644 --- a/source/blender/include/BIF_sketch.h +++ b/source/blender/include/BIF_sketch.h @@ -24,6 +24,7 @@ #define BIF_SKETCH_H int BIF_paintSketch(short mbut); +void BIF_endStrokeSketch(); void BIF_convertSketch(); void BIF_deleteSketch(); void BIF_selectAllSketch(int mode); /* -1: deselect, 0: select, 1: toggle */ diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 2367660d48c..cb06366bc96 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -97,6 +97,7 @@ typedef struct SK_Sketch { ListBase strokes; SK_Stroke *active_stroke; + SK_Stroke *gesture; } SK_Sketch; SK_Sketch *GLOBAL_sketch = NULL; @@ -351,6 +352,7 @@ SK_Sketch* sk_createSketch() sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch"); sketch->active_stroke = NULL; + sketch->gesture = NULL; sketch->strokes.first = NULL; sketch->strokes.last = NULL; @@ -529,7 +531,7 @@ SK_Point *sk_lastStrokePoint(SK_Stroke *stk) return pt; } -void sk_drawStroke(SK_Stroke *stk, int id) +void sk_drawStroke(SK_Stroke *stk, int id, float rgb[3]) { int i; @@ -549,28 +551,18 @@ void sk_drawStroke(SK_Stroke *stk, int id) } else { - float r, g, b; + float d_rgb[3] = {1, 1, 1}; - if (stk->selected) - { - r = 1; - g = 0; - b = 0; - } - else - { - r = 1; - g = 0.5; - b = 0; - } + VecSubf(d_rgb, d_rgb, rgb); + VecMulf(d_rgb, 1.0f / (float)stk->nb_points); glBegin(GL_LINE_STRIP); for (i = 0; i < stk->nb_points; i++) { - float f = (float)i / (float)stk->nb_points; - glColor3f(r + (1 - r) * f, g + (1 - g) * f, b + (1 - b) * f); + glColor3fv(rgb); glVertex3fv(stk->points[i].p); + VecAddf(rgb, rgb, d_rgb); } glEnd(); @@ -1377,17 +1369,26 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) int id; for (id = 0, stk = sketch->strokes.first; stk; id++, stk = stk->next) { - sk_drawStroke(stk, id); + sk_drawStroke(stk, id, NULL); } } else { + float selected_rgb[3] = {1, 0, 0}; + float unselected_rgb[3] = {1, 0.5, 0}; + for (stk = sketch->strokes.first; stk; stk = stk->next) { - sk_drawStroke(stk, -1); + sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb)); } } + if (sketch->gesture != NULL) + { + float gesture_rgb[3] = {0, 0.5, 1}; + sk_drawStroke(sketch->gesture, -1, gesture_rgb); + } + if (sketch->active_stroke != NULL) { SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); @@ -1489,7 +1490,7 @@ int sk_paint(SK_Sketch *sketch, short mbut) /* do mouse checking at the end, so don't check twice, and potentially * miss a short tap */ - } while (get_mbut() & LEFTMOUSE); + } while (get_mbut() & L_MOUSE); sk_endContinuousStroke(sketch->active_stroke); sk_filterLastContinuousStroke(sketch->active_stroke); @@ -1503,7 +1504,75 @@ int sk_paint(SK_Sketch *sketch, short mbut) } else { - sk_selectStroke(sketch); + SK_DrawData dd; + sketch->gesture = sk_createStroke(); + + sk_initDrawData(&dd); + + /* paint loop */ + do { + /* get current user input */ + getmouseco_areawin(dd.mval); + + /* only add current point to buffer if mouse moved (otherwise wait until it does) */ + if (sk_stroke_filtermval(&dd)) { + int point_added = 0; + + if (G.qual & LR_CTRLKEY) + { + SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, SNAP_MIN_DISTANCE); + point_added = sk_addStrokeSnapPoint(sketch->gesture, &dd, snap_pt); + } + + if (point_added == 0 && G.qual & LR_SHIFTKEY) + { + point_added = sk_addStrokeEmbedPoint(sketch->gesture, &dd); + } + + if (point_added == 0) + { + point_added = sk_addStrokeDrawPoint(sketch->gesture, &dd); + } + + sk_updateDrawData(&dd); + + /* draw only if mouse has moved */ + if (sketch->gesture->nb_points > 1) + { + force_draw(0); + } + } + else + { + BIF_wait_for_statechange(); + } + + while( qtest() ) { + short event, val; + event = extern_qread(&val); + } + + /* do mouse checking at the end, so don't check twice, and potentially + * miss a short tap + */ + } while (get_mbut() & R_MOUSE); + + sk_endContinuousStroke(sketch->gesture); + sk_filterLastContinuousStroke(sketch->gesture); + + if (sketch->gesture->nb_points == 1) + { + sk_selectStroke(sketch); + } + else + { + /* apply gesture here */ + printf("FOO!\n"); + } + + sk_freeStroke(sketch->gesture); + sketch->gesture = NULL; + allqueue(REDRAWVIEW3D, 0); } } @@ -1533,11 +1602,26 @@ void BDR_drawSketch() } } +void BIF_endStrokeSketch() +{ + if (BIF_validSketchMode()) + { + if (GLOBAL_sketch != NULL) + { + sk_endStroke(GLOBAL_sketch); + allqueue(REDRAWVIEW3D, 0); + } + } +} + void BIF_deleteSketch() { if (BIF_validSketchMode()) { - sk_deleteStrokes(GLOBAL_sketch); + if (GLOBAL_sketch != NULL) + { + sk_deleteStrokes(GLOBAL_sketch); + } } } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 99939d87b30..d26819d094a 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -2945,7 +2945,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case ESCKEY: - if(G.qual==0) { + if (G.qual == 0 && BIF_validSketchMode()) + { + BIF_endStrokeSketch(); + } + else if(G.qual==0) { if (G.vd->flag & V3D_DISPIMAGE) { G.vd->flag &= ~V3D_DISPIMAGE; doredraw= 1; From 16aaefb5c3e53283813bc0fd84ca2251345b511c Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 17 Oct 2008 04:17:16 +0000 Subject: [PATCH 017/252] Bugfixes for sketching with multiple 3d view (correct update and poly line preview in all views). Fixed a bug with correlation conversion (matrix application wasn't done at the correct place). --- source/blender/src/editarmature_sketch.c | 357 +++++++++++++---------- 1 file changed, 209 insertions(+), 148 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index cb06366bc96..d803aca1f7c 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -60,7 +60,7 @@ typedef enum SK_PType PT_EXACT, } SK_PType; -typedef enum Method +typedef enum SK_PMode { PT_EMBED, PT_SNAP, @@ -98,6 +98,7 @@ typedef struct SK_Sketch ListBase strokes; SK_Stroke *active_stroke; SK_Stroke *gesture; + SK_Point next_point; } SK_Sketch; SK_Sketch *GLOBAL_sketch = NULL; @@ -531,8 +532,9 @@ SK_Point *sk_lastStrokePoint(SK_Stroke *stk) return pt; } -void sk_drawStroke(SK_Stroke *stk, int id, float rgb[3]) +void sk_drawStroke(SK_Stroke *stk, int id, float color[3]) { + float rgb[3]; int i; if (id != -1) @@ -553,6 +555,7 @@ void sk_drawStroke(SK_Stroke *stk, int id, float rgb[3]) { float d_rgb[3] = {1, 1, 1}; + VECCOPY(rgb, color); VecSubf(d_rgb, d_rgb, rgb); VecMulf(d_rgb, 1.0f / (float)stk->nb_points); @@ -664,35 +667,6 @@ SK_Point *sk_snapPointArmature(ListBase *ebones, short mval[2], int *dist) return pt; } -SK_Point *sk_snapPoint(SK_Sketch *sketch, short mval[2], int min_dist) -{ - SK_Point *pt = NULL; - SK_Stroke *stk; - int dist = min_dist; - - for (stk = sketch->strokes.first; stk; stk = stk->next) - { - SK_Point *spt = sk_snapPointStroke(stk, mval, &dist); - - if (spt != NULL) - { - pt = spt; - } - } - - /* check on bones */ - { - SK_Point *spt = sk_snapPointArmature(&G.edbo, mval, &dist); - - if (spt != NULL) - { - pt = spt; - } - } - - return pt; -} - void sk_startStroke(SK_Sketch *sketch) { SK_Stroke *stk = sk_createStroke(); @@ -707,28 +681,6 @@ void sk_endStroke(SK_Sketch *sketch) sketch->active_stroke = NULL; } -void sk_projectPaintData(SK_Stroke *stk, SK_DrawData *dd, float vec[3]) -{ - /* copied from grease pencil, need fixing */ - SK_Point *last = sk_lastStrokePoint(stk); - short cval[2]; - //float *fp = give_cursor(); - float fp[3] = {0, 0, 0}; - float dvec[3]; - - if (last != NULL) - { - VECCOPY(fp, last->p); - } - - initgrabz(fp[0], fp[1], fp[2]); - - /* method taken from editview.c - mouse_cursor() */ - project_short_noclip(fp, cval); - window_to_3d(dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]); - VecSubf(vec, fp, dvec); -} - void sk_updateDrawData(SK_DrawData *dd) { dd->type = PT_CONTINUOUS; @@ -779,65 +731,132 @@ void sk_interpolateDepth(SK_Stroke *stk, int start, int end, float length, float } } -int sk_addStrokeSnapPoint(SK_Stroke *stk, SK_DrawData *dd, SK_Point *snap_pt) +void sk_projectDrawPoint(float vec[3], SK_Stroke *stk, SK_DrawData *dd) { - SK_Point pt; - float distance; - float length; - int i, total; + /* copied from grease pencil, need fixing */ + SK_Point *last = sk_lastStrokePoint(stk); + short cval[2]; + //float *fp = give_cursor(); + float fp[3] = {0, 0, 0}; + float dvec[3]; - if (snap_pt == NULL) + if (last != NULL) { - return 0; + VECCOPY(fp, last->p); } - pt.type = PT_EXACT; - pt.mode = PT_SNAP; + initgrabz(fp[0], fp[1], fp[2]); - sk_projectPaintData(stk, dd, pt.p); + /* method taken from editview.c - mouse_cursor() */ + project_short_noclip(fp, cval); + window_to_3d(dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]); + VecSubf(vec, fp, dvec); +} + +int sk_getStrokeDrawPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) +{ + pt->type = dd->type; + pt->mode = PT_PROJECT; + sk_projectDrawPoint(pt->p, stk, dd); + + return 1; +} + +int sk_addStrokeDrawPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) +{ + SK_Point pt; + + sk_getStrokeDrawPoint(&pt, sketch, stk, dd); sk_appendStrokePoint(stk, &pt); - /* update all previous point to give smooth Z progresion */ - total = 0; - length = 0; - for (i = stk->nb_points - 2; i > 0; i--) + return 1; +} + + +int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *source_stk, SK_DrawData *dd) +{ + SK_Stroke *stk; + int dist = SNAP_MIN_DISTANCE; + int point_added = 0; + + for (stk = sketch->strokes.first; stk; stk = stk->next) { - length += VecLenf(stk->points[i].p, stk->points[i + 1].p); - total++; - if (stk->points[i].type == PT_EXACT) + SK_Point *spt = sk_snapPointStroke(stk, dd->mval, &dist); + + if (spt != NULL) { - break; + VECCOPY(pt->p, spt->p); + point_added = 1; } } - if (total > 1) + /* check on bones */ { - distance = sk_distanceDepth(snap_pt->p, stk->points[i].p); + SK_Point *spt = sk_snapPointArmature(&G.edbo, dd->mval, &dist); - sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance); + if (spt != NULL) + { + VECCOPY(pt->p, spt->p); + point_added = 1; + } } - - VECCOPY(stk->points[stk->nb_points - 1].p, snap_pt->p); - return 1; + if (point_added) + { + pt->type = PT_EXACT; + pt->mode = PT_SNAP; + } + + return point_added; } -int sk_addStrokeDrawPoint(SK_Stroke *stk, SK_DrawData *dd) +int sk_addStrokeSnapPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { SK_Point pt; + int point_added = 0; - pt.type = dd->type; - pt.mode = PT_PROJECT; + point_added = sk_getStrokeSnapPoint(&pt, sketch, stk, dd); - sk_projectPaintData(stk, dd, pt.p); + if (point_added) + { + float final_p[3]; + float distance; + float length; + int i, total; + + VECCOPY(final_p, pt.p); - sk_appendStrokePoint(stk, &pt); + sk_projectDrawPoint(pt.p, stk, dd); + sk_appendStrokePoint(stk, &pt); + + /* update all previous point to give smooth Z progresion */ + total = 0; + length = 0; + for (i = stk->nb_points - 2; i > 0; i--) + { + length += VecLenf(stk->points[i].p, stk->points[i + 1].p); + total++; + if (stk->points[i].type == PT_EXACT) + { + break; + } + } + + if (total > 1) + { + distance = sk_distanceDepth(final_p, stk->points[i].p); + + sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance); + } - return 1; + VECCOPY(stk->points[stk->nb_points - 1].p, final_p); + } + + return point_added; } -int sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) +int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { ListBase depth_peels; SK_DepthPeel *p1, *p2; @@ -850,7 +869,6 @@ int sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) peelObjects(&depth_peels, dd->mval); - if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) { last_pt = stk->points + (stk->nb_points - 1); @@ -903,15 +921,35 @@ int sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) if (dist != FLT_MAX) { - SK_Point pt; + pt->type = dd->type; + pt->mode = PT_EMBED; + VECCOPY(pt->p, p); + + point_added = 1; + } + + BLI_freelistN(&depth_peels); + + return point_added; +} + +int sk_addStrokeEmbedPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) +{ + SK_Point pt; + int point_added; + + point_added = sk_getStrokeEmbedPoint(&pt, sketch, stk, dd); + + if (point_added) + { + float final_p[3]; float length, distance; int total; int i; - pt.type = dd->type; - pt.mode = PT_EMBED; + VECCOPY(final_p, pt.p); - sk_projectPaintData(stk, dd, pt.p); + sk_projectDrawPoint(pt.p, stk, dd); sk_appendStrokePoint(stk, &pt); /* update all previous point to give smooth Z progresion */ @@ -929,26 +967,73 @@ int sk_addStrokeEmbedPoint(SK_Stroke *stk, SK_DrawData *dd) if (total > 1) { - distance = sk_distanceDepth(p, stk->points[i].p); + distance = sk_distanceDepth(final_p, stk->points[i].p); sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance); } - VECCOPY(stk->points[stk->nb_points - 1].p, p); + VECCOPY(stk->points[stk->nb_points - 1].p, final_p); point_added = 1; } - BLI_freelistN(&depth_peels); - return point_added; } +void sk_addStrokePoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual) +{ + int point_added = 0; + + if (qual & LR_CTRLKEY) + { + point_added = sk_addStrokeSnapPoint(sketch, stk, dd); + } + + if (point_added == 0 && qual & LR_SHIFTKEY) + { + point_added = sk_addStrokeEmbedPoint(sketch, stk, dd); + } + + if (point_added == 0) + { + point_added = sk_addStrokeDrawPoint(sketch, stk, dd); + } +} + +void sk_getStrokePoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual) +{ + int point_added = 0; + + if (qual & LR_CTRLKEY) + { + point_added = sk_getStrokeSnapPoint(pt, sketch, stk, dd); + } + + if (point_added == 0 && qual & LR_SHIFTKEY) + { + point_added = sk_getStrokeEmbedPoint(pt, sketch, stk, dd); + } + + if (point_added == 0) + { + point_added = sk_getStrokeDrawPoint(pt, sketch, stk, dd); + } +} + void sk_endContinuousStroke(SK_Stroke *stk) { stk->points[stk->nb_points - 1].type = PT_EXACT; } +void sk_updateNextPoint(SK_Sketch *sketch) +{ + if (sketch->active_stroke) + { + SK_Stroke *stk = sketch->active_stroke; + memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point)); + } +} + int sk_stroke_filtermval(SK_DrawData *dd) { int retval = 0; @@ -1046,10 +1131,10 @@ EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, floa if (calcStrokeCorrelation(stk, boneStart, i, parent->head, n) < CORRELATION_THRESHOLD) { VECCOPY(parent->tail, stk->points[i - 1].p); + Mat4MulVecfl(invmat, parent->tail); child = addEditBone("Bone", &G.edbo, arm); VECCOPY(child->head, parent->tail); - Mat4MulVecfl(invmat, parent->tail); child->parent = parent; child->flag |= BONE_CONNECTED; @@ -1395,37 +1480,43 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) if (last != NULL) { - SK_DrawData dd; - float vec[3]; - - sk_initDrawData(&dd); - sk_projectPaintData(sketch->active_stroke, &dd, vec); + if (area_is_active_area(G.vd->area)) + { + SK_DrawData dd; + + sk_initDrawData(&dd); + sk_getStrokePoint(&sketch->next_point, sketch, sketch->active_stroke, &dd, G.qual); + } glEnable(GL_LINE_STIPPLE); glColor3f(1, 0.5, 0); glBegin(GL_LINE_STRIP); glVertex3fv(last->p); - glVertex3fv(vec); + glVertex3fv(sketch->next_point.p); glEnd(); glDisable(GL_LINE_STIPPLE); - - if (G.qual & LR_CTRLKEY) + + switch (sketch->next_point.mode) { - SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, SNAP_MIN_DISTANCE); - - if (snap_pt != NULL) - { + case PT_SNAP: glColor3f(0, 0.5, 1); - glBegin(GL_POINTS); - - glVertex3fv(snap_pt->p); - - glEnd(); - } + break; + case PT_EMBED: + glColor3f(0, 1, 0); + break; + case PT_PROJECT: + glColor3f(0, 0, 0); + break; } + + glBegin(GL_POINTS); + + glVertex3fv(sketch->next_point.p); + + glEnd(); } } @@ -1456,24 +1547,8 @@ int sk_paint(SK_Sketch *sketch, short mbut) /* only add current point to buffer if mouse moved (otherwise wait until it does) */ if (sk_stroke_filtermval(&dd)) { - int point_added = 0; - - if (G.qual & LR_CTRLKEY) - { - SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, SNAP_MIN_DISTANCE); - point_added = sk_addStrokeSnapPoint(sketch->active_stroke, &dd, snap_pt); - } - - if (point_added == 0 && G.qual & LR_SHIFTKEY) - { - point_added = sk_addStrokeEmbedPoint(sketch->active_stroke, &dd); - } - - if (point_added == 0) - { - point_added = sk_addStrokeDrawPoint(sketch->active_stroke, &dd); - } - + + sk_addStrokePoint(sketch, sketch->active_stroke, &dd, G.qual); sk_updateDrawData(&dd); force_draw(0); } @@ -1494,6 +1569,7 @@ int sk_paint(SK_Sketch *sketch, short mbut) sk_endContinuousStroke(sketch->active_stroke); sk_filterLastContinuousStroke(sketch->active_stroke); + sk_updateNextPoint(sketch); } else if (mbut == RIGHTMOUSE) { @@ -1516,24 +1592,8 @@ int sk_paint(SK_Sketch *sketch, short mbut) /* only add current point to buffer if mouse moved (otherwise wait until it does) */ if (sk_stroke_filtermval(&dd)) { - int point_added = 0; - - if (G.qual & LR_CTRLKEY) - { - SK_Point *snap_pt = sk_snapPoint(sketch, dd.mval, SNAP_MIN_DISTANCE); - point_added = sk_addStrokeSnapPoint(sketch->gesture, &dd, snap_pt); - } - - if (point_added == 0 && G.qual & LR_SHIFTKEY) - { - point_added = sk_addStrokeEmbedPoint(sketch->gesture, &dd); - } - - if (point_added == 0) - { - point_added = sk_addStrokeDrawPoint(sketch->gesture, &dd); - } - + + sk_addStrokeDrawPoint(sketch, sketch->gesture, &dd); sk_updateDrawData(&dd); /* draw only if mouse has moved */ @@ -1652,6 +1712,7 @@ int BIF_paintSketch(short mbut) return 0; } } + void BDR_queueDrawSketch() { From 0f49fd401fba68ca9fb78ef3c6578797824f3f3a Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 17 Oct 2008 21:52:50 +0000 Subject: [PATCH 018/252] Skeleton Sketching Cut gesture: drawing a line with RMB adds exact points (joints in the final skeleton) on strokes. Can cut multiple strokes at once as long as it cuts each one only once (this could be changed). Shape of the gesture doesn't matter, but eventually it would be straight lines shapes for cuts. --- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 61 +++++++++++ source/blender/src/editarmature_sketch.c | 123 ++++++++++++++++++++++- 3 files changed, 183 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index e2e71a2fb1a..3c8d2915cf9 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -388,6 +388,7 @@ void tubemap(float x, float y, float z, float *u, float *v); void spheremap(float x, float y, float z, float *u, float *v); int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3]); +int LineIntersectLineStrict(float v1[3], float v2[3], float v3[3], float v4[3], float vi[3], float *lambda); int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 79517c4fde4..54e1bd5fc57 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -4221,6 +4221,67 @@ int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float } } +/* Intersection point strictly between the two lines + * 0 when no intersection is found + * */ +int LineIntersectLineStrict(float v1[3], float v2[3], float v3[3], float v4[3], float vi[3], float *lambda) +{ + float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3]; + float d; + float d1; + + VecSubf(c, v3, v1); + VecSubf(a, v2, v1); + VecSubf(b, v4, v3); + + VecCopyf(dir1, a); + Normalize(dir1); + VecCopyf(dir2, b); + Normalize(dir2); + d = Inpf(dir1, dir2); + if (d == 1.0f || d == -1.0f || d == 0) { + /* colinear or one vector is zero-length*/ + return 0; + } + + d1 = d; + + Crossf(ab, a, b); + d = Inpf(c, ab); + + /* test if the two lines are coplanar */ + if (d > -0.000001f && d < 0.000001f) { + float f1, f2; + Crossf(cb, c, b); + Crossf(ca, c, a); + + f1 = Inpf(cb, ab) / Inpf(ab, ab); + f2 = Inpf(ca, ab) / Inpf(ab, ab); + + if (f1 >= 0 && f1 <= 1 && + f2 >= 0 && f2 <= 1) + { + VecMulf(a, f1); + VecAddf(vi, v1, a); + + if (lambda != NULL) + { + *lambda = f1; + } + + return 1; /* intersection found */ + } + else + { + return 0; + } + } + else + { + return 0; + } +} + int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]) { return (min1[0]nb_points - n; + + sk_growStrokeBuffer(stk); + + memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point)); + + memcpy(stk->points + n, pt, sizeof(SK_Point)); + + stk->nb_points++; +} + void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt) { sk_growStrokeBuffer(stk); @@ -1329,6 +1351,98 @@ void sk_convert(SK_Sketch *sketch) } } } +/******************* GESTURE *************************/ + +/* returns the maximum number of intersections per stroke */ +int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) +{ + SK_Stroke *stk; + int added = 0; + + for (stk = sketch->strokes.first; stk; stk = stk->next) + { + int s_added = 0; + int s_i; + + for (s_i = 0; s_i < stk->nb_points - 1; s_i++) + { + float s_p1[3] = {0, 0, 0}; + float s_p2[3] = {0, 0, 0}; + int g_i; + + project_float(stk->points[s_i].p, s_p1); + project_float(stk->points[s_i + 1].p, s_p2); + + for (g_i = 0; g_i < gesture->nb_points - 1; g_i++) + { + float g_p1[3] = {0, 0, 0}; + float g_p2[3] = {0, 0, 0}; + float vi[3]; + float lambda; + + project_float(gesture->points[g_i].p, g_p1); + project_float(gesture->points[g_i + 1].p, g_p2); + + if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) + { + SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); + + isect->start = s_i; + isect->end = s_i + 1; + isect->stroke = stk; + + VecSubf(isect->p, stk->points[s_i + 1].p, stk->points[s_i].p); + VecMulf(isect->p, lambda); + VecAddf(isect->p, isect->p, stk->points[s_i].p); + + BLI_addtail(list, isect); + + s_added++; + } + } + } + + added = MAX2(s_added, added); + } + + + return added; +} + +void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list) +{ + SK_Intersection *isect; + + for (isect = list->first; isect; isect = isect->next) + { + SK_Point pt; + + pt.type = PT_EXACT; + pt.mode = PT_PROJECT; /* take mode from neighbouring points */ + VECCOPY(pt.p, isect->p); + + sk_insertStrokePoint(isect->stroke, &pt, isect->end); + } +} + +void sk_applyGesture(SK_Sketch *sketch) +{ + ListBase list; + int added; + + list.first = list.last = NULL; + + added = sk_getIntersections(&list, sketch, sketch->gesture); + + /* detect and apply */ + if (added == 1) + { + sk_applyCutGesture(sketch, sketch->gesture, &list); + } + + BLI_freelistN(&list); +} + /********************************************/ void sk_deleteStrokes(SK_Sketch *sketch) @@ -1354,7 +1468,7 @@ void sk_selectAllSketch(SK_Sketch *sketch, int mode) if (mode == -1) { for (stk = sketch->strokes.first; stk; stk = stk->next) - { + {sk_applyGesture(sketch); stk->selected = 0; } } @@ -1468,7 +1582,8 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) } } - if (sketch->gesture != NULL) + /* only draw gesture in active area */ + if (sketch->gesture != NULL && area_is_active_area(G.vd->area)) { float gesture_rgb[3] = {0, 0.5, 1}; sk_drawStroke(sketch->gesture, -1, gesture_rgb); @@ -1480,6 +1595,7 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) if (last != NULL) { + /* update point if in active area */ if (area_is_active_area(G.vd->area)) { SK_DrawData dd; @@ -1619,6 +1735,8 @@ int sk_paint(SK_Sketch *sketch, short mbut) sk_endContinuousStroke(sketch->gesture); sk_filterLastContinuousStroke(sketch->gesture); + sk_filterLastContinuousStroke(sketch->gesture); + sk_filterLastContinuousStroke(sketch->gesture); if (sketch->gesture->nb_points == 1) { @@ -1627,6 +1745,7 @@ int sk_paint(SK_Sketch *sketch, short mbut) else { /* apply gesture here */ + sk_applyGesture(sketch); printf("FOO!\n"); } From 9dc10efa15ca34d06e8969963fa9855802348b9f Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sat, 18 Oct 2008 22:16:42 +0000 Subject: [PATCH 019/252] Gesture recognition: - straight segments are extracted from the strock - Cut gesture is now on straight strokes only Trim Gesture: - Two segments gesture. First segment indicates where the cut is, second indicates which side to trim. Gesture / Stroke intersection bugfix: better code to deal with perspective (this is very brute force still). --- source/blender/src/editarmature_sketch.c | 144 ++++++++++++++++++++--- 1 file changed, 130 insertions(+), 14 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index ecb8a0836fe..ba313c13cd1 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -428,6 +428,11 @@ void sk_growStrokeBuffer(SK_Stroke *stk) } } +void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n) +{ + memcpy(stk->points + n, pt, sizeof(SK_Point)); +} + void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n) { int size = stk->nb_points - n; @@ -450,6 +455,18 @@ void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt) stk->nb_points++; } +void sk_trimStroke(SK_Stroke *stk, int start, int end) +{ + int size = end - start + 1; + + if (start > 0) + { + memmove(stk->points, stk->points + start, size * sizeof(SK_Point)); + } + + stk->nb_points = size; +} + /* Apply reverse Chaikin filter to simplify the polyline * */ void sk_filterStroke(SK_Stroke *stk, int start, int end) @@ -1386,14 +1403,23 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) { SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); + float ray_start[3], ray_end[3]; + short mval[2]; isect->start = s_i; isect->end = s_i + 1; isect->stroke = stk; - - VecSubf(isect->p, stk->points[s_i + 1].p, stk->points[s_i].p); - VecMulf(isect->p, lambda); - VecAddf(isect->p, isect->p, stk->points[s_i].p); + + mval[0] = (short)(vi[0]); + mval[1] = (short)(vi[1]); + viewline(mval, ray_start, ray_end); + + LineIntersectLine( stk->points[s_i].p, + stk->points[s_i + 1].p, + ray_start, + ray_end, + isect->p, + vi); BLI_addtail(list, isect); @@ -1409,7 +1435,37 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) return added; } -void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list) +int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) +{ + float CORRELATION_THRESHOLD = 0.995f; + float *vec; + int i, j; + + sk_appendStrokePoint(segments, &gesture->points[0]); + vec = segments->points[segments->nb_points - 1].p; + + for (i = 1, j = 0; i < gesture->nb_points; i++) + { + float n[3]; + + /* Calculate normal */ + VecSubf(n, gesture->points[i].p, vec); + + if (calcStrokeCorrelation(gesture, j, i, vec, n) < CORRELATION_THRESHOLD) + { + j = i - 1; + sk_appendStrokePoint(segments, &gesture->points[j]); + vec = segments->points[segments->nb_points - 1].p; + segments->points[segments->nb_points - 1].type = PT_EXACT; + } + } + + sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]); + + return segments->nb_points - 1; +} + +void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) { SK_Intersection *isect; @@ -1425,22 +1481,83 @@ void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list) } } +int sk_detectTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + float s1[3], s2[3]; + float angle; + + VecSubf(s1, segments->points[1].p, segments->points[0].p); + VecSubf(s2, segments->points[2].p, segments->points[1].p); + + angle = VecAngle2(s1, s2); + + if (angle > 60 && angle < 120) + { + return 1; + } + else + { + return 0; + } +} + +void sk_applyTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + SK_Intersection *isect; + float trim_dir[3]; + + VecSubf(trim_dir, segments->points[2].p, segments->points[1].p); + + for (isect = list->first; isect; isect = isect->next) + { + SK_Point pt; + float stroke_dir[3]; + + pt.type = PT_EXACT; + pt.mode = PT_PROJECT; /* take mode from neighbouring points */ + VECCOPY(pt.p, isect->p); + + VecSubf(stroke_dir, isect->stroke->points[isect->end].p, isect->stroke->points[isect->start].p); + + /* same direction, trim end */ + if (Inpf(stroke_dir, trim_dir) > 0) + { + sk_replaceStrokePoint(isect->stroke, &pt, isect->end); + sk_trimStroke(isect->stroke, 0, isect->end); + } + /* else, trim start */ + else + { + sk_replaceStrokePoint(isect->stroke, &pt, isect->start); + sk_trimStroke(isect->stroke, isect->start, isect->stroke->nb_points - 1); + } + + } +} + void sk_applyGesture(SK_Sketch *sketch) { - ListBase list; - int added; + ListBase intersections; + SK_Stroke *segments = sk_createStroke(); + int nb_intersections, nb_segments; - list.first = list.last = NULL; + intersections.first = intersections.last = NULL; - added = sk_getIntersections(&list, sketch, sketch->gesture); + nb_intersections = sk_getIntersections(&intersections, sketch, sketch->gesture); + nb_segments = sk_getSegments(segments, sketch->gesture); /* detect and apply */ - if (added == 1) + if (nb_segments == 1 && nb_intersections == 1) { - sk_applyCutGesture(sketch, sketch->gesture, &list); + sk_applyCutGesture(sketch, sketch->gesture, &intersections, segments); + } + else if (nb_segments == 2 && nb_intersections == 1 && sk_detectTrimGesture(sketch, sketch->gesture, &intersections, segments)) + { + sk_applyTrimGesture(sketch, sketch->gesture, &intersections, segments); } - BLI_freelistN(&list); + sk_freeStroke(segments); + BLI_freelistN(&intersections); } /********************************************/ @@ -1468,7 +1585,7 @@ void sk_selectAllSketch(SK_Sketch *sketch, int mode) if (mode == -1) { for (stk = sketch->strokes.first; stk; stk = stk->next) - {sk_applyGesture(sketch); + { stk->selected = 0; } } @@ -1746,7 +1863,6 @@ int sk_paint(SK_Sketch *sketch, short mbut) { /* apply gesture here */ sk_applyGesture(sketch); - printf("FOO!\n"); } sk_freeStroke(sketch->gesture); From 7d108a30eeb0954ab3e434a1f469a5fb29220f42 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sat, 18 Oct 2008 23:54:09 +0000 Subject: [PATCH 020/252] Delete Gesture: 2 segments gesture, going back and forth over a stroke (intersecting twice, angle between segments > 120). Can delete more than one stroke at once. Stroke crossed only once are not deleted. --- source/blender/src/editarmature_sketch.c | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index ba313c13cd1..bd7af4b915d 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1535,6 +1535,43 @@ void sk_applyTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, } } +int sk_detectDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + float s1[3], s2[3]; + float angle; + + VecSubf(s1, segments->points[1].p, segments->points[0].p); + VecSubf(s2, segments->points[2].p, segments->points[1].p); + + angle = VecAngle2(s1, s2); + + if (angle > 120) + { + return 1; + } + else + { + return 0; + } +} + +void sk_applyDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + SK_Intersection *isect; + + for (isect = list->first; isect; isect = isect->next) + { + /* only delete strokes that are crossed twice */ + if (isect->next && isect->next->stroke == isect->stroke) + { + isect = isect->next; + + BLI_remlink(&sketch->strokes, isect->stroke); + sk_freeStroke(isect->stroke); + } + } +} + void sk_applyGesture(SK_Sketch *sketch) { ListBase intersections; @@ -1555,6 +1592,10 @@ void sk_applyGesture(SK_Sketch *sketch) { sk_applyTrimGesture(sketch, sketch->gesture, &intersections, segments); } + else if (nb_segments == 2 && nb_intersections == 2 && sk_detectDeleteGesture(sketch, sketch->gesture, &intersections, segments)) + { + sk_applyDeleteGesture(sketch, sketch->gesture, &intersections, segments); + } sk_freeStroke(segments); BLI_freelistN(&intersections); From 96f524ee98a81545b4822c36602a7580be6f6e35 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 19 Oct 2008 00:35:00 +0000 Subject: [PATCH 021/252] Alt-C and Del/X for convert and delete (no confirmation, no undo, LIVE ON THE EDGE!) Fix bug with mouse selection (would selected last stroke when clicking in empty space). --- source/blender/src/edit.c | 7 +- source/blender/src/editarmature_sketch.c | 107 ++++++++++++----------- source/blender/src/space.c | 6 +- 3 files changed, 67 insertions(+), 53 deletions(-) diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index a80e7b6c360..651bfc854d9 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -99,6 +99,7 @@ #include "BIF_space.h" #include "BIF_screen.h" #include "BIF_toolbox.h" +#include "BIF_sketch.h" #ifdef WITH_VERSE #include "BIF_verse.h" @@ -1838,7 +1839,11 @@ void mergemenu(void) void delete_context_selected(void) { - if(G.obedit) { + if(BIF_validSketchMode()) + { + BIF_deleteSketch(); + } + else if(G.obedit) { if(G.obedit->type==OB_MESH) delete_mesh(); else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) delNurb(); else if(G.obedit->type==OB_MBALL) delete_mball(); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index bd7af4b915d..ebbdc1d06ea 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1679,9 +1679,9 @@ void sk_selectStroke(SK_Sketch *sketch) /* loop and get best hit */ } - if (besthitresult != -1) + if (besthitresult > 0) { - SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult); + SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1); if ((G.qual & LR_SHIFTKEY) == 0) { @@ -1724,10 +1724,12 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) if (with_names) { int id; - for (id = 0, stk = sketch->strokes.first; stk; id++, stk = stk->next) + for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next) { sk_drawStroke(stk, id, NULL); } + + glLoadName(-1); } else { @@ -1738,59 +1740,59 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) { sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb)); } - } - /* only draw gesture in active area */ - if (sketch->gesture != NULL && area_is_active_area(G.vd->area)) - { - float gesture_rgb[3] = {0, 0.5, 1}; - sk_drawStroke(sketch->gesture, -1, gesture_rgb); - } - - if (sketch->active_stroke != NULL) - { - SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); - - if (last != NULL) + /* only draw gesture in active area */ + if (sketch->gesture != NULL && area_is_active_area(G.vd->area)) { - /* update point if in active area */ - if (area_is_active_area(G.vd->area)) + float gesture_rgb[3] = {0, 0.5, 1}; + sk_drawStroke(sketch->gesture, -1, gesture_rgb); + } + + if (sketch->active_stroke != NULL) + { + SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); + + if (last != NULL) { - SK_DrawData dd; + /* update point if in active area */ + if (area_is_active_area(G.vd->area)) + { + SK_DrawData dd; + + sk_initDrawData(&dd); + sk_getStrokePoint(&sketch->next_point, sketch, sketch->active_stroke, &dd, G.qual); + } - sk_initDrawData(&dd); - sk_getStrokePoint(&sketch->next_point, sketch, sketch->active_stroke, &dd, G.qual); + glEnable(GL_LINE_STIPPLE); + glColor3f(1, 0.5, 0); + glBegin(GL_LINE_STRIP); + + glVertex3fv(last->p); + glVertex3fv(sketch->next_point.p); + + glEnd(); + + glDisable(GL_LINE_STIPPLE); + + switch (sketch->next_point.mode) + { + case PT_SNAP: + glColor3f(0, 0.5, 1); + break; + case PT_EMBED: + glColor3f(0, 1, 0); + break; + case PT_PROJECT: + glColor3f(0, 0, 0); + break; + } + + glBegin(GL_POINTS); + + glVertex3fv(sketch->next_point.p); + + glEnd(); } - - glEnable(GL_LINE_STIPPLE); - glColor3f(1, 0.5, 0); - glBegin(GL_LINE_STRIP); - - glVertex3fv(last->p); - glVertex3fv(sketch->next_point.p); - - glEnd(); - - glDisable(GL_LINE_STIPPLE); - - switch (sketch->next_point.mode) - { - case PT_SNAP: - glColor3f(0, 0.5, 1); - break; - case PT_EMBED: - glColor3f(0, 1, 0); - break; - case PT_PROJECT: - glColor3f(0, 0, 0); - break; - } - - glBegin(GL_POINTS); - - glVertex3fv(sketch->next_point.p); - - glEnd(); } } @@ -1957,6 +1959,7 @@ void BIF_deleteSketch() if (GLOBAL_sketch != NULL) { sk_deleteStrokes(GLOBAL_sketch); + allqueue(REDRAWVIEW3D, 0); } } } @@ -1968,6 +1971,8 @@ void BIF_convertSketch() if (GLOBAL_sketch != NULL) { sk_convert(GLOBAL_sketch); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); } } } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index d26819d094a..94ba10cca4a 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1976,6 +1976,10 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.qual==LR_ALTKEY) { if(ob && (ob->flag & OB_POSEMODE)) pose_clear_constraints(); /* poseobject.c */ + else if (BIF_validSketchMode()) + { + BIF_convertSketch(); + } else convertmenu(); /* editobject.c */ } @@ -2783,7 +2787,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case DELKEY: if(G.qual==0 || G.qual==LR_SHIFTKEY) delete_context_selected(); - if(G.qual==LR_ALTKEY) + else if(G.qual==LR_ALTKEY) gpencil_delete_menu(); break; case YKEY: From ba72ff005c3d0bf5148fa927486b661895bde8d8 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 19 Oct 2008 03:33:53 +0000 Subject: [PATCH 022/252] Self intersection detection for gestures. Two new gestures: - Merge: remove cuts on a stroke (gesture is a circle around the cuts to remove). The encircled points are changed to continuous points. - Convert: convert selected strokes to bones (gesture is a stroke that loops back on itself once). Note that all those different gestures are experimental. First, to get a good hang on recognition. Second, to try different things. --- source/blender/src/editarmature_sketch.c | 143 ++++++++++++++++++++++- 1 file changed, 142 insertions(+), 1 deletion(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index ebbdc1d06ea..0d53ec5f8a6 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1370,6 +1370,56 @@ void sk_convert(SK_Sketch *sketch) } /******************* GESTURE *************************/ + +/* returns the number of self intersections */ +int sk_getSelfIntersections(ListBase *list, SK_Stroke *gesture) +{ + int added = 0; + int s_i; + + for (s_i = 0; s_i < gesture->nb_points - 1; s_i++) + { + float s_p1[3] = {0, 0, 0}; + float s_p2[3] = {0, 0, 0}; + int g_i; + + project_float(gesture->points[s_i].p, s_p1); + project_float(gesture->points[s_i + 1].p, s_p2); + + /* start checking from second next, because two consecutive cannot intersect */ + for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++) + { + float g_p1[3] = {0, 0, 0}; + float g_p2[3] = {0, 0, 0}; + float vi[3]; + float lambda; + + project_float(gesture->points[g_i].p, g_p1); + project_float(gesture->points[g_i + 1].p, g_p2); + + if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) + { + SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); + + isect->start = s_i; + isect->end = g_i + 1; + isect->stroke = gesture; + + VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p); + VecMulf(isect->p, lambda); + VecAddf(isect->p, isect->p, gesture->points[s_i].p); + + BLI_addtail(list, isect); + + added++; + } + } + } + + return added; +} + + /* returns the maximum number of intersections per stroke */ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) { @@ -1572,14 +1622,96 @@ void sk_applyDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list } } +int sk_detectMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + short start_val[2], end_val[2]; + short dist; + + project_short_noclip(gesture->points[0].p, start_val); + project_short_noclip(gesture->points[gesture->nb_points - 1].p, end_val); + + dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1])); + + /* if gesture is a circle */ + if ( dist <= 20 ) + { + SK_Intersection *isect; + + /* check if it circled around an exact point */ + for (isect = list->first; isect; isect = isect->next) + { + /* only delete strokes that are crossed twice */ + if (isect->next && isect->next->stroke == isect->stroke) + { + int start_index, end_index; + int i; + + start_index = MIN2(isect->end, isect->next->end); + end_index = MAX2(isect->start, isect->next->start); + + for (i = start_index; i <= end_index; i++) + { + if (isect->stroke->points[i].type == PT_EXACT) + { + return 1; /* at least one exact point found, stop detect here */ + } + } + + /* skip next */ + isect = isect->next; + } + } + + return 0; + } + else + { + return 0; + } +} + +void sk_applyMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + SK_Intersection *isect; + + /* check if it circled around an exact point */ + for (isect = list->first; isect; isect = isect->next) + { + /* only delete strokes that are crossed twice */ + if (isect->next && isect->next->stroke == isect->stroke) + { + int start_index, end_index; + int i; + + start_index = MIN2(isect->end, isect->next->end); + end_index = MAX2(isect->start, isect->next->start); + + for (i = start_index; i <= end_index; i++) + { + /* if exact, switch to continuous */ + if (isect->stroke->points[i].type == PT_EXACT) + { + isect->stroke->points[i].type = PT_CONTINUOUS; + } + } + + /* skip next */ + isect = isect->next; + } + } +} + void sk_applyGesture(SK_Sketch *sketch) { ListBase intersections; + ListBase self_intersections; SK_Stroke *segments = sk_createStroke(); - int nb_intersections, nb_segments; + int nb_self_intersections, nb_intersections, nb_segments; intersections.first = intersections.last = NULL; + self_intersections.first = self_intersections.last = NULL; + nb_self_intersections = sk_getSelfIntersections(&self_intersections, sketch->gesture); nb_intersections = sk_getIntersections(&intersections, sketch, sketch->gesture); nb_segments = sk_getSegments(segments, sketch->gesture); @@ -1596,9 +1728,18 @@ void sk_applyGesture(SK_Sketch *sketch) { sk_applyDeleteGesture(sketch, sketch->gesture, &intersections, segments); } + else if (nb_segments > 2 && nb_intersections == 2 && sk_detectMergeGesture(sketch, sketch->gesture, &intersections, segments)) + { + sk_applyMergeGesture(sketch, sketch->gesture, &intersections, segments); + } + else if (nb_segments > 2 && nb_self_intersections == 1) + { + sk_convert(sketch); + } sk_freeStroke(segments); BLI_freelistN(&intersections); + BLI_freelistN(&self_intersections); } /********************************************/ From 1e17953d68356c3911d9e09e3539068bb04bfdcb Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 20 Oct 2008 00:04:40 +0000 Subject: [PATCH 023/252] Adding undo push and redraw for convert calls. --- source/blender/src/editarmature_sketch.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 0d53ec5f8a6..07bdddfa400 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1735,6 +1735,8 @@ void sk_applyGesture(SK_Sketch *sketch) else if (nb_segments > 2 && nb_self_intersections == 1) { sk_convert(sketch); + BIF_undo_push("Convert Sketch"); + allqueue(REDRAWBUTSEDIT, 0); } sk_freeStroke(segments); @@ -2112,6 +2114,7 @@ void BIF_convertSketch() if (GLOBAL_sketch != NULL) { sk_convert(GLOBAL_sketch); + BIF_undo_push("Convert Sketch"); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); } From ff3924ce2f37145ec63c38c168d2bcd00f594c15 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 20 Oct 2008 18:55:09 +0000 Subject: [PATCH 024/252] Quick Strokes option When turned on, edit mode armature act as usual, but LMB can be directly used to paint strokes or poly lines which will be directly converted to bones once ended (with RMB). Esc now cancels the current stroke instead of ending it (more useful with quick strokes). Video online: http://blenderartists.org/~theeth/bf/etch-a-ton/quick_strokes.ogv --- source/blender/include/BIF_sketch.h | 2 + source/blender/makesdna/DNA_scene_types.h | 3 +- source/blender/src/drawview.c | 3 +- source/blender/src/edit.c | 2 +- source/blender/src/editarmature_sketch.c | 71 +++++++++++++++++++++-- source/blender/src/space.c | 6 +- source/blender/src/view.c | 3 +- 7 files changed, 77 insertions(+), 13 deletions(-) diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h index b9fd5d35d7b..530f0001b15 100644 --- a/source/blender/include/BIF_sketch.h +++ b/source/blender/include/BIF_sketch.h @@ -29,5 +29,7 @@ void BIF_convertSketch(); void BIF_deleteSketch(); void BIF_selectAllSketch(int mode); /* -1: deselect, 0: select, 1: toggle */ int BIF_validSketchMode(); +int BIF_fullSketchMode(); /* full sketch turned on (not Quick) */ +void BIF_cancelStrokeSketch(); #endif /* BIF_SKETCH_H */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3dec57680c7..7ecc524fe7a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -858,7 +858,8 @@ typedef struct Scene { #define SKGEN_SHARPEN 2 /* toolsettings->bone_sketching */ -#define BONE_SKETCHING 1 +#define BONE_SKETCHING 1 +#define BONE_SKETCHING_QUICK 2 #ifdef __cplusplus } diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 386cf30b61f..214a5f42716 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2300,7 +2300,8 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockBeginAlign(block); /* use real flag instead of 1 */ - uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, 225, 150, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, 225, 130, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 140, 225, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end"); but = uiDefBut(block, BUT, B_REDR, "Convert", 10,205,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); uiButSetFunc(but, convert_sketch_armature, NULL, NULL); but = uiDefBut(block, BUT, B_REDR, "Delete", 10,185,150,20, 0, 0, 0, 0, 0, "Delete sketch"); diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index 651bfc854d9..f681b65925f 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -1839,7 +1839,7 @@ void mergemenu(void) void delete_context_selected(void) { - if(BIF_validSketchMode()) + if(BIF_fullSketchMode()) { BIF_deleteSketch(); } diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 07bdddfa400..55bd9d69f20 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -467,6 +467,25 @@ void sk_trimStroke(SK_Stroke *stk, int start, int end) stk->nb_points = size; } +void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk) +{ + if (sketch->active_stroke == stk) + { + sketch->active_stroke = NULL; + } + + BLI_remlink(&sketch->strokes, stk); + sk_freeStroke(stk); +} + +void sk_cancelStroke(SK_Sketch *sketch) +{ + if (sketch->active_stroke != NULL) + { + sk_removeStroke(sketch, sketch->active_stroke); + } +} + /* Apply reverse Chaikin filter to simplify the polyline * */ void sk_filterStroke(SK_Stroke *stk, int start, int end) @@ -1616,8 +1635,7 @@ void sk_applyDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list { isect = isect->next; - BLI_remlink(&sketch->strokes, isect->stroke); - sk_freeStroke(isect->stroke); + sk_removeStroke(sketch, isect->stroke); } } } @@ -1746,7 +1764,7 @@ void sk_applyGesture(SK_Sketch *sketch) /********************************************/ -void sk_deleteStrokes(SK_Sketch *sketch) +void sk_deleteSelectedStrokes(SK_Sketch *sketch) { SK_Stroke *stk, *next; @@ -1756,8 +1774,7 @@ void sk_deleteStrokes(SK_Sketch *sketch) if (stk->selected == 1) { - BLI_remlink(&sketch->strokes, stk); - sk_freeStroke(stk); + sk_removeStroke(sketch, stk); } } } @@ -1994,9 +2011,24 @@ int sk_paint(SK_Sketch *sketch, short mbut) { if (sketch->active_stroke != NULL) { + SK_Stroke *stk = sketch->active_stroke; + sk_endStroke(sketch); + + if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) + { + sk_convertStroke(stk); + sk_removeStroke(sketch, stk); + allqueue(REDRAWBUTSEDIT, 0); + } + allqueue(REDRAWVIEW3D, 0); } + /* no gestures in quick mode */ + else if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) + { + retval = 0; /* return zero for default click behavior */ + } else { SK_DrawData dd; @@ -2095,13 +2127,25 @@ void BIF_endStrokeSketch() } } +void BIF_cancelStrokeSketch() +{ + if (BIF_validSketchMode()) + { + if (GLOBAL_sketch != NULL) + { + sk_cancelStroke(GLOBAL_sketch); + allqueue(REDRAWVIEW3D, 0); + } + } +} + void BIF_deleteSketch() { if (BIF_validSketchMode()) { if (GLOBAL_sketch != NULL) { - sk_deleteStrokes(GLOBAL_sketch); + sk_deleteSelectedStrokes(GLOBAL_sketch); allqueue(REDRAWVIEW3D, 0); } } @@ -2175,3 +2219,18 @@ int BIF_validSketchMode() return 0; } } + +int BIF_fullSketchMode() +{ + if (G.obedit && + G.obedit->type == OB_ARMATURE && + G.scene->toolsettings->bone_sketching & BONE_SKETCHING && + (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) == 0) + { + return 1; + } + else + { + return 0; + } +} diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 71c31fea209..b52ffd54fcf 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1908,7 +1908,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) deselectall_Latt(); else if(G.obedit->type==OB_ARMATURE) { - if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING) + if (BIF_fullSketchMode()) { BIF_selectAllSketch(1); } @@ -1984,7 +1984,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.qual==LR_ALTKEY) { if(ob && (ob->flag & OB_POSEMODE)) pose_clear_constraints(); /* poseobject.c */ - else if (BIF_validSketchMode()) + else if (BIF_fullSketchMode()) { BIF_convertSketch(); } @@ -2959,7 +2959,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case ESCKEY: if (G.qual == 0 && BIF_validSketchMode()) { - BIF_endStrokeSketch(); + BIF_cancelStrokeSketch(); } else if(G.qual==0) { if (G.vd->flag & V3D_DISPIMAGE) { diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 0687faaeec8..5734a0ee65b 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -75,6 +75,7 @@ #include "BIF_space.h" #include "BIF_screen.h" #include "BIF_toolbox.h" +#include "BIF_sketch.h" #include "BSE_view.h" #include "BSE_edit.h" /* For countall */ @@ -1885,7 +1886,7 @@ short view3d_opengl_select(unsigned int *buffer, unsigned int bufsize, short x1 draw_object(BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); } else if ((G.obedit && G.obedit->type==OB_ARMATURE)) { - if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING) + if (BIF_fullSketchMode()) { BDR_drawSketchNames(); } From 0107b2729a8c8b95bd25bc9274146d07ae446198 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 20 Oct 2008 20:16:33 +0000 Subject: [PATCH 025/252] Add undo push for quick strokes conversion --- source/blender/src/editarmature_sketch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 55bd9d69f20..948611ca029 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -2019,6 +2019,7 @@ int sk_paint(SK_Sketch *sketch, short mbut) { sk_convertStroke(stk); sk_removeStroke(sketch, stk); + BIF_undo_push("Convert Sketch"); allqueue(REDRAWBUTSEDIT, 0); } From 62c708624d6ebdec16768a7c462268940d418f52 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 21 Oct 2008 16:40:42 +0000 Subject: [PATCH 026/252] Draw subdivision preview for quick strokes and selected strokes (those that would be converted). Preview can be slightly off for quick strokes since subdivision will be affected by stroke smoothing applied only when a continuous stroke is finished. --- source/blender/src/editarmature_sketch.c | 339 +++++++++++++++++------ 1 file changed, 247 insertions(+), 92 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 948611ca029..73d99874574 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -120,6 +120,9 @@ SK_Point boneSnap; void sk_freeStroke(SK_Stroke *stk); void sk_freeSketch(SK_Sketch *sketch); +int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); +int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); + /******************** PEELING *********************************/ typedef struct SK_DepthPeel @@ -656,6 +659,110 @@ void sk_drawStroke(SK_Stroke *stk, int id, float color[3]) // glEnd(); } + +int drawStrokeByCorrelation(SK_Stroke *stk, int start, int end) +{ + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) + { + float head[3], tail[3]; + int bone_start = start; + int index; + + VECCOPY(head, stk->points[start].p); + + glColor3f(0, 1, 1); + glBegin(GL_POINTS); + + index = nextCorrelationSubdivision(stk, bone_start, end, head, tail); + while (index != -1) + { + glVertex3fv(tail); + + VECCOPY(head, tail); + bone_start = index; // start next bone from current index + + index = nextCorrelationSubdivision(stk, bone_start, end, head, tail); + } + + glEnd(); + + return 1; + } + else + { + return 0; + } +} + +int drawStrokeByLength(SK_Stroke *stk, int start, int end) +{ + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + { + float head[3], tail[3]; + int bone_start = start; + int index; + + VECCOPY(head, stk->points[start].p); + + glColor3f(0, 1, 1); + glBegin(GL_POINTS); + + index = nextLengthSubdivision(stk, bone_start, end, head, tail); + while (index != -1) + { + glVertex3fv(tail); + + VECCOPY(head, tail); + bone_start = index; // start next bone from current index + + index = nextLengthSubdivision(stk, bone_start, end, head, tail); + } + + glEnd(); + + return 1; + } + else + { + return 0; + } +} + +void sk_drawStrokeSubdivision(SK_Stroke *stk) +{ + int head_index = -1; + int i; + + for (i = 0; i < stk->nb_points; i++) + { + SK_Point *pt = stk->points + i; + + if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */ + { + if (head_index == -1) + { + head_index = i; + } + else + { + int done = 0; + + if (i - head_index > 1) + { + done = drawStrokeByCorrelation(stk, head_index, i); + + if (done == 0) + { + done = drawStrokeByLength(stk, head_index, i); + } + } + + head_index = i; + } + } + } +} + SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist) { SK_Point *pt = NULL; @@ -683,19 +790,22 @@ SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist) return pt; } -SK_Point *sk_snapPointArmature(ListBase *ebones, short mval[2], int *dist) +SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int *dist) { SK_Point *pt = NULL; EditBone *bone; for (bone = ebones->first; bone; bone = bone->next) { + float vec[3]; short pval[2]; int pdist; if ((bone->flag & BONE_CONNECTED) == 0) { - project_short_noclip(bone->head, pval); + VECCOPY(vec, bone->head); + Mat4MulVecfl(ob->obmat, vec); + project_short_noclip(vec, pval); pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); @@ -709,7 +819,9 @@ SK_Point *sk_snapPointArmature(ListBase *ebones, short mval[2], int *dist) } - project_short_noclip(bone->tail, pval); + VECCOPY(vec, bone->tail); + Mat4MulVecfl(ob->obmat, vec); + project_short_noclip(vec, pval); pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); @@ -851,7 +963,7 @@ int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *source_stk /* check on bones */ { - SK_Point *spt = sk_snapPointArmature(&G.edbo, dd->mval, &dist); + SK_Point *spt = sk_snapPointArmature(G.obedit, &G.edbo, dd->mval, &dist); if (spt != NULL) { @@ -1163,44 +1275,60 @@ float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], flo } } +int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) +{ + float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit; + float n[3]; + int i; + + for (i = start + 2; i < end; i++) + { + /* Calculate normal */ + VecSubf(n, stk->points[i].p, head); + + if (calcStrokeCorrelation(stk, start, i, stk->points[start].p, n) < correlation_threshold) + { + VECCOPY(p, stk->points[i - 1].p); + return i - 1; + } + } + + return -1; +} + EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, float invmat[][4]) { bArmature *arm= G.obedit->data; EditBone *lastBone = NULL; - float n[3]; - float CORRELATION_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit; if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) { EditBone *child = NULL; EditBone *parent = NULL; - int boneStart = start; - int i; + int bone_start = start; + int index; parent = addEditBone("Bone", &G.edbo, arm); VECCOPY(parent->head, stk->points[start].p); - Mat4MulVecfl(invmat, parent->head); - for (i = start + 1; i < end; i++) + index = nextCorrelationSubdivision(stk, bone_start, end, parent->head, parent->tail); + while (index != -1) { - /* Calculate normal */ - VecSubf(n, stk->points[i].p, parent->head); + Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */ - if (calcStrokeCorrelation(stk, boneStart, i, parent->head, n) < CORRELATION_THRESHOLD) - { - VECCOPY(parent->tail, stk->points[i - 1].p); - Mat4MulVecfl(invmat, parent->tail); + child = addEditBone("Bone", &G.edbo, arm); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED; + + parent = child; // new child is next parent + bone_start = index; // start next bone from current index - child = addEditBone("Bone", &G.edbo, arm); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED; - - parent = child; // new child is next parent - boneStart = i; // start next bone from current index - } + index = nextCorrelationSubdivision(stk, bone_start, end, parent->head, parent->tail); } + Mat4MulVecfl(invmat, parent->head); + VECCOPY(parent->tail, stk->points[end].p); Mat4MulVecfl(invmat, parent->tail); lastBone = parent; @@ -1209,6 +1337,74 @@ EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, floa return lastBone; } +int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) +{ + float lengthLimit = G.scene->toolsettings->skgen_length_limit; + int same = 1; + int i; + + i = start + 1; + while (i < end) + { + float *vec0 = stk->points[i - 1].p; + float *vec1 = stk->points[i].p; + + /* If lengthLimit hits the current segment */ + if (VecLenf(vec1, head) > lengthLimit) + { + if (same == 0) + { + float dv[3], off[3]; + float a, b, c, f; + + /* Solve quadratic distance equation */ + VecSubf(dv, vec1, vec0); + a = Inpf(dv, dv); + + VecSubf(off, vec0, head); + b = 2 * Inpf(dv, off); + + c = Inpf(off, off) - (lengthLimit * lengthLimit); + + f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a); + + //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); + + if (isnan(f) == 0 && f < 1.0f) + { + VECCOPY(p, dv); + VecMulf(p, f); + VecAddf(p, p, vec0); + } + else + { + VECCOPY(p, vec1); + } + } + else + { + float dv[3]; + + VecSubf(dv, vec1, vec0); + Normalize(dv); + + VECCOPY(p, dv); + VecMulf(p, lengthLimit); + VecAddf(p, p, head); + } + + return i - 1; /* restart at lower bound */ + } + else + { + i++; + same = 0; // Reset same + } + } + + return -1; +} + EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float invmat[][4]) { bArmature *arm= G.obedit->data; @@ -1218,81 +1414,30 @@ EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float inv { EditBone *child = NULL; EditBone *parent = NULL; - float lengthLimit = G.scene->toolsettings->skgen_length_limit; - int i; - int same = 0; + int bone_start = start; + int index; parent = addEditBone("Bone", &G.edbo, arm); VECCOPY(parent->head, stk->points[start].p); - i = start + 1; - while (i < end) + index = nextLengthSubdivision(stk, bone_start, end, parent->head, parent->tail); + while (index != -1) { - float *vec0 = stk->points[i - 1].p; - float *vec1 = stk->points[i].p; + Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */ - /* If lengthLimit hits the current segment */ - if (VecLenf(vec1, parent->head) > lengthLimit) - { - if (same == 0) - { - float dv[3], off[3]; - float a, b, c, f; - - /* Solve quadratic distance equation */ - VecSubf(dv, vec1, vec0); - a = Inpf(dv, dv); - - VecSubf(off, vec0, parent->head); - b = 2 * Inpf(dv, off); - - c = Inpf(off, off) - (lengthLimit * lengthLimit); - - f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a); - - //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); - - if (isnan(f) == 0 && f < 1.0f) - { - VECCOPY(parent->tail, dv); - VecMulf(parent->tail, f); - VecAddf(parent->tail, parent->tail, vec0); - } - else - { - VECCOPY(parent->tail, vec1); - } - } - else - { - float dv[3]; - - VecSubf(dv, vec1, vec0); - Normalize(dv); - - VECCOPY(parent->tail, dv); - VecMulf(parent->tail, lengthLimit); - VecAddf(parent->tail, parent->tail, parent->head); - } - - /* put head in correct space */ - Mat4MulVecfl(invmat, parent->head); - - child = addEditBone("Bone", &G.edbo, arm); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED; - - parent = child; // new child is next parent - - same = 1; // mark as same - } - else - { - i++; - same = 0; // Reset same - } + child = addEditBone("Bone", &G.edbo, arm); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED; + + parent = child; // new child is next parent + bone_start = index; // start next bone from current index + + index = nextLengthSubdivision(stk, bone_start, end, parent->head, parent->tail); } + + Mat4MulVecfl(invmat, parent->head); + VECCOPY(parent->tail, stk->points[end].p); Mat4MulVecfl(invmat, parent->tail); lastBone = parent; @@ -1899,6 +2044,11 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) for (stk = sketch->strokes.first; stk; stk = stk->next) { sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb)); + + if (stk->selected == 1) + { + sk_drawStrokeSubdivision(stk); + } } /* only draw gesture in active area */ @@ -1912,6 +2062,11 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) { SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); + if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) + { + sk_drawStrokeSubdivision(sketch->active_stroke); + } + if (last != NULL) { /* update point if in active area */ From 7c1639f032929d8e29066a2345e3dce6d5535d25 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 21 Oct 2008 17:59:56 +0000 Subject: [PATCH 027/252] Auto Roll: Bone roll to face the screen on painted strokes. --- source/blender/include/BIF_editarmature.h | 2 + source/blender/src/editarmature.c | 25 ++++++++ source/blender/src/editarmature_sketch.c | 72 +++++++++++++++++++---- 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 7211d71fcb6..df2965f4993 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -70,6 +70,8 @@ typedef struct EditBone EditBone *addEditBone(char *name, struct ListBase *ebones, struct bArmature *arm); +float rollBoneToVector(EditBone *bone, float new_up_axis[3]); + void adduplicate_armature(void); void addvert_armature(void); void add_primitiveArmature(int type); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 2ab58512657..d57d99ada66 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -1817,6 +1817,31 @@ void deselectall_armature(int toggle, int doundo) } } +/* adjust bone roll to align Z axis with vector + * vec is in local space and is normalized + */ +float rollBoneToVector(EditBone *bone, float new_up_axis[3]) +{ + float mat[3][3], nor[3], up_axis[3], vec[3]; + float roll; + + VecSubf(nor, bone->tail, bone->head); + + vec_roll_to_mat3(nor, 0, mat); + VECCOPY(up_axis, mat[2]); + + roll = NormalizedVecAngle2(new_up_axis, up_axis); + + Crossf(vec, up_axis, new_up_axis); + + if (Inpf(vec, nor) < 0) + { + roll = -roll; + } + + return roll; +} + /* Sets the roll value of selected bones, depending on the mode * mode == 0: their z-axes point upwards * mode == 1: their z-axes point towards 3d-cursor diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 73d99874574..6ec53b5618a 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -70,6 +70,7 @@ typedef enum SK_PMode typedef struct SK_Point { float p[3]; + float no[3]; SK_PType type; SK_PMode mode; } SK_Point; @@ -373,6 +374,18 @@ SK_Sketch* sk_createSketch() return sketch; } +void sk_initPoint(SK_Point *pt) +{ + VECCOPY(pt->no, G.vd->viewinv[2]); + Normalize(pt->no); + /* more init code here */ +} + +void sk_copyPoint(SK_Point *dst, SK_Point *src) +{ + memcpy(dst, src, sizeof(SK_Point)); +} + void sk_allocStrokeBuffer(SK_Stroke *stk) { stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer"); @@ -519,7 +532,8 @@ void sk_filterStroke(SK_Stroke *stk, int start, int end) SK_Point pt; float vec[3]; - pt.type = PT_CONTINUOUS; + sk_copyPoint(&pt, &old_points[j+1]); + pt.p[0] = 0; pt.p[1] = 0; pt.p[2] = 0; @@ -936,6 +950,8 @@ int sk_addStrokeDrawPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { SK_Point pt; + sk_initPoint(&pt); + sk_getStrokeDrawPoint(&pt, sketch, stk, dd); sk_appendStrokePoint(stk, &pt); @@ -983,8 +999,10 @@ int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *source_stk int sk_addStrokeSnapPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { - SK_Point pt; int point_added = 0; + SK_Point pt; + + sk_initPoint(&pt); point_added = sk_getStrokeSnapPoint(&pt, sketch, stk, dd); @@ -1105,9 +1123,11 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D int sk_addStrokeEmbedPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { - SK_Point pt; int point_added; + SK_Point pt; + sk_initPoint(&pt); + point_added = sk_getStrokeEmbedPoint(&pt, sketch, stk, dd); if (point_added) @@ -1224,6 +1244,22 @@ void sk_initDrawData(SK_DrawData *dd) } /********************************************/ +/* bone is assumed to be in GLOBAL space */ +void setBoneRollFromPoint(EditBone *bone, SK_Point *pt, float invmat[][4], float tmat[][3]) +{ + float tangent[3], cotangent[3], normal[3]; + + VecSubf(tangent, bone->tail, bone->head); + Crossf(cotangent, tangent, pt->no); + Crossf(normal, cotangent, tangent); + + Mat3MulVecfl(tmat, normal); + Normalize(normal); + + bone->roll = rollBoneToVector(bone, normal); + +} + float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], float n[3]) { int len = 2 + abs(end - start); @@ -1296,7 +1332,7 @@ int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3] return -1; } -EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, float invmat[][4]) +EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3]) { bArmature *arm= G.obedit->data; EditBone *lastBone = NULL; @@ -1314,6 +1350,8 @@ EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, floa index = nextCorrelationSubdivision(stk, bone_start, end, parent->head, parent->tail); while (index != -1) { + setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); + Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */ child = addEditBone("Bone", &G.edbo, arm); @@ -1327,9 +1365,11 @@ EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, floa index = nextCorrelationSubdivision(stk, bone_start, end, parent->head, parent->tail); } - Mat4MulVecfl(invmat, parent->head); - VECCOPY(parent->tail, stk->points[end].p); + + setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); + + Mat4MulVecfl(invmat, parent->head); Mat4MulVecfl(invmat, parent->tail); lastBone = parent; } @@ -1405,7 +1445,7 @@ int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], flo return -1; } -EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float invmat[][4]) +EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3]) { bArmature *arm= G.obedit->data; EditBone *lastBone = NULL; @@ -1419,10 +1459,11 @@ EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float inv parent = addEditBone("Bone", &G.edbo, arm); VECCOPY(parent->head, stk->points[start].p); - + index = nextLengthSubdivision(stk, bone_start, end, parent->head, parent->tail); while (index != -1) { + setBoneRollFromPoint(parent, &stk->points[index], invmat, tmat); Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */ child = addEditBone("Bone", &G.edbo, arm); @@ -1436,9 +1477,11 @@ EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float inv index = nextLengthSubdivision(stk, bone_start, end, parent->head, parent->tail); } - Mat4MulVecfl(invmat, parent->head); - VECCOPY(parent->tail, stk->points[end].p); + + setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); + + Mat4MulVecfl(invmat, parent->head); Mat4MulVecfl(invmat, parent->tail); lastBone = parent; } @@ -1452,6 +1495,7 @@ void sk_convertStroke(SK_Stroke *stk) SK_Point *head; EditBone *parent = NULL; float invmat[4][4]; /* move in caller function */ + float tmat[3][3]; int head_index = 0; int i; @@ -1459,6 +1503,9 @@ void sk_convertStroke(SK_Stroke *stk) Mat4Invert(invmat, G.obedit->obmat); + Mat3CpyMat4(tmat, G.obedit->obmat); + Mat3Transp(tmat); + for (i = 0; i < stk->nb_points; i++) { SK_Point *pt = stk->points + i; @@ -1477,11 +1524,11 @@ void sk_convertStroke(SK_Stroke *stk) if (i - head_index > 1) { - bone = subdivideStrokeByCorrelation(stk, head_index, i, invmat); + bone = subdivideStrokeByCorrelation(stk, head_index, i, invmat, tmat); if (bone == NULL) { - bone = subdivideStrokeByLength(stk, head_index, i, invmat); + bone = subdivideStrokeByLength(stk, head_index, i, invmat, tmat); } } @@ -1491,6 +1538,7 @@ void sk_convertStroke(SK_Stroke *stk) VECCOPY(bone->head, head->p); VECCOPY(bone->tail, pt->p); + setBoneRollFromPoint(bone, pt, invmat, tmat); Mat4MulVecfl(invmat, bone->head); Mat4MulVecfl(invmat, bone->tail); From a96863b65c172d23e82b5bf1a55dcb298ad25a03 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 21 Oct 2008 22:38:32 +0000 Subject: [PATCH 028/252] Fixed Subdivision method (subdivide in a set number of bones). Subdivision method cleanup (reuse more code) --- source/blender/makesdna/DNA_scene_types.h | 4 +- source/blender/src/drawview.c | 3 + source/blender/src/editarmature_sketch.c | 265 +++++++++------------- 3 files changed, 119 insertions(+), 153 deletions(-) diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 7ecc524fe7a..9b7bfbebb3d 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -440,10 +440,11 @@ typedef struct ToolSettings { /* Skeleton Sketching */ char bone_sketching; + char skgen_subdivision_number; /* Alt+RMB option */ char edge_mode; - char pad3[3]; + char pad3[2]; } ToolSettings; /* Used by all brushes to store their properties, which can be directly set @@ -846,6 +847,7 @@ typedef struct Scene { #define SKGEN_CUT_LENGTH 8 #define SKGEN_CUT_ANGLE 16 #define SKGEN_CUT_CORRELATION 32 +#define SKGEN_CUT_FIXED 64 #define SKGEN_SUB_LENGTH 0 #define SKGEN_SUB_ANGLE 1 diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 214a5f42716..66d9417e79d 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2317,6 +2317,9 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_DIFF, "Correlation", 10, 135, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation"); uiDefButF(block, NUM, B_DIFF, "T:", 70, 135, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); + uiDefButBitS(block, TOG, SKGEN_CUT_FIXED, B_DIFF, "Fixed", 10, 115, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on a fixed number of bones"); + uiDefButC(block, NUM, B_DIFF, "N:", 70, 115, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,0, 100, 1, 0, "Specify the bones to subdivide into"); + uiBlockEndAlign(block); if(yco < 0) uiNewPanelHeight(block, height-yco); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 6ec53b5618a..3b3b0679c39 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -118,9 +118,12 @@ SK_Point boneSnap; /******************** PROTOTYPES ******************************/ +typedef int(NextSubdivisionFunc)(SK_Stroke*, int, int, float[3], float[3]); + void sk_freeStroke(SK_Stroke *stk); void sk_freeSketch(SK_Sketch *sketch); +int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); @@ -673,73 +676,29 @@ void sk_drawStroke(SK_Stroke *stk, int id, float color[3]) // glEnd(); } - -int drawStrokeByCorrelation(SK_Stroke *stk, int start, int end) +void drawSubdividedStrokeBy(SK_Stroke *stk, int start, int end, NextSubdivisionFunc next_subdividion) { - if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) + float head[3], tail[3]; + int bone_start = start; + int index; + + VECCOPY(head, stk->points[start].p); + + glColor3f(0, 1, 1); + glBegin(GL_POINTS); + + index = next_subdividion(stk, bone_start, end, head, tail); + while (index != -1) { - float head[3], tail[3]; - int bone_start = start; - int index; - - VECCOPY(head, stk->points[start].p); + glVertex3fv(tail); - glColor3f(0, 1, 1); - glBegin(GL_POINTS); - - index = nextCorrelationSubdivision(stk, bone_start, end, head, tail); - while (index != -1) - { - glVertex3fv(tail); - - VECCOPY(head, tail); - bone_start = index; // start next bone from current index + VECCOPY(head, tail); + bone_start = index; // start next bone from current index - index = nextCorrelationSubdivision(stk, bone_start, end, head, tail); - } - - glEnd(); - - return 1; - } - else - { - return 0; - } -} - -int drawStrokeByLength(SK_Stroke *stk, int start, int end) -{ - if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) - { - float head[3], tail[3]; - int bone_start = start; - int index; - - VECCOPY(head, stk->points[start].p); - - glColor3f(0, 1, 1); - glBegin(GL_POINTS); - - index = nextLengthSubdivision(stk, bone_start, end, head, tail); - while (index != -1) - { - glVertex3fv(tail); - - VECCOPY(head, tail); - bone_start = index; // start next bone from current index - - index = nextLengthSubdivision(stk, bone_start, end, head, tail); - } - - glEnd(); - - return 1; - } - else - { - return 0; + index = next_subdividion(stk, bone_start, end, head, tail); } + + glEnd(); } void sk_drawStrokeSubdivision(SK_Stroke *stk) @@ -759,16 +718,21 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) } else { - int done = 0; - if (i - head_index > 1) { - done = drawStrokeByCorrelation(stk, head_index, i); - - if (done == 0) + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) { - done = drawStrokeByLength(stk, head_index, i); + drawSubdividedStrokeBy(stk, head_index, i, nextCorrelationSubdivision); } + else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + { + drawSubdividedStrokeBy(stk, head_index, i, nextLengthSubdivision); + } + else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_FIXED) + { + drawSubdividedStrokeBy(stk, head_index, i, nextFixedSubdivision); + } + } head_index = i; @@ -1311,13 +1275,52 @@ float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], flo } } +int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) +{ + static float stroke_length = 0; + static float current_length; + static char n; + float length_threshold; + int i; + + if (stroke_length == 0) + { + current_length = 0; + for (i = start + 1; i < end; i++) + { + stroke_length += VecLenf(stk->points[i].p, stk->points[i - 1].p); + } + + n = 0; + current_length = 0; + } + + n++; + + length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number; + + for (i = start + 1; i < end; i++) + { + current_length += VecLenf(stk->points[i].p, stk->points[i - 1].p); + + if (current_length >= length_threshold) + { + VECCOPY(p, stk->points[i].p); + return i; + } + } + + stroke_length = 0; + + return -1; +} int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) { float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit; float n[3]; int i; - for (i = start + 2; i < end; i++) + for (i = start + 2; i <= end; i++) { /* Calculate normal */ VecSubf(n, stk->points[i].p, head); @@ -1332,51 +1335,6 @@ int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3] return -1; } -EditBone * subdivideStrokeByCorrelation(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3]) -{ - bArmature *arm= G.obedit->data; - EditBone *lastBone = NULL; - - if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) - { - EditBone *child = NULL; - EditBone *parent = NULL; - int bone_start = start; - int index; - - parent = addEditBone("Bone", &G.edbo, arm); - VECCOPY(parent->head, stk->points[start].p); - - index = nextCorrelationSubdivision(stk, bone_start, end, parent->head, parent->tail); - while (index != -1) - { - setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); - - Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */ - - child = addEditBone("Bone", &G.edbo, arm); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED; - - parent = child; // new child is next parent - bone_start = index; // start next bone from current index - - index = nextCorrelationSubdivision(stk, bone_start, end, parent->head, parent->tail); - } - - VECCOPY(parent->tail, stk->points[end].p); - - setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); - - Mat4MulVecfl(invmat, parent->head); - Mat4MulVecfl(invmat, parent->tail); - lastBone = parent; - } - - return lastBone; -} - int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) { float lengthLimit = G.scene->toolsettings->skgen_length_limit; @@ -1384,7 +1342,7 @@ int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], flo int i; i = start + 1; - while (i < end) + while (i <= end) { float *vec0 = stk->points[i - 1].p; float *vec1 = stk->points[i].p; @@ -1445,50 +1403,47 @@ int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], flo return -1; } -EditBone * subdivideStrokeByLength(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3]) +EditBone * subdivideStrokeBy(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion) { - bArmature *arm= G.obedit->data; + bArmature *arm = G.obedit->data; EditBone *lastBone = NULL; + EditBone *child = NULL; + EditBone *parent = NULL; + int bone_start = start; + int index; - if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + parent = addEditBone("Bone", &G.edbo, arm); + VECCOPY(parent->head, stk->points[start].p); + + index = next_subdividion(stk, bone_start, end, parent->head, parent->tail); + while (index != -1) { - EditBone *child = NULL; - EditBone *parent = NULL; - int bone_start = start; - int index; + setBoneRollFromPoint(parent, &stk->points[index], invmat, tmat); + Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */ + + child = addEditBone("Bone", &G.edbo, arm); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED; - parent = addEditBone("Bone", &G.edbo, arm); - VECCOPY(parent->head, stk->points[start].p); - - index = nextLengthSubdivision(stk, bone_start, end, parent->head, parent->tail); - while (index != -1) - { - setBoneRollFromPoint(parent, &stk->points[index], invmat, tmat); - Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */ + parent = child; // new child is next parent + bone_start = index; // start next bone from current index - child = addEditBone("Bone", &G.edbo, arm); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED; - - parent = child; // new child is next parent - bone_start = index; // start next bone from current index - - index = nextLengthSubdivision(stk, bone_start, end, parent->head, parent->tail); - } - - VECCOPY(parent->tail, stk->points[end].p); - - setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); - - Mat4MulVecfl(invmat, parent->head); - Mat4MulVecfl(invmat, parent->tail); - lastBone = parent; + index = next_subdividion(stk, bone_start, end, parent->head, parent->tail); } + + VECCOPY(parent->tail, stk->points[end].p); + + setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); + + Mat4MulVecfl(invmat, parent->head); + Mat4MulVecfl(invmat, parent->tail); + lastBone = parent; return lastBone; } + void sk_convertStroke(SK_Stroke *stk) { bArmature *arm= G.obedit->data; @@ -1524,11 +1479,17 @@ void sk_convertStroke(SK_Stroke *stk) if (i - head_index > 1) { - bone = subdivideStrokeByCorrelation(stk, head_index, i, invmat, tmat); - - if (bone == NULL) + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) { - bone = subdivideStrokeByLength(stk, head_index, i, invmat, tmat); + bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextCorrelationSubdivision); + } + else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + { + bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextLengthSubdivision); + } + else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_FIXED) + { + bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextFixedSubdivision); } } From 0033293b1e0c0bd29c0e6bb02e61c90f3a29c5ae Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 22 Oct 2008 18:08:06 +0000 Subject: [PATCH 029/252] Correct handler for floating panel (close button wouldn't work) Redraw event on floating panel buttons Correct limit for Number of Fixed subdivision button Fix off by one error in fixed subdivision loop. --- source/blender/src/drawview.c | 16 ++++++++-------- source/blender/src/editarmature_sketch.c | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 66d9417e79d..cb3cb3379f1 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2289,9 +2289,9 @@ static void view3d_panel_bonesketch_spaces(short cntrl) /* replace with check call to sketching lib */ if (G.obedit && G.obedit->type == OB_ARMATURE) { - block= uiNewBlock(&curarea->uiblocks, "view3d_panel_transform", UI_EMBOSS, UI_HELV, curarea->win); + block= uiNewBlock(&curarea->uiblocks, "view3d_panel_bonesketch_spaces", UI_EMBOSS, UI_HELV, curarea->win); uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); - uiSetPanelHandler(VIEW3D_HANDLER_TRANSFORM); // for close and esc + uiSetPanelHandler(VIEW3D_HANDLER_BONESKETCH); // for close and esc if(uiNewPanel(curarea, block, "Bone Sketching", "View3d", 10, 230, 318, height)==0) return; @@ -2311,14 +2311,14 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_DIFF, "Length", 10, 155, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs in bones of equal length"); - uiDefButF(block, NUM, B_DIFF, "L:", 70, 155, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); + uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_REDR, "Length", 10, 155, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs in bones of equal length"); + uiDefButF(block, NUM, B_REDR, "L:", 70, 155, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); - uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_DIFF, "Correlation", 10, 135, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation"); - uiDefButF(block, NUM, B_DIFF, "T:", 70, 135, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); + uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_REDR, "Correlation", 10, 135, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation"); + uiDefButF(block, NUM, B_REDR, "T:", 70, 135, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); - uiDefButBitS(block, TOG, SKGEN_CUT_FIXED, B_DIFF, "Fixed", 10, 115, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on a fixed number of bones"); - uiDefButC(block, NUM, B_DIFF, "N:", 70, 115, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,0, 100, 1, 0, "Specify the bones to subdivide into"); + uiDefButBitS(block, TOG, SKGEN_CUT_FIXED, B_REDR, "Fixed", 10, 115, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on a fixed number of bones"); + uiDefButC(block, NUM, B_REDR, "N:", 70, 115, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Specify the bones to subdivide into"); uiBlockEndAlign(block); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 3b3b0679c39..1d40395f6db 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1286,7 +1286,7 @@ int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], floa if (stroke_length == 0) { current_length = 0; - for (i = start + 1; i < end; i++) + for (i = start + 1; i <= end; i++) { stroke_length += VecLenf(stk->points[i].p, stk->points[i - 1].p); } @@ -1299,6 +1299,7 @@ int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], floa length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number; + /* < and not <= because we don't care about end, it is P_EXACT anyway */ for (i = start + 1; i < end; i++) { current_length += VecLenf(stk->points[i].p, stk->points[i - 1].p); From 229ae0275fecbc1a9276a574651f964dcfe2d291 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 22 Oct 2008 20:17:11 +0000 Subject: [PATCH 030/252] Gesture for delete selected (experimental): figure 8 (gesture crossing on itself twice) --- source/blender/src/editarmature_sketch.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 1d40395f6db..5f150a20941 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -120,6 +120,8 @@ SK_Point boneSnap; typedef int(NextSubdivisionFunc)(SK_Stroke*, int, int, float[3], float[3]); +void sk_deleteSelectedStrokes(SK_Sketch *sketch); + void sk_freeStroke(SK_Stroke *stk); void sk_freeSketch(SK_Sketch *sketch); @@ -1661,7 +1663,7 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) { - float CORRELATION_THRESHOLD = 0.995f; + float CORRELATION_THRESHOLD = 0.99f; float *vec; int i, j; @@ -1911,6 +1913,11 @@ void sk_applyGesture(SK_Sketch *sketch) BIF_undo_push("Convert Sketch"); allqueue(REDRAWBUTSEDIT, 0); } + else if (nb_segments > 2 && nb_self_intersections == 2) + { + sk_deleteSelectedStrokes(sketch); + BIF_undo_push("Convert Sketch"); + } sk_freeStroke(segments); BLI_freelistN(&intersections); From 42075d5229ca04e4be6f21eca5077857c5e51116 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 22 Oct 2008 20:30:02 +0000 Subject: [PATCH 031/252] Snapping sketch to bone was using untransformed head/tail. Fixed. --- source/blender/src/editarmature_sketch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 5f150a20941..3a3ed4f9ce8 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -793,7 +793,7 @@ SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int { *dist = pdist; pt = &boneSnap; - VECCOPY(pt->p, bone->head); + VECCOPY(pt->p, vec); pt->type = PT_EXACT; } } @@ -809,7 +809,7 @@ SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int { *dist = pdist; pt = &boneSnap; - VECCOPY(pt->p, bone->tail); + VECCOPY(pt->p, vec); pt->type = PT_EXACT; } } From 3db27c9acbf0fa525b473e6b0d869275147ca487 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 27 Oct 2008 23:25:08 +0000 Subject: [PATCH 032/252] Sketching: Gesture to flip stroke (circular arc intersecting the stroke twice). Some name cleanup. --- source/blender/src/editarmature_sketch.c | 114 +++++++++++++++++++---- 1 file changed, 96 insertions(+), 18 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 3a3ed4f9ce8..080564e9387 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -98,8 +98,9 @@ typedef struct SK_Intersection { struct SK_Intersection *next, *prev; SK_Stroke *stroke; - int start; - int end; + int before; + int after; + int gesture_index; float p[3]; } SK_Intersection; @@ -499,6 +500,22 @@ void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk) sk_freeStroke(stk); } +void sk_reverseStroke(SK_Stroke *stk) +{ + SK_Point *old_points = stk->points; + int i = 0; + + sk_allocStrokeBuffer(stk); + + for (i = 0; i < stk->nb_points; i++) + { + sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i); + } + + MEM_freeN(old_points); +} + + void sk_cancelStroke(SK_Sketch *sketch) { if (sketch->active_stroke != NULL) @@ -1577,8 +1594,9 @@ int sk_getSelfIntersections(ListBase *list, SK_Stroke *gesture) { SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); - isect->start = s_i; - isect->end = g_i + 1; + isect->gesture_index = g_i; + isect->before = s_i; + isect->after = s_i + 1; isect->stroke = gesture; VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p); @@ -1632,8 +1650,9 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) float ray_start[3], ray_end[3]; short mval[2]; - isect->start = s_i; - isect->end = s_i + 1; + isect->gesture_index = g_i; + isect->before = s_i; + isect->after = s_i + 1; isect->stroke = stk; mval[0] = (short)(vi[0]); @@ -1703,7 +1722,7 @@ void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, S pt.mode = PT_PROJECT; /* take mode from neighbouring points */ VECCOPY(pt.p, isect->p); - sk_insertStrokePoint(isect->stroke, &pt, isect->end); + sk_insertStrokePoint(isect->stroke, &pt, isect->after); } } @@ -1743,19 +1762,19 @@ void sk_applyTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, pt.mode = PT_PROJECT; /* take mode from neighbouring points */ VECCOPY(pt.p, isect->p); - VecSubf(stroke_dir, isect->stroke->points[isect->end].p, isect->stroke->points[isect->start].p); + VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p); /* same direction, trim end */ if (Inpf(stroke_dir, trim_dir) > 0) { - sk_replaceStrokePoint(isect->stroke, &pt, isect->end); - sk_trimStroke(isect->stroke, 0, isect->end); + sk_replaceStrokePoint(isect->stroke, &pt, isect->after); + sk_trimStroke(isect->stroke, 0, isect->after); } /* else, trim start */ else { - sk_replaceStrokePoint(isect->stroke, &pt, isect->start); - sk_trimStroke(isect->stroke, isect->start, isect->stroke->nb_points - 1); + sk_replaceStrokePoint(isect->stroke, &pt, isect->before); + sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1); } } @@ -1821,8 +1840,8 @@ int sk_detectMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, int start_index, end_index; int i; - start_index = MIN2(isect->end, isect->next->end); - end_index = MAX2(isect->start, isect->next->start); + start_index = MIN2(isect->after, isect->next->after); + end_index = MAX2(isect->before, isect->next->before); for (i = start_index; i <= end_index; i++) { @@ -1852,14 +1871,14 @@ void sk_applyMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, /* check if it circled around an exact point */ for (isect = list->first; isect; isect = isect->next) { - /* only delete strokes that are crossed twice */ + /* only merge strokes that are crossed twice */ if (isect->next && isect->next->stroke == isect->stroke) { int start_index, end_index; int i; - start_index = MIN2(isect->end, isect->next->end); - end_index = MAX2(isect->start, isect->next->start); + start_index = MIN2(isect->after, isect->next->after); + end_index = MAX2(isect->before, isect->next->before); for (i = start_index; i <= end_index; i++) { @@ -1876,6 +1895,62 @@ void sk_applyMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, } } +int sk_detectReverseGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + SK_Intersection *isect; + + /* check if it circled around an exact point */ + for (isect = list->first; isect; isect = isect->next) + { + /* only delete strokes that are crossed twice */ + if (isect->next && isect->next->stroke == isect->stroke) + { + float start_v[3], end_v[3]; + float angle; + + if (isect->gesture_index < isect->next->gesture_index) + { + VecSubf(start_v, isect->p, gesture->points[0].p); + VecSubf(end_v, sk_lastStrokePoint(gesture)->p, isect->next->p); + } + else + { + VecSubf(start_v, isect->next->p, gesture->points[0].p); + VecSubf(end_v, sk_lastStrokePoint(gesture)->p, isect->p); + } + + angle = VecAngle2(start_v, end_v); + + if (angle > 120) + { + return 1; + } + + /* skip next */ + isect = isect->next; + } + } + + return 0; +} + +void sk_applyReverseGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + SK_Intersection *isect; + + for (isect = list->first; isect; isect = isect->next) + { + /* only reverse strokes that are crossed twice */ + if (isect->next && isect->next->stroke == isect->stroke) + { + sk_reverseStroke(isect->stroke); + + /* skip next */ + isect = isect->next; + } + } +} + void sk_applyGesture(SK_Sketch *sketch) { ListBase intersections; @@ -1907,6 +1982,10 @@ void sk_applyGesture(SK_Sketch *sketch) { sk_applyMergeGesture(sketch, sketch->gesture, &intersections, segments); } + else if (nb_segments > 2 && nb_intersections == 2 && sk_detectReverseGesture(sketch, sketch->gesture, &intersections, segments)) + { + sk_applyReverseGesture(sketch, sketch->gesture, &intersections, segments); + } else if (nb_segments > 2 && nb_self_intersections == 1) { sk_convert(sketch); @@ -1916,7 +1995,6 @@ void sk_applyGesture(SK_Sketch *sketch) else if (nb_segments > 2 && nb_self_intersections == 2) { sk_deleteSelectedStrokes(sketch); - BIF_undo_push("Convert Sketch"); } sk_freeStroke(segments); From 1a7bc63933454a412ac404b0c427b95f72317041 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 29 Oct 2008 21:49:58 +0000 Subject: [PATCH 033/252] moving stuff home. first draft for template retargetting --- source/blender/include/BIF_retarget.h | 133 +++++++++ ...autoarmature.c => editarmature_retarget.c} | 279 +++++++++--------- source/blender/src/editarmature_sketch.c | 53 +++- 3 files changed, 325 insertions(+), 140 deletions(-) create mode 100644 source/blender/include/BIF_retarget.h rename source/blender/src/{autoarmature.c => editarmature_retarget.c} (94%) diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h new file mode 100644 index 00000000000..df46d309a94 --- /dev/null +++ b/source/blender/include/BIF_retarget.h @@ -0,0 +1,133 @@ +/** + * $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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BIF_RETARGET_H +#define BIF_RETARGET_H + +#include "DNA_listBase.h" + +#include "BLI_graph.h" +#include "BLI_ghash.h" +#include "BLI_threads.h" + +#include "reeb.h" + +struct EditBone; + +struct RigJoint; +struct RigGraph; +struct RigNode; +struct RigArc; +struct RigEdge; + +#define USE_THREADS + +typedef struct RigGraph { + ListBase arcs; + ListBase nodes; + ListBase controls; + + ListBase* editbones; + + float length; + + FreeArc free_arc; + FreeNode free_node; + RadialSymmetry radial_symmetry; + AxialSymmetry axial_symmetry; + /*********************************/ + + struct RigNode *head; + ReebGraph *link_mesh; + + + struct ThreadedWorker *worker; + + GHash *bones_map; /* map of editbones by name */ + GHash *controls_map; /* map of rigcontrols by bone pointer */ + + Object *ob; +} RigGraph; + +typedef struct RigNode { + void *next, *prev; + float p[3]; + int flag; + + int degree; + struct BArc **arcs; + + int subgraph_index; + + int symmetry_level; + int symmetry_flag; + float symmetry_axis[3]; + /*********************************/ + + ReebNode *link_mesh; +} RigNode; + +typedef struct RigArc { + void *next, *prev; + RigNode *head, *tail; + int flag; + + float length; + + int symmetry_level; + int symmetry_group; + int symmetry_flag; + /*********************************/ + + ListBase edges; + int count; + ReebArc *link_mesh; +} RigArc; + +typedef struct RigEdge { + struct RigEdge *next, *prev; + float head[3], tail[3]; + float length; + float angle; + EditBone *bone; + float up_axis[3]; +} RigEdge; + +/* Control flags */ +#define RIG_CTRL_DONE 1 +#define RIG_CTRL_PARENT_DEFORM 2 +#define RIG_CTRL_FIT_ROOT 4 +#define RIG_CTRL_FIT_BONE 8 + +typedef struct RigControl { + struct RigControl *next, *prev; + float head[3], tail[3]; + EditBone *bone; + EditBone *link; + float up_axis[3]; + float offset[3]; + int flag; +} RigControl; + +void BIF_retargetArc(ReebArc *earc); + +#endif /* BIF_RETARGET_H */ diff --git a/source/blender/src/autoarmature.c b/source/blender/src/editarmature_retarget.c similarity index 94% rename from source/blender/src/autoarmature.c rename to source/blender/src/editarmature_retarget.c index b0a7a2ab5cc..51e1e789d8e 100644 --- a/source/blender/src/autoarmature.c +++ b/source/blender/src/editarmature_retarget.c @@ -62,6 +62,7 @@ #include "BKE_armature.h" #include "BIF_editarmature.h" +#include "BIF_retarget.h" #include "BIF_space.h" #include "PIL_time.h" @@ -72,100 +73,6 @@ /************ RIG RETARGET DATA STRUCTURES ***************/ -struct RigJoint; -struct RigGraph; -struct RigNode; -struct RigArc; -struct RigEdge; - -//#define USE_THREADS - -typedef struct RigGraph { - ListBase arcs; - ListBase nodes; - - float length; - - FreeArc free_arc; - FreeNode free_node; - RadialSymmetry radial_symmetry; - AxialSymmetry axial_symmetry; - /*********************************/ - - struct RigNode *head; - ReebGraph *link_mesh; - - ListBase editbones; - - ListBase controls; - struct ThreadedWorker *worker; - - GHash *bones_map; /* map of editbones by name */ - GHash *controls_map; /* map of rigcontrols by bone pointer */ - - Object *ob; -} RigGraph; - -typedef struct RigNode { - void *next, *prev; - float p[3]; - int flag; - - int degree; - struct BArc **arcs; - - int subgraph_index; - - int symmetry_level; - int symmetry_flag; - float symmetry_axis[3]; - /*********************************/ - - ReebNode *link_mesh; -} RigNode; - -typedef struct RigArc { - void *next, *prev; - RigNode *head, *tail; - int flag; - - float length; - - int symmetry_level; - int symmetry_group; - int symmetry_flag; - /*********************************/ - - ListBase edges; - int count; - ReebArc *link_mesh; -} RigArc; - -typedef struct RigEdge { - struct RigEdge *next, *prev; - float head[3], tail[3]; - float length; - float angle; - EditBone *bone; - float up_axis[3]; -} RigEdge; - -/* Control flags */ -#define RIG_CTRL_DONE 1 -#define RIG_CTRL_PARENT_DEFORM 2 -#define RIG_CTRL_FIT_ROOT 4 -#define RIG_CTRL_FIT_BONE 8 - -typedef struct RigControl { - struct RigControl *next, *prev; - float head[3], tail[3]; - EditBone *bone; - EditBone *link; - float up_axis[3]; - float offset[3]; - int flag; -} RigControl; - typedef struct MemoNode { float weight; int next; @@ -197,7 +104,6 @@ typedef enum ARC_USED = 2 } ArcUsageFlags; - RigGraph *GLOBAL_RIGG = NULL; /*******************************************************************************************************/ @@ -291,14 +197,18 @@ void RIG_freeRigArc(BArc *arc) void RIG_freeRigGraph(BGraph *rg) { + RigGraph *rigg = (RigGraph*)rg; BNode *node; BArc *arc; #ifdef USE_THREADS - BLI_destroy_worker(((RigGraph*)rg)->worker); + BLI_destroy_worker(rigg->worker); #endif - REEB_freeGraph(((RigGraph*)rg)->link_mesh); + if (rigg->link_mesh) + { + REEB_freeGraph(rigg->link_mesh); + } for (arc = rg->arcs.first; arc; arc = arc->next) { @@ -312,12 +222,16 @@ void RIG_freeRigGraph(BGraph *rg) } BLI_freelistN(&rg->nodes); - BLI_freelistN(&((RigGraph*)rg)->controls); + BLI_freelistN(&rigg->controls); - BLI_ghash_free(((RigGraph*)rg)->bones_map, NULL, NULL); - BLI_ghash_free(((RigGraph*)rg)->controls_map, NULL, NULL); + BLI_ghash_free(rigg->bones_map, NULL, NULL); + BLI_ghash_free(rigg->controls_map, NULL, NULL); - BLI_freelistN(&((RigGraph*)rg)->editbones); + if (rigg->editbones != &G.edbo) + { + BLI_freelistN(rigg->editbones); + MEM_freeN(rigg->editbones); + } MEM_freeN(rg); } @@ -1034,7 +948,7 @@ static void RIG_removeUneededOffsets(RigGraph *rg) } } -static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node) +static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node, int selected) { EditBone *bone, *last_bone = root_bone; RigArc *arc = NULL; @@ -1044,41 +958,44 @@ static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bo { int nb_children; - if ((bone->flag & BONE_NO_DEFORM) == 0) - { - BLI_ghash_insert(rg->bones_map, bone->name, bone); - - if (arc == NULL) + if (selected == 0 || (bone->flag & BONE_SELECTED)) + { + if ((bone->flag & BONE_NO_DEFORM) == 0) { - arc = newRigArc(rg); + BLI_ghash_insert(rg->bones_map, bone->name, bone); + + if (arc == NULL) + { + arc = newRigArc(rg); + + if (starting_node == NULL) + { + starting_node = newRigNodeHead(rg, arc, root_bone->head); + } + else + { + addRigNodeHead(rg, arc, starting_node); + } + } - if (starting_node == NULL) + if (bone->parent && (bone->flag & BONE_CONNECTED) == 0) { - starting_node = newRigNodeHead(rg, arc, root_bone->head); + RIG_addEdgeToArc(arc, bone->head, NULL); } - else + + RIG_addEdgeToArc(arc, bone->tail, bone); + + last_bone = bone; + + if (strcmp(bone->name, "head") == 0) { - addRigNodeHead(rg, arc, starting_node); + contain_head = 1; } } - - if (bone->parent && (bone->flag & BONE_CONNECTED) == 0) + else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) /* ignore locked bones */ { - RIG_addEdgeToArc(arc, bone->head, NULL); + RIG_addControlBone(rg, bone); } - - RIG_addEdgeToArc(arc, bone->tail, bone); - - last_bone = bone; - - if (strcmp(bone->name, "head") == 0) - { - contain_head = 1; - } - } - else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) /* ignore locked bones */ - { - RIG_addControlBone(rg, bone); } nb_children = countEditBoneChildren(list, bone); @@ -1099,7 +1016,7 @@ static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bo for (i = 0; i < nb_children; i++) { root_bone = nextEditBoneChild(list, bone, i); - RIG_arcFromBoneChain(rg, list, root_bone, end_node); + RIG_arcFromBoneChain(rg, list, root_bone, end_node, selected); } /* arc ends here, break */ @@ -1266,21 +1183,30 @@ void RIG_printGraph(RigGraph *rg) /*******************************************************************************************************/ -static RigGraph *armatureToGraph(Object *ob, bArmature *arm) +RigGraph *armatureToGraph(Object *ob, bArmature *arm) { EditBone *ebone; RigGraph *rg; rg = newRigGraph(); - make_boneList(&rg->editbones, &arm->bonebase, NULL); + if (G.obedit == ob) + { + rg->editbones = &G.edbo; + } + else + { + rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones"); + make_boneList(rg->editbones, &arm->bonebase, NULL); + } + rg->ob = ob; /* Do the rotations */ - for (ebone = rg->editbones.first; ebone; ebone=ebone->next){ + for (ebone = rg->editbones->first; ebone; ebone=ebone->next){ if (ebone->parent == NULL) { - RIG_arcFromBoneChain(rg, &rg->editbones, ebone, NULL); + RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 0); } } @@ -1306,6 +1232,54 @@ static RigGraph *armatureToGraph(Object *ob, bArmature *arm) return rg; } +RigGraph *armatureSelectedToGraph(Object *ob, bArmature *arm) +{ + EditBone *ebone; + RigGraph *rg; + + rg = newRigGraph(); + + if (G.obedit == ob) + { + rg->editbones = &G.edbo; + } + else + { + rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones"); + make_boneList(rg->editbones, &arm->bonebase, NULL); + } + + rg->ob = ob; + + /* Do the rotations */ + for (ebone = rg->editbones->first; ebone; ebone=ebone->next){ + if (ebone->parent == NULL) + { + RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 1); + } + } + + BLI_removeDoubleNodes((BGraph*)rg, 0.001); + + RIG_removeNormalNodes(rg); + + RIG_removeUneededOffsets(rg); + + BLI_buildAdjacencyList((BGraph*)rg); + + RIG_findHead(rg); + + BLI_markdownSymmetry((BGraph*)rg, (BNode*)rg->head, G.scene->toolsettings->skgen_symmetry_limit); + + RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */ + + if (BLI_isGraphCyclic((BGraph*)rg)) + { + printf("armature cyclic\n"); + } + + return rg; +} /************************************ GENERATING *****************************************************/ static EditBone *add_editbonetolist(char *name, ListBase *list) @@ -1356,7 +1330,7 @@ EditBone * generateBonesForArc(RigGraph *rigg, ReebArc *arc, ReebNode *head, Ree int total = 0; int boneStart = iter.start; - parent = add_editbonetolist("Bone", &rigg->editbones); + parent = add_editbonetolist("Bone", rigg->editbones); parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; VECCOPY(parent->head, head->p); @@ -1405,7 +1379,7 @@ EditBone * generateBonesForArc(RigGraph *rigg, ReebArc *arc, ReebNode *head, Ree { VECCOPY(parent->tail, btail); - child = add_editbonetolist("Bone", &rigg->editbones); + child = add_editbonetolist("Bone", rigg->editbones); VECCOPY(child->head, parent->tail); child->parent = parent; child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; @@ -2836,7 +2810,7 @@ static void adjustGraphs(RigGraph *rigg) #endif /* Turn the list into an armature */ - editbones_to_armature(&rigg->editbones, rigg->ob); + editbones_to_armature(rigg->editbones, rigg->ob); BIF_undo_push("Retarget Skeleton"); } @@ -2865,7 +2839,7 @@ static void retargetGraphs(RigGraph *rigg) #endif /* Turn the list into an armature */ - editbones_to_armature(&rigg->editbones, rigg->ob); + editbones_to_armature(rigg->editbones, rigg->ob); } @@ -2950,6 +2924,37 @@ void BIF_retargetArmature() allqueue(REDRAWVIEW3D, 0); } +void BIF_retargetArc(ReebArc *earc) +{ + Object *ob; + RigGraph *rigg; + RigArc *iarc; + bArmature *arm; + + ob = G.obedit; + arm = ob->data; + + rigg = armatureSelectedToGraph(ob, arm); + + iarc = rigg->arcs.first; + + iarc->link_mesh = earc; + iarc->head->link_mesh = earc->head; + iarc->tail->link_mesh = earc->tail; + + retargetArctoArc(rigg, iarc, iarc->head); + +#ifdef USE_THREADS + BLI_end_worker(rigg->worker); +#endif + + //RIG_freeRigGraph((BGraph*)rigg); + + BIF_undo_push("Retarget Arc"); + + allqueue(REDRAWVIEW3D, 0); +} + void BIF_adjustRetarget() { if (GLOBAL_RIGG) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 080564e9387..0cd0cd8ff29 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -50,9 +50,11 @@ #include "BIF_mywindow.h" #include "BIF_editarmature.h" #include "BIF_sketch.h" +#include "BIF_retarget.h" #include "blendef.h" #include "mydevice.h" +#include "reeb.h" typedef enum SK_PType { @@ -126,6 +128,8 @@ void sk_deleteSelectedStrokes(SK_Sketch *sketch); void sk_freeStroke(SK_Stroke *stk); void sk_freeSketch(SK_Sketch *sketch); +SK_Point *sk_lastStrokePoint(SK_Stroke *stk); + int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); @@ -348,6 +352,48 @@ int peelObjects(ListBase *depth_peels, short mval[2]) return retval; } +/*********************** CONVERSION ***************************/ + +ReebNode *pointToNode(SK_Point *pt) +{ + ReebNode *node; + + node = MEM_callocN(sizeof(ReebNode), "reeb node"); + VECCOPY(node->p, pt->p); + + return node; +} + +ReebArc *strokeToArc(SK_Stroke *stk) +{ + ReebArc *arc; + int i; + + arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); + arc->head = pointToNode(stk->points); + arc->tail = pointToNode(sk_lastStrokePoint(stk)); + + arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */ + arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets"); + + for (i = 0; i < arc->bcount; i++) + { + VECCOPY(arc->buckets[i].p, stk->points[i + 1].p); + } + + return arc; +} + +void retargetStroke(SK_Stroke *stk) +{ + ReebArc *arc = strokeToArc(stk); + + BIF_retargetArc(arc); + + MEM_freeN(arc->head); + MEM_freeN(arc->tail); + REEB_freeArc(arc); +} /**************************************************************/ @@ -2267,9 +2313,10 @@ int sk_paint(SK_Sketch *sketch, short mbut) if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) { - sk_convertStroke(stk); - sk_removeStroke(sketch, stk); - BIF_undo_push("Convert Sketch"); + retargetStroke(stk); +// sk_convertStroke(stk); +// sk_removeStroke(sketch, stk); +// BIF_undo_push("Convert Sketch"); allqueue(REDRAWBUTSEDIT, 0); } From cfee0079d22ec1db07b9da9b6d78e6679de76db1 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 30 Oct 2008 19:58:11 +0000 Subject: [PATCH 034/252] Lots of code cleanup and some new features. Clean and split editbone duplication methods for easy reuse. Copy and retarget selected bones to stroke conversion method. This is the start of the infamous templating system. A simple demo video is available: http://blenderartists.org/~theeth/bf/etch-a-ton/retarget.ogv and http://vimeo.com/2111535 (for those who dislike ogg/theora) --- source/blender/include/BIF_editarmature.h | 7 + source/blender/include/BIF_retarget.h | 6 +- source/blender/include/reeb.h | 1 + source/blender/makesdna/DNA_scene_types.h | 12 +- source/blender/src/buttons_editing.c | 1 - source/blender/src/drawview.c | 39 +- source/blender/src/editarmature.c | 91 +++- source/blender/src/editarmature_retarget.c | 495 +++++++-------------- source/blender/src/editarmature_sketch.c | 35 +- source/blender/src/reeb.c | 3 - 10 files changed, 322 insertions(+), 368 deletions(-) diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 4c3ba94ccc1..a89aecf854e 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -70,6 +70,13 @@ typedef struct EditBone EditBone *addEditBone(char *name, struct ListBase *ebones, struct bArmature *arm); +/* duplicate method */ +void preEditBoneDuplicate(struct ListBase *editbones); +EditBone *duplicateEditBone(EditBone *curBone, struct ListBase *editbones, struct Object *ob); +void updateDuplicateSubtarget(EditBone *dupBone, struct Object *ob); + +/* -- */ + float rollBoneToVector(EditBone *bone, float new_up_axis[3]); void make_boneList(struct ListBase *list, struct ListBase *bones, EditBone *parent); void editbones_to_armature (struct ListBase *list, struct Object *ob); diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h index df46d309a94..867c90460ba 100644 --- a/source/blender/include/BIF_retarget.h +++ b/source/blender/include/BIF_retarget.h @@ -44,10 +44,7 @@ struct RigEdge; typedef struct RigGraph { ListBase arcs; ListBase nodes; - ListBase controls; - ListBase* editbones; - float length; FreeArc free_arc; @@ -56,6 +53,9 @@ typedef struct RigGraph { AxialSymmetry axial_symmetry; /*********************************/ + ListBase controls; + ListBase* editbones; + struct RigNode *head; ReebGraph *link_mesh; diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index 57f7d1b60cf..d8146ff8d6d 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -185,6 +185,7 @@ ReebNode *BIF_lowestLevelNode(ReebNode *node); ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node); void REEB_freeGraph(ReebGraph *rg); +void REEB_freeArc(BArc *barc); void REEB_exportGraph(ReebGraph *rg, int count); void REEB_draw(); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b5e588ee747..6f33ece2ee9 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -441,17 +441,15 @@ typedef struct ToolSettings { char skgen_postpro_passes; char skgen_subdivisions[3]; char skgen_multi_level; - char skgen_optimisation_method; - - char tpad[6]; /* Skeleton Sketching */ char bone_sketching; + char bone_sketching_convert; char skgen_subdivision_number; /* Alt+RMB option */ char edge_mode; - char pad3[6]; + char pad3[4]; } ToolSettings; /* Used by all brushes to store their properties, which can be directly set @@ -879,6 +877,12 @@ typedef struct Scene { #define BONE_SKETCHING 1 #define BONE_SKETCHING_QUICK 2 +/* toolsettings->bone_sketching_convert */ +#define SK_CONVERT_CUT_FIXED 1 +#define SK_CONVERT_CUT_LENGTH 2 +#define SK_CONVERT_CUT_CORRELATION 3 +#define SK_CONVERT_RETARGET 4 + #ifdef __cplusplus } #endif diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index f362fa815ce..26c0496f107 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -5246,7 +5246,6 @@ static void editing_panel_mesh_skgen_retarget(Object *ob, Mesh *me) uiDefButF(block, NUM, B_DIFF, "Ang:", 1025, 40, 83,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); uiDefButF(block, NUM, B_DIFF, "Len:", 1108, 40, 83,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); uiDefButF(block, NUM, B_DIFF, "Dist:", 1191, 40, 84,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); - uiDefButC(block, NUM, B_DIFF, "Method:", 1025, 20, 125,19, &G.scene->toolsettings->skgen_optimisation_method, 0, 2, 1, 0,"Optimisation Method (0: brute, 1: memoize, 2: annealing max fixed"); } static void editing_panel_mesh_skgen(Object *ob, Mesh *me) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index dbc9dcfd805..7f1e8122da6 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2297,35 +2297,52 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); uiSetPanelHandler(VIEW3D_HANDLER_BONESKETCH); // for close and esc - if(uiNewPanel(curarea, block, "Bone Sketching", "View3d", 10, 230, 318, height)==0) return; + if(uiNewPanel(curarea, block, "Bone Sketching", "View3d", 10, 230, 250, height)==0) return; uiNewPanelHeight(block, height); uiBlockBeginAlign(block); /* use real flag instead of 1 */ - uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, 225, 130, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); - uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 140, 225, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end"); - but = uiDefBut(block, BUT, B_REDR, "Convert", 10,205,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); + uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 130, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 140, yco, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end"); + yco -= 20; + + but = uiDefBut(block, BUT, B_REDR, "Convert", 10,yco,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); uiButSetFunc(but, convert_sketch_armature, NULL, NULL); - but = uiDefBut(block, BUT, B_REDR, "Delete", 10,185,150,20, 0, 0, 0, 0, 0, "Delete sketch"); + yco -= 20; + + but = uiDefBut(block, BUT, B_REDR, "Delete", 10,yco,150,20, 0, 0, 0, 0, 0, "Delete sketch"); uiButSetFunc(but, delete_sketch_armature, NULL, NULL); + yco -= 20; uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, SKGEN_CUT_LENGTH, B_REDR, "Length", 10, 155, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs in bones of equal length"); - uiDefButF(block, NUM, B_REDR, "L:", 70, 155, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); + uiDefButC(block, ROW, B_REDR, "Length", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_LENGTH, 0, 0, "Subdivide arcs in bones of equal length"); + uiDefButF(block, NUM, B_REDR, "L:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); + yco -= 20; - uiDefButBitS(block, TOG, SKGEN_CUT_CORRELATION, B_REDR, "Correlation", 10, 135, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on correlation"); - uiDefButF(block, NUM, B_REDR, "T:", 70, 135, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); + uiDefButC(block, ROW, B_REDR, "Correlation", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_CORRELATION, 0, 0, "Subdivide arcs based on correlation"); + uiDefButF(block, NUM, B_REDR, "T:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); + yco -= 20; - uiDefButBitS(block, TOG, SKGEN_CUT_FIXED, B_REDR, "Fixed", 10, 115, 60, 19, &G.scene->toolsettings->skgen_options, 0, 0, 0, 0, "Subdivide arcs based on a fixed number of bones"); - uiDefButC(block, NUM, B_REDR, "N:", 70, 115, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Specify the bones to subdivide into"); + uiDefButC(block, ROW, B_REDR, "Fixed", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_FIXED, 0, 0, "Subdivide arcs based on a fixed number of bones"); + uiDefButC(block, NUM, B_REDR, "N:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Specify the bones to subdivide into"); + yco -= 20; + + uiDefButC(block, ROW, B_REDR, "Retarget", 10, yco,150, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_RETARGET, 0, 0, "Subdivide arcs based on a fixed number of bones"); + /* button here to select what to do (copy or not), template, ...*/ + yco -= 20; uiBlockEndAlign(block); + uiDefButF(block, NUM, B_DIFF, "Ang:", 10, yco, 50,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); + uiDefButF(block, NUM, B_DIFF, "Len:", 60, yco, 50,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); + uiDefButF(block, NUM, B_DIFF, "Dist:", 110,yco, 50,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); + yco -= 20; + if(yco < 0) uiNewPanelHeight(block, height-yco); } } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 6fc94e4f997..63d5b9ce1f5 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -2212,7 +2212,20 @@ static EditBone *get_named_editbone(char *name) return NULL; } -static void update_dup_subtarget(EditBone *dupBone) +/* Call this before doing any duplications + * */ +void preEditBoneDuplicate(ListBase *editbones) +{ + EditBone *eBone; + + /* clear temp */ + for (eBone = editbones->first; eBone; eBone = eBone->next) + { + eBone->temp = NULL; + } +} + +void updateDuplicateSubtarget(EditBone *dupBone, Object *ob) { /* If an edit bone has been duplicated, lets * update it's constraints if the subtarget @@ -2223,7 +2236,7 @@ static void update_dup_subtarget(EditBone *dupBone) bConstraint *curcon; ListBase *conlist; - if ( (chan = verify_pose_channel(OBACT->pose, dupBone->name)) ) { + if ( (chan = verify_pose_channel(ob->pose, dupBone->name)) ) { if ( (conlist = &chan->constraints) ) { for (curcon = conlist->first; curcon; curcon=curcon->next) { /* does this constraint have a subtarget in @@ -2244,7 +2257,7 @@ static void update_dup_subtarget(EditBone *dupBone) * so, update the constraint to point at the * duplicate of the old subtarget. */ - if (oldtarget->flag & BONE_SELECTED){ + if (oldtarget->temp){ newtarget = (EditBone *) oldtarget->temp; strcpy(ct->subtarget, newtarget->name); } @@ -2260,6 +2273,67 @@ static void update_dup_subtarget(EditBone *dupBone) } } +EditBone *duplicateEditBone(EditBone *curBone, ListBase *editbones, Object *ob) +{ + EditBone *eBone = MEM_callocN(sizeof(EditBone), "addup_editbone"); + + /* Copy data from old bone to new bone */ + memcpy(eBone, curBone, sizeof(EditBone)); + + curBone->temp = eBone; + eBone->temp = curBone; + + unique_editbone_name(editbones, eBone->name); + BLI_addtail(editbones, eBone); + + /* Lets duplicate the list of constraints that the + * current bone has. + */ + if (ob->pose) { + bPoseChannel *chanold, *channew; + ListBase *listold, *listnew; + + chanold = verify_pose_channel(ob->pose, curBone->name); + if (chanold) { + listold = &chanold->constraints; + if (listold) { + /* WARNING: this creates a new posechannel, but there will not be an attached bone + * yet as the new bones created here are still 'EditBones' not 'Bones'. + */ + channew = + verify_pose_channel(ob->pose, eBone->name); + if (channew) { + /* copy transform locks */ + channew->protectflag = chanold->protectflag; + + /* copy bone group */ + channew->agrp_index= chanold->agrp_index; + + /* ik (dof) settings */ + channew->ikflag = chanold->ikflag; + VECCOPY(channew->limitmin, chanold->limitmin); + VECCOPY(channew->limitmax, chanold->limitmax); + VECCOPY(channew->stiffness, chanold->stiffness); + channew->ikstretch= chanold->ikstretch; + + /* constraints */ + listnew = &channew->constraints; + copy_constraints(listnew, listold); + + /* custom shape */ + channew->custom= chanold->custom; + } + } + } + } + + /* --------------------WARNING-------------------- + * + * need to call static void updateDuplicateSubtarget(EditBone *dupBone) at some point + * */ + + return eBone; +} void adduplicate_armature(void) { @@ -2269,6 +2343,8 @@ void adduplicate_armature(void) EditBone *firstDup=NULL; /* The beginning of the duplicated bones in the edbo list */ countall(); // flushes selection! + + preEditBoneDuplicate(&G.edbo); /* Select mirrored bones */ if (arm->flag & ARM_MIRROR_EDIT) { @@ -2282,6 +2358,7 @@ void adduplicate_armature(void) } } } + /* Find the selected bones and duplicate them as needed */ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) { @@ -2356,12 +2433,12 @@ void adduplicate_armature(void) */ if (!curBone->parent) eBone->parent = NULL; - /* If this bone has a parent that IS selected, + /* If this bone has a parent that was duplicated, Set the duplicate->parent to the curBone->parent->duplicate */ - else if (curBone->parent->flag & BONE_SELECTED) + else if (curBone->parent->temp) eBone->parent= (EditBone *)curBone->parent->temp; - /* If this bone has a parent that IS not selected, + /* If this bone has a parent that was not duplicated, Set the duplicate->parent to the curBone->parent */ else { @@ -2371,7 +2448,7 @@ void adduplicate_armature(void) /* Lets try to fix any constraint subtargets that might have been duplicated */ - update_dup_subtarget(eBone); + updateDuplicateSubtarget(eBone, OBACT); } } } diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 51e1e789d8e..eef8c743823 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -93,8 +93,7 @@ typedef enum typedef enum { METHOD_BRUTE_FORCE = 0, - METHOD_MEMOIZE = 1, - METHOD_ANNEALING = 2 + METHOD_MEMOIZE = 1 } RetargetMethod; typedef enum @@ -374,6 +373,155 @@ static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone) RIG_appendEdgeToArc(arc, edge); } +/************************************** CLONING TEMPLATES **********************************************/ + +static RigControl *cloneControl(RigGraph *rg, RigControl *src_ctrl, GHash *ptr_hash) +{ + RigControl *ctrl; + + ctrl = newRigControl(rg); + + VECCOPY(ctrl->head, src_ctrl->head); + VECCOPY(ctrl->tail, src_ctrl->tail); + VECCOPY(ctrl->up_axis, src_ctrl->up_axis); + VECCOPY(ctrl->offset, src_ctrl->offset); + + ctrl->flag = src_ctrl->flag; + + ctrl->bone = duplicateEditBone(src_ctrl->bone, rg->editbones, rg->ob); + ctrl->bone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); + BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone); + + ctrl->link = src_ctrl->link; + + return ctrl; +} + +static RigArc *cloneArc(RigGraph *rg, RigArc *src_arc, GHash *ptr_hash) +{ + RigEdge *src_edge; + RigArc *arc; + + arc = newRigArc(rg); + + arc->head = BLI_ghash_lookup(ptr_hash, src_arc->head); + arc->tail = BLI_ghash_lookup(ptr_hash, src_arc->tail); + + arc->head->degree++; + arc->tail->degree++; + + arc->length = src_arc->length; + + arc->count = src_arc->count; + + for (src_edge = src_arc->edges.first; src_edge; src_edge = src_edge->next) + { + RigEdge *edge; + + edge = MEM_callocN(sizeof(RigEdge), "rig edge"); + + VECCOPY(edge->head, src_edge->head); + VECCOPY(edge->tail, src_edge->tail); + VECCOPY(edge->up_axis, src_edge->up_axis); + + edge->length = src_edge->length; + edge->angle = src_edge->angle; + + if (src_edge->bone != NULL) + { + edge->bone = duplicateEditBone(src_edge->bone, rg->editbones, rg->ob); + edge->bone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); + BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone); + } + + BLI_addtail(&arc->edges, edge); + } + + return arc; +} + +static RigGraph *cloneRigGraph(RigGraph *src) +{ + GHash *ptr_hash; + RigNode *node; + RigArc *arc; + RigControl *ctrl; + RigGraph *rg; + + ptr_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + rg = newRigGraph(); + + rg->ob = src->ob; + rg->editbones = src->editbones; + + preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */ + + /* Clone nodes */ + for (node = src->nodes.first; node; node = node->next) + { + RigNode *cloned_node = newRigNode(rg, node->p); + BLI_ghash_insert(ptr_hash, node, cloned_node); + } + + rg->head = BLI_ghash_lookup(ptr_hash, src->head); + + /* Clone arcs */ + for (arc = src->arcs.first; arc; arc = arc->next) + { + cloneArc(rg, arc, ptr_hash); + } + + /* Clone controls */ + for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next) + { + cloneControl(rg, ctrl, ptr_hash); + } + + /* Relink bones properly */ + for (arc = rg->arcs.first; arc; arc = arc->next) + { + RigEdge *edge; + + for (edge = arc->edges.first; edge; edge = edge->next) + { + if (edge->bone != NULL) + { + EditBone *bone; + + updateDuplicateSubtarget(edge->bone, rg->ob); + + bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent); + + if (bone != NULL) + { + edge->bone->parent = bone; + } + } + } + } + + for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) + { + EditBone *bone; + + updateDuplicateSubtarget(ctrl->bone, rg->ob); + + bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent); + + if (bone != NULL) + { + ctrl->bone->parent = bone; + } + + ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link); + } + + BLI_ghash_free(ptr_hash, NULL, NULL); + + return rg; +} + /*******************************************************************************************************/ @@ -606,8 +754,6 @@ static void RIG_reconnectControlBones(RigGraph *rg) { change = 0; - printf("-------------------------\n"); - for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) { /* if control is not linked yet */ @@ -1577,29 +1723,6 @@ static RetargetMode detectArcRetargetMode(RigArc *iarc) } #ifndef USE_THREADS -static void printCostCube(float *cost_cube, int nb_joints) -{ - int i; - - for (i = 0; i < nb_joints; i++) - { - printf("%0.3f ", cost_cube[3 * i]); - } - printf("\n"); - - for (i = 0; i < nb_joints; i++) - { - printf("%0.3f ", cost_cube[3 * i + 1]); - } - printf("\n"); - - for (i = 0; i < nb_joints; i++) - { - printf("%0.3f ", cost_cube[3 * i + 2]); - } - printf("\n"); -} - static void printMovesNeeded(int *positions, int nb_positions) { int moves = 0; @@ -1746,187 +1869,6 @@ static float calcCostAngleLengthDistance(ReebArcIterator *iter, float **vec_cach return new_cost; } -static float calcCost(ReebArcIterator *iter, RigEdge *e1, RigEdge *e2, float *vec0, float *vec1, float *vec2, int i0, int i1, int i2) -{ - float vec_second[3], vec_first[3]; - float length1, length2; - float new_cost = 0; - - VecSubf(vec_second, vec2, vec1); - length2 = Normalize(vec_second); - - VecSubf(vec_first, vec1, vec0); - length1 = Normalize(vec_first); - - /* Angle cost */ - new_cost += costAngle(e1->angle, vec_first, vec_second); - - /* Length cost */ - new_cost += costLength(e1->length, length1); - new_cost += costLength(e2->length, length2); - - /* Distance cost */ - new_cost += costDistance(iter, vec0, vec1, i0, i1); - new_cost += costDistance(iter, vec1, vec2, i1, i2); - - return new_cost; -} - -static void calcGradient(RigEdge *e1, RigEdge *e2, ReebArcIterator *iter, int index, int nb_joints, float *cost_cube, int *positions, float **vec_cache) -{ - EmbedBucket *bucket = NULL; - float *vec0, *vec1, *vec2; - float current_cost; - int i0, i1, i2; - int next_position; - - vec0 = vec_cache[index]; - vec1 = vec_cache[index + 1]; - vec2 = vec_cache[index + 2]; - - if (index == 0) - { - i0 = 0; - } - else - { - i0 = positions[index - 1]; - } - - i1 = positions[index]; - - if (index +1 == nb_joints) - { - i2 = iter->length; - } - else - { - i2 = positions[index + 1]; - } - - - current_cost = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, i1, i2); - cost_cube[index * 3 + 1] = current_cost; - - next_position = positions[index] + 1; - - if (index + 1 < nb_joints && next_position == positions[index + 1]) - { - cost_cube[index * 3 + 2] = MAX_COST; - } - else if (next_position > iter->length) /* positions are indexed at 1, so length is last */ - { - cost_cube[index * 3 + 2] = MAX_COST; - } - else - { - bucket = peekBucket(iter, next_position); - - if (bucket == NULL) - { - cost_cube[index * 3 + 2] = MAX_COST; - } - else - { - vec1 = bucket->p; - - cost_cube[index * 3 + 2] = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, next_position, i2) - current_cost; - } - } - - next_position = positions[index] - 1; - - if (index - 1 > -1 && next_position == positions[index - 1]) - { - cost_cube[index * 3] = MAX_COST; - } - else if (next_position < 1) /* positions are indexed at 1, so 1 is first */ - { - cost_cube[index * 3] = MAX_COST; - } - else - { - bucket = peekBucket(iter, next_position); - - if (bucket == NULL) - { - cost_cube[index * 3] = MAX_COST; - } - else - { - vec1 = bucket->p; - - cost_cube[index * 3] = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, next_position, i2) - current_cost; - } - } -} - -static float probability(float delta_cost, float temperature) -{ - if (delta_cost < 0) - { - return 1; - } - else - { - return (float)exp(delta_cost / temperature); - } -} - -static int neighbour(int nb_joints, float *cost_cube, int *moving_joint, int *moving_direction) -{ - int total = 0; - int chosen = 0; - int i; - - for (i = 0; i < nb_joints; i++) - { - if (cost_cube[i * 3] < MAX_COST) - { - total++; - } - - if (cost_cube[i * 3 + 2] < MAX_COST) - { - total++; - } - } - - if (total == 0) - { - return 0; - } - - chosen = (int)(BLI_drand() * total); - - for (i = 0; i < nb_joints; i++) - { - if (cost_cube[i * 3] < MAX_COST) - { - if (chosen == 0) - { - *moving_joint = i; - *moving_direction = -1; - break; - } - chosen--; - } - - if (cost_cube[i * 3 + 2] < MAX_COST) - { - if (chosen == 0) - { - *moving_joint = i; - *moving_direction = 1; - break; - } - chosen--; - } - } - - return 1; -} - static int indexMemoNode(int nb_positions, int previous, int current, int joints_left) { return joints_left * nb_positions * nb_positions + current * nb_positions + previous; @@ -2050,7 +1992,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino int *positions; int nb_edges = BLI_countlist(&iarc->edges); int nb_joints = nb_edges - 1; - RetargetMethod method = G.scene->toolsettings->skgen_optimisation_method; + RetargetMethod method = METHOD_MEMOIZE; int i; if (nb_joints > earc->bcount) @@ -2261,114 +2203,6 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino } } } - /* SIMULATED ANNEALING */ - else if (method == METHOD_ANNEALING) - { - RigEdge *previous; - float *cost_cube; - float cost; - int k; - int kmax; - - kmax = 100000; - - BLI_srand(nb_joints); - - /* [joint: index][position: -1, 0, +1] */ - cost_cube = MEM_callocN(sizeof(float) * 3 * nb_joints, "Cost Cube"); - - initArcIterator(&iter, earc, node_start); - - /* init vec_cache */ - for (i = 0; i < nb_joints; i++) - { - bucket = peekBucket(&iter, positions[i]); - vec_cache[i + 1] = bucket->p; - } - - cost = 0; - - /* init cost cube */ - for (previous = iarc->edges.first, edge = previous->next, i = 0; - edge; - previous = edge, edge = edge->next, i += 1) - { - calcGradient(previous, edge, &iter, i, nb_joints, cost_cube, positions, vec_cache); - - cost += cost_cube[3 * i + 1]; - } - -#ifndef USE_THREADS - printf("initial cost: %f\n", cost); - printf("kmax: %i\n", kmax); -#endif - - for (k = 0; k < kmax; k++) - { - int status; - int moving_joint = -1; - int move_direction = -1; - float delta_cost; - float temperature; - - status = neighbour(nb_joints, cost_cube, &moving_joint, &move_direction); - - if (status == 0) - { - /* if current state is still a minimum, copy it */ - if (cost < min_cost) - { - min_cost = cost; - memcpy(best_positions, positions, sizeof(int) * nb_joints); - } - break; - } - - delta_cost = cost_cube[moving_joint * 3 + (1 + move_direction)]; - - temperature = 1 - (float)k / (float)kmax; - if (probability(delta_cost, temperature) > BLI_frand()) - { - /* update position */ - positions[moving_joint] += move_direction; - - /* update vector cache */ - bucket = peekBucket(&iter, positions[moving_joint]); - vec_cache[moving_joint + 1] = bucket->p; - - cost += delta_cost; - - /* cost optimizing */ - if (cost < min_cost) - { - min_cost = cost; - memcpy(best_positions, positions, sizeof(int) * nb_joints); - } - - /* update cost cube */ - for (previous = iarc->edges.first, edge = previous->next, i = 0; - edge; - previous = edge, edge = edge->next, i += 1) - { - if (i == moving_joint - 1 || - i == moving_joint || - i == moving_joint + 1) - { - calcGradient(previous, edge, &iter, i, nb_joints, cost_cube, positions, vec_cache); - } - } - } - } - - //min_cost = cost; - //memcpy(best_positions, positions, sizeof(int) * nb_joints); - -// printf("k = %i\n", k); - - - MEM_freeN(cost_cube); - } - vec0 = node_start->p; initArcIterator(&iter, earc, node_start); @@ -2793,6 +2627,13 @@ static void retargetSubgraph(RigGraph *rigg, RigArc *start_arc, RigNode *start_n } } +static void finishRetarget(RigGraph *rigg) +{ +#ifdef USE_THREADS + BLI_end_worker(rigg->worker); +#endif +} + static void adjustGraphs(RigGraph *rigg) { RigArc *arc; @@ -2805,9 +2646,7 @@ static void adjustGraphs(RigGraph *rigg) } } -#ifdef USE_THREADS - BLI_end_worker(rigg->worker); -#endif + finishRetarget(rigg); /* Turn the list into an armature */ editbones_to_armature(rigg->editbones, rigg->ob); @@ -2834,9 +2673,7 @@ static void retargetGraphs(RigGraph *rigg) //generateMissingArcs(rigg); -#ifdef USE_THREADS - BLI_end_worker(rigg->worker); -#endif + finishRetarget(rigg); /* Turn the list into an armature */ editbones_to_armature(rigg->editbones, rigg->ob); @@ -2927,6 +2764,7 @@ void BIF_retargetArmature() void BIF_retargetArc(ReebArc *earc) { Object *ob; + RigGraph *template; RigGraph *rigg; RigArc *iarc; bArmature *arm; @@ -2934,7 +2772,9 @@ void BIF_retargetArc(ReebArc *earc) ob = G.obedit; arm = ob->data; - rigg = armatureSelectedToGraph(ob, arm); + template = armatureSelectedToGraph(ob, arm); + + rigg = cloneRigGraph(template); iarc = rigg->arcs.first; @@ -2944,11 +2784,10 @@ void BIF_retargetArc(ReebArc *earc) retargetArctoArc(rigg, iarc, iarc->head); -#ifdef USE_THREADS - BLI_end_worker(rigg->worker); -#endif + finishRetarget(rigg); - //RIG_freeRigGraph((BGraph*)rigg); + RIG_freeRigGraph((BGraph*)template); + RIG_freeRigGraph((BGraph*)rigg); BIF_undo_push("Retarget Arc"); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 0cd0cd8ff29..22173e469cf 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -34,6 +34,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_graph.h" #include "BKE_utildefines.h" #include "BKE_global.h" @@ -392,7 +393,7 @@ void retargetStroke(SK_Stroke *stk) MEM_freeN(arc->head); MEM_freeN(arc->tail); - REEB_freeArc(arc); + REEB_freeArc((BArc*)arc); } /**************************************************************/ @@ -771,6 +772,12 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) int head_index = -1; int i; + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET) + { + return; + } + + for (i = 0; i < stk->nb_points; i++) { SK_Point *pt = stk->points + i; @@ -785,15 +792,15 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) { if (i - head_index > 1) { - if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) { drawSubdividedStrokeBy(stk, head_index, i, nextCorrelationSubdivision); } - else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { drawSubdividedStrokeBy(stk, head_index, i, nextLengthSubdivision); } - else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_FIXED) + else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { drawSubdividedStrokeBy(stk, head_index, i, nextFixedSubdivision); } @@ -1545,15 +1552,15 @@ void sk_convertStroke(SK_Stroke *stk) if (i - head_index > 1) { - if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) { bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextCorrelationSubdivision); } - else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) + else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextLengthSubdivision); } - else if (G.scene->toolsettings->skgen_options & SKGEN_CUT_FIXED) + else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextFixedSubdivision); } @@ -2313,10 +2320,16 @@ int sk_paint(SK_Sketch *sketch, short mbut) if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) { - retargetStroke(stk); -// sk_convertStroke(stk); -// sk_removeStroke(sketch, stk); -// BIF_undo_push("Convert Sketch"); + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET) + { + retargetStroke(stk); + } + else + { + sk_convertStroke(stk); + } + sk_removeStroke(sketch, stk); + BIF_undo_push("Convert Sketch"); allqueue(REDRAWBUTSEDIT, 0); } diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index 5f80a2c7227..3678106e9ef 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -69,9 +69,6 @@ #include "reeb.h" -/* REPLACE WITH NEW ONE IN UTILDEFINES ONCE PATCH IS APPLIED */ -#define FTOCHAR(val) (val<=0.0f)? 0 : ((val>(1.0f-0.5f/255.0f))? 255 : (char)((255.0f*val)+0.5f)) - ReebGraph *GLOBAL_RG = NULL; ReebGraph *FILTERED_RG = NULL; From d7aad3559914cc869d0bff92c4394eb0df17caa3 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 2 Nov 2008 17:43:55 +0000 Subject: [PATCH 035/252] Sketch Retargetting: Use stroke normal to align roll of the retargetted bones. Unlike stroke conversion, the final roll is not forced to point exactly to the normal. Rather, It tries to align the X or Z axis of the bones (whichever is closest) to the stroke normal. Forcing the roll can invert knees while this rightly only makes one of the joints rotation axis perpendicular. --- source/blender/include/reeb.h | 1 + source/blender/src/editarmature_retarget.c | 93 ++++++++++++++++------ source/blender/src/editarmature_sketch.c | 1 + 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index d8146ff8d6d..5dcbad7e80b 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -63,6 +63,7 @@ typedef struct EmbedBucket { float val; int nv; float p[3]; + float *no; /* if present, normal of the bucket */ } EmbedBucket; typedef struct ReebNode { diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index eef8c743823..34c5064e5f3 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -64,6 +64,7 @@ #include "BIF_editarmature.h" #include "BIF_retarget.h" #include "BIF_space.h" +#include "BIF_toolbox.h" #include "PIL_time.h" @@ -161,30 +162,52 @@ void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3]) VECCOPY(up_axis, mat[2]); } -float getNewBoneRoll(EditBone *bone, float old_up_axis[3], float quat[4]) +float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float quat[4], float qroll[4], float aligned_axis[3]) { - float mat[3][3]; - float nor[3], up_axis[3], new_up_axis[3], vec[3]; - float roll; + float nor[3], new_up_axis[3], x_axis[3], z_axis[3]; VECCOPY(new_up_axis, old_up_axis); QuatMulVecf(quat, new_up_axis); - + VecSubf(nor, bone->tail, bone->head); - vec_roll_to_mat3(nor, 0, mat); - VECCOPY(up_axis, mat[2]); + Crossf(x_axis, nor, aligned_axis); + Crossf(z_axis, x_axis, nor); - roll = NormalizedVecAngle2(new_up_axis, up_axis); + Normalize(new_up_axis); + Normalize(x_axis); + Normalize(z_axis); - Crossf(vec, up_axis, new_up_axis); - - if (Inpf(vec, nor) < 0) + if (Inpf(new_up_axis, x_axis) < 0) { - roll = -roll; + VecMulf(x_axis, -1); } - return roll; + if (Inpf(new_up_axis, z_axis) < 0) + { + VecMulf(z_axis, -1); + } + + if (NormalizedVecAngle2(x_axis, new_up_axis) < NormalizedVecAngle2(z_axis, new_up_axis)) + { + RotationBetweenVectorsToQuat(qroll, new_up_axis, x_axis); /* set roll rotation quat */ + return rollBoneToVector(bone, x_axis); + } + else + { + RotationBetweenVectorsToQuat(qroll, new_up_axis, z_axis); /* set roll rotation quat */ + return rollBoneToVector(bone, z_axis); + } +} + +float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float quat[4]) +{ + float new_up_axis[3]; + + VECCOPY(new_up_axis, old_up_axis); + QuatMulVecf(quat, new_up_axis); + + return rollBoneToVector(bone, new_up_axis); } /************************************ DESTRUCTORS ******************************************************/ @@ -1617,7 +1640,7 @@ static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], f VecAddf(ctrl->bone->head, head, parent_offset); VecAddf(ctrl->bone->tail, ctrl->bone->head, tail_offset); - ctrl->bone->roll = getNewBoneRoll(ctrl->bone, ctrl->up_axis, qrot); + ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, qrot); ctrl->flag |= RIG_CTRL_DONE; @@ -1632,7 +1655,7 @@ static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], f } -static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3]) +static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float *up_axis) { EditBone *bone; RigControl *ctrl; @@ -1652,6 +1675,22 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v RotationBetweenVectorsToQuat(qrot, v1, v2); + VECCOPY(bone->head, vec0); + VECCOPY(bone->tail, vec1); + + if (up_axis != NULL) + { + float qroll[4]; + + bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis); + + QuatMul(qrot, qrot, qroll); + } + else + { + bone->roll = rollBoneByQuat(bone, edge->up_axis, qrot); + } + for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next) { if (ctrl->link == bone) @@ -1659,10 +1698,6 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v repositionControl(rigg, ctrl, vec0, vec1, qrot, resize); } } - - VECCOPY(bone->head, vec0); - VECCOPY(bone->tail, vec1); - bone->roll = getNewBoneRoll(bone, edge->up_axis, qrot); } static RetargetMode detectArcRetargetMode(RigArc *arc); @@ -2219,10 +2254,12 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino edge; edge = edge->next, i++) { + float *no = NULL; if (i < nb_joints) { bucket = peekBucket(&iter, best_positions[i]); vec1 = bucket->p; + no = bucket->no; } else { @@ -2231,7 +2268,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino if (edge->bone) { - repositionBone(rigg, edge, vec0, vec1); + repositionBone(rigg, edge, vec0, vec1, no); } vec0 = vec1; @@ -2297,7 +2334,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ for (edge = iarc->edges.first; edge; edge = edge->next) { float new_bone_length = edge->length / iarc->length * embedding_length; - + float *no = NULL; float length = 0; while (bucket && new_bone_length > length) @@ -2306,17 +2343,19 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ bucket = nextBucket(&iter); previous_vec = vec1; vec1 = bucket->p; + no = bucket->no; } if (bucket == NULL) { vec1 = node_end->p; + no = NULL; } /* no need to move virtual edges (space between unconnected bones) */ if (edge->bone) { - repositionBone(rigg, edge, vec0, vec1); + repositionBone(rigg, edge, vec0, vec1, no); } vec0 = vec1; @@ -2359,11 +2398,11 @@ void *exec_retargetArctoArc(void *param) if (testFlipArc(iarc, inode_start)) { - repositionBone(rigg, edge, earc->tail->p, earc->head->p); + repositionBone(rigg, edge, earc->tail->p, earc->head->p, NULL); } else { - repositionBone(rigg, edge, earc->head->p, earc->tail->p); + repositionBone(rigg, edge, earc->head->p, earc->tail->p, NULL); } } else @@ -2774,6 +2813,12 @@ void BIF_retargetArc(ReebArc *earc) template = armatureSelectedToGraph(ob, arm); + if (template->arcs.first == NULL) + { + error("No deforming bones selected"); + return; + } + rigg = cloneRigGraph(template); iarc = rigg->arcs.first; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 22173e469cf..f1ca1bd0387 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -380,6 +380,7 @@ ReebArc *strokeToArc(SK_Stroke *stk) for (i = 0; i < arc->bcount; i++) { VECCOPY(arc->buckets[i].p, stk->points[i + 1].p); + arc->buckets[i].no = stk->points[i + 1].no; } return arc; From 86e8d54dcb7c46f876816dd0ddc87e893e958201 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 3 Nov 2008 17:54:12 +0000 Subject: [PATCH 036/252] Sketch Retargetting: Rolling bone perpendicular to stroke's normal is now optional. Normal pointer added to reeb nodes (the last bone in a chain needs it and can't get it from the embedding). --- source/blender/include/reeb.h | 2 ++ source/blender/makesdna/DNA_scene_types.h | 7 ++++++- source/blender/src/drawview.c | 9 +++++---- source/blender/src/editarmature_retarget.c | 7 ++++--- source/blender/src/editarmature_sketch.c | 10 +++++++++- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index 5dcbad7e80b..6496eb34836 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -80,6 +80,8 @@ typedef struct ReebNode { int symmetry_flag; float symmetry_axis[3]; /*********************************/ + + float *no; int index; float weight; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 6f33ece2ee9..3899600af30 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -446,10 +446,11 @@ typedef struct ToolSettings { char bone_sketching; char bone_sketching_convert; char skgen_subdivision_number; + char skgen_retarget_options; /* Alt+RMB option */ char edge_mode; - char pad3[4]; + char pad3[3]; } ToolSettings; /* Used by all brushes to store their properties, which can be directly set @@ -883,6 +884,10 @@ typedef struct Scene { #define SK_CONVERT_CUT_CORRELATION 3 #define SK_CONVERT_RETARGET 4 +/* toolsettings->skgen_retarget_options */ +#define SK_RETARGET_ROLL 1 + + #ifdef __cplusplus } #endif diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 7f1e8122da6..d799d31c742 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2321,18 +2321,19 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockBeginAlign(block); uiDefButC(block, ROW, B_REDR, "Length", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_LENGTH, 0, 0, "Subdivide arcs in bones of equal length"); - uiDefButF(block, NUM, B_REDR, "L:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the bones when subdividing"); + uiDefButF(block, NUM, B_REDR, "L:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the subdivided bones"); yco -= 20; uiDefButC(block, ROW, B_REDR, "Correlation", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_CORRELATION, 0, 0, "Subdivide arcs based on correlation"); - uiDefButF(block, NUM, B_REDR, "T:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Specify the threshold correlation for subdivision"); + uiDefButF(block, NUM, B_REDR, "T:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Correlation threshold for subdivision"); yco -= 20; uiDefButC(block, ROW, B_REDR, "Fixed", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_FIXED, 0, 0, "Subdivide arcs based on a fixed number of bones"); - uiDefButC(block, NUM, B_REDR, "N:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Specify the bones to subdivide into"); + uiDefButC(block, NUM, B_REDR, "N:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Number of subdivided bones"); yco -= 20; - uiDefButC(block, ROW, B_REDR, "Retarget", 10, yco,150, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_RETARGET, 0, 0, "Subdivide arcs based on a fixed number of bones"); + uiDefButC(block, ROW, B_REDR, "Retarget", 10, yco,80, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_RETARGET, 0, 0, "Retarget selected bones to stroke"); + uiDefButBitC(block, TOG, SK_RETARGET_ROLL, B_DIFF, "Roll", 90, yco, 70,19, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Roll bones perpendicular to view"); /* button here to select what to do (copy or not), template, ...*/ yco -= 20; diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 34c5064e5f3..d54389e7d80 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -2264,6 +2264,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino else { vec1 = node_end->p; + no = node_end->no; } if (edge->bone) @@ -2349,7 +2350,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ if (bucket == NULL) { vec1 = node_end->p; - no = NULL; + no = node_end->no; } /* no need to move virtual edges (space between unconnected bones) */ @@ -2398,11 +2399,11 @@ void *exec_retargetArctoArc(void *param) if (testFlipArc(iarc, inode_start)) { - repositionBone(rigg, edge, earc->tail->p, earc->head->p, NULL); + repositionBone(rigg, edge, earc->tail->p, earc->head->p, earc->head->no); } else { - repositionBone(rigg, edge, earc->head->p, earc->tail->p, NULL); + repositionBone(rigg, edge, earc->head->p, earc->tail->p, earc->tail->no); } } else diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index f1ca1bd0387..aeff63ce4d7 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -362,6 +362,11 @@ ReebNode *pointToNode(SK_Point *pt) node = MEM_callocN(sizeof(ReebNode), "reeb node"); VECCOPY(node->p, pt->p); + if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_ROLL) + { + node->no = pt->no; + } + return node; } @@ -380,7 +385,10 @@ ReebArc *strokeToArc(SK_Stroke *stk) for (i = 0; i < arc->bcount; i++) { VECCOPY(arc->buckets[i].p, stk->points[i + 1].p); - arc->buckets[i].no = stk->points[i + 1].no; + if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_ROLL) + { + arc->buckets[i].no = stk->points[i + 1].no; + } } return arc; From 571520e976ce76dadbcfd319d908354ace182a14 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 4 Nov 2008 19:10:54 +0000 Subject: [PATCH 037/252] Properly unselect copied bones (it wasn't clearing active flag) Remove double undo push --- source/blender/src/editarmature_retarget.c | 6 +++--- source/blender/src/editarmature_sketch.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index d54389e7d80..a51c9ec0c43 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -412,7 +412,7 @@ static RigControl *cloneControl(RigGraph *rg, RigControl *src_ctrl, GHash *ptr_h ctrl->flag = src_ctrl->flag; ctrl->bone = duplicateEditBone(src_ctrl->bone, rg->editbones, rg->ob); - ctrl->bone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); + ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone); ctrl->link = src_ctrl->link; @@ -453,7 +453,7 @@ static RigArc *cloneArc(RigGraph *rg, RigArc *src_arc, GHash *ptr_hash) if (src_edge->bone != NULL) { edge->bone = duplicateEditBone(src_edge->bone, rg->editbones, rg->ob); - edge->bone->flag &= ~(BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL); + edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone); } @@ -1684,7 +1684,7 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis); - QuatMul(qrot, qrot, qroll); + QuatMul(qrot, qroll, qrot); } else { diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index aeff63ce4d7..2b4bc9b89b0 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -355,7 +355,7 @@ int peelObjects(ListBase *depth_peels, short mval[2]) } /*********************** CONVERSION ***************************/ -ReebNode *pointToNode(SK_Point *pt) +ReebNode *sk_pointToNode(SK_Point *pt) { ReebNode *node; @@ -370,14 +370,14 @@ ReebNode *pointToNode(SK_Point *pt) return node; } -ReebArc *strokeToArc(SK_Stroke *stk) +ReebArc *sk_strokeToArc(SK_Stroke *stk) { ReebArc *arc; int i; arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); - arc->head = pointToNode(stk->points); - arc->tail = pointToNode(sk_lastStrokePoint(stk)); + arc->head = sk_pointToNode(stk->points); + arc->tail = sk_pointToNode(sk_lastStrokePoint(stk)); arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */ arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets"); @@ -394,9 +394,9 @@ ReebArc *strokeToArc(SK_Stroke *stk) return arc; } -void retargetStroke(SK_Stroke *stk) +void sk_retargetStroke(SK_Stroke *stk) { - ReebArc *arc = strokeToArc(stk); + ReebArc *arc = sk_strokeToArc(stk); BIF_retargetArc(arc); @@ -2331,14 +2331,14 @@ int sk_paint(SK_Sketch *sketch, short mbut) { if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET) { - retargetStroke(stk); + sk_retargetStroke(stk); } else { sk_convertStroke(stk); + BIF_undo_push("Convert Sketch"); } sk_removeStroke(sketch, stk); - BIF_undo_push("Convert Sketch"); allqueue(REDRAWBUTSEDIT, 0); } From a405ed75fe830bd3ce110a94452af093a890bd04 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 5 Nov 2008 20:15:32 +0000 Subject: [PATCH 038/252] Sketch retargetting. Templating from other armature objects. Moving stuff home, saving doesn't work ok yet, will finish this later today, demo video when done. Also a couple of bug fixes for crashing and some text reformulation and the like. --- source/blender/blenlib/intern/graph.c | 5 ++ source/blender/blenloader/intern/readfile.c | 2 + source/blender/include/BIF_editarmature.h | 10 +++- source/blender/makesdna/DNA_scene_types.h | 1 + source/blender/src/drawview.c | 8 ++++ source/blender/src/editarmature.c | 49 ++++++++++++------- source/blender/src/editarmature_retarget.c | 52 ++++++++++++--------- source/blender/src/editarmature_sketch.c | 18 +++++-- 8 files changed, 101 insertions(+), 44 deletions(-) diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c index 8f35b38379e..e2ed8f11ee2 100644 --- a/source/blender/blenlib/intern/graph.c +++ b/source/blender/blenlib/intern/graph.c @@ -1033,6 +1033,11 @@ void BLI_markdownSymmetry(BGraph *graph, BNode *root_node, float limit) BNode *node; BArc *arc; + if (root_node == NULL) + { + return; + } + if (BLI_isGraphCyclic(graph)) { return; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index acedf51e619..154f6d7264a 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3549,6 +3549,8 @@ static void direct_link_scene(FileData *fd, Scene *sce) sce->radio= newdataadr(fd, sce->radio); sce->toolsettings= newdataadr(fd, sce->toolsettings); + + sce->toolsettings->skgen_template = newdataadr(fd, sce->toolsettings->skgen_template); sce->sculptdata.session= NULL; /* SculptData textures */ diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index a89aecf854e..88e6630078f 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -73,7 +73,15 @@ EditBone *addEditBone(char *name, struct ListBase *ebones, struct bArmature *arm /* duplicate method */ void preEditBoneDuplicate(struct ListBase *editbones); EditBone *duplicateEditBone(EditBone *curBone, struct ListBase *editbones, struct Object *ob); -void updateDuplicateSubtarget(EditBone *dupBone, struct Object *ob); +void updateDuplicateSubtarget(EditBone *dupBone, struct ListBase *editbones, struct Object *ob); + +/* duplicate method (cross objects */ + +/* editbones is the target list */ +EditBone *duplicateEditBoneObjects(EditBone *curBone, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob); + +/* editbones is the source list */ +void updateDuplicateSubtargetObjects(EditBone *dupBone, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob); /* -- */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3899600af30..b92799cdf2a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -443,6 +443,7 @@ typedef struct ToolSettings { char skgen_multi_level; /* Skeleton Sketching */ + struct Object *skgen_template; char bone_sketching; char bone_sketching_convert; char skgen_subdivision_number; diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index d799d31c742..59a96bed319 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2338,12 +2338,20 @@ static void view3d_panel_bonesketch_spaces(short cntrl) yco -= 20; uiBlockEndAlign(block); + + yco -= 10; + uiBlockBeginAlign(block); + + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_DIFF, "OB:", 10, yco, 150, 19, &G.scene->toolsettings->skgen_template, "Template Object"); + yco -= 20; uiDefButF(block, NUM, B_DIFF, "Ang:", 10, yco, 50,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); uiDefButF(block, NUM, B_DIFF, "Len:", 60, yco, 50,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); uiDefButF(block, NUM, B_DIFF, "Dist:", 110,yco, 50,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); yco -= 20; + uiBlockEndAlign(block); + if(yco < 0) uiNewPanelHeight(block, height-yco); } } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 63d5b9ce1f5..38d8262ea4d 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -2197,13 +2197,12 @@ static EditBone *add_points_bone (float head[], float tail[]) return ebo; } - -static EditBone *get_named_editbone(char *name) +static EditBone *get_named_editbone_from_list(char *name, ListBase *editbones) { EditBone *eBone; if (name) { - for (eBone=G.edbo.first; eBone; eBone=eBone->next) { + for (eBone=editbones->first; eBone; eBone=eBone->next) { if (!strcmp(name, eBone->name)) return eBone; } @@ -2212,6 +2211,11 @@ static EditBone *get_named_editbone(char *name) return NULL; } +static EditBone *get_named_editbone(char *name) +{ + return get_named_editbone_from_list(name, &G.edbo); +} + /* Call this before doing any duplications * */ void preEditBoneDuplicate(ListBase *editbones) @@ -2225,7 +2229,11 @@ void preEditBoneDuplicate(ListBase *editbones) } } -void updateDuplicateSubtarget(EditBone *dupBone, Object *ob) +/* + * Note: When duplicating cross objects, editbones here is the list of bones + * from the SOURCE object but ob is the DESTINATION object + * */ +void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Object *src_ob, Object *dst_ob) { /* If an edit bone has been duplicated, lets * update it's constraints if the subtarget @@ -2236,7 +2244,7 @@ void updateDuplicateSubtarget(EditBone *dupBone, Object *ob) bConstraint *curcon; ListBase *conlist; - if ( (chan = verify_pose_channel(ob->pose, dupBone->name)) ) { + if ( (chan = verify_pose_channel(dst_ob->pose, dupBone->name)) ) { if ( (conlist = &chan->constraints) ) { for (curcon = conlist->first; curcon; curcon=curcon->next) { /* does this constraint have a subtarget in @@ -2250,8 +2258,9 @@ void updateDuplicateSubtarget(EditBone *dupBone, Object *ob) cti->get_constraint_targets(curcon, &targets); for (ct= targets.first; ct; ct= ct->next) { - if ((ct->tar == G.obedit) && (ct->subtarget[0])) { - oldtarget = get_named_editbone(ct->subtarget); + if ((ct->tar == src_ob) && (ct->subtarget[0])) { + ct->tar = dst_ob; /* update target */ + oldtarget = get_named_editbone_from_list(ct->subtarget, editbones); if (oldtarget) { /* was the subtarget bone duplicated too? If * so, update the constraint to point at the @@ -2273,7 +2282,13 @@ void updateDuplicateSubtarget(EditBone *dupBone, Object *ob) } } -EditBone *duplicateEditBone(EditBone *curBone, ListBase *editbones, Object *ob) +void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob) +{ + updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob); +} + + +EditBone *duplicateEditBoneObjects(EditBone *curBone, ListBase *editbones, Object *src_ob, Object *dst_ob) { EditBone *eBone = MEM_callocN(sizeof(EditBone), "addup_editbone"); @@ -2289,11 +2304,11 @@ EditBone *duplicateEditBone(EditBone *curBone, ListBase *editbones, Object *ob) /* Lets duplicate the list of constraints that the * current bone has. */ - if (ob->pose) { + if (src_ob->pose) { bPoseChannel *chanold, *channew; ListBase *listold, *listnew; - chanold = verify_pose_channel(ob->pose, curBone->name); + chanold = verify_pose_channel(src_ob->pose, curBone->name); if (chanold) { listold = &chanold->constraints; if (listold) { @@ -2301,7 +2316,7 @@ EditBone *duplicateEditBone(EditBone *curBone, ListBase *editbones, Object *ob) * yet as the new bones created here are still 'EditBones' not 'Bones'. */ channew = - verify_pose_channel(ob->pose, eBone->name); + verify_pose_channel(dst_ob->pose, eBone->name); if (channew) { /* copy transform locks */ channew->protectflag = chanold->protectflag; @@ -2327,14 +2342,14 @@ EditBone *duplicateEditBone(EditBone *curBone, ListBase *editbones, Object *ob) } } - /* --------------------WARNING-------------------- - * - * need to call static void updateDuplicateSubtarget(EditBone *dupBone) at some point - * */ - return eBone; } +EditBone *duplicateEditBone(EditBone *curBone, ListBase *editbones, Object *ob) +{ + return duplicateEditBoneObjects(curBone, editbones, ob, ob); +} + void adduplicate_armature(void) { bArmature *arm= G.obedit->data; @@ -2448,7 +2463,7 @@ void adduplicate_armature(void) /* Lets try to fix any constraint subtargets that might have been duplicated */ - updateDuplicateSubtarget(eBone, OBACT); + updateDuplicateSubtarget(eBone, &G.edbo, OBACT); } } } diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index a51c9ec0c43..fb9ba740ec3 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -398,7 +398,7 @@ static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone) } /************************************** CLONING TEMPLATES **********************************************/ -static RigControl *cloneControl(RigGraph *rg, RigControl *src_ctrl, GHash *ptr_hash) +static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash) { RigControl *ctrl; @@ -411,7 +411,7 @@ static RigControl *cloneControl(RigGraph *rg, RigControl *src_ctrl, GHash *ptr_h ctrl->flag = src_ctrl->flag; - ctrl->bone = duplicateEditBone(src_ctrl->bone, rg->editbones, rg->ob); + ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, rg->editbones, src_rg->ob, rg->ob); ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone); @@ -420,7 +420,7 @@ static RigControl *cloneControl(RigGraph *rg, RigControl *src_ctrl, GHash *ptr_h return ctrl; } -static RigArc *cloneArc(RigGraph *rg, RigArc *src_arc, GHash *ptr_hash) +static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash *ptr_hash) { RigEdge *src_edge; RigArc *arc; @@ -452,7 +452,7 @@ static RigArc *cloneArc(RigGraph *rg, RigArc *src_arc, GHash *ptr_hash) if (src_edge->bone != NULL) { - edge->bone = duplicateEditBone(src_edge->bone, rg->editbones, rg->ob); + edge->bone = duplicateEditBoneObjects(src_edge->bone, rg->editbones, src_rg->ob, rg->ob); edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone); } @@ -463,7 +463,7 @@ static RigArc *cloneArc(RigGraph *rg, RigArc *src_arc, GHash *ptr_hash) return arc; } -static RigGraph *cloneRigGraph(RigGraph *src) +static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob) { GHash *ptr_hash; RigNode *node; @@ -475,10 +475,11 @@ static RigGraph *cloneRigGraph(RigGraph *src) rg = newRigGraph(); - rg->ob = src->ob; - rg->editbones = src->editbones; + rg->ob = ob; + rg->editbones = editbones; preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */ + preEditBoneDuplicate(src->editbones); /* prime bones for duplication */ /* Clone nodes */ for (node = src->nodes.first; node; node = node->next) @@ -492,13 +493,13 @@ static RigGraph *cloneRigGraph(RigGraph *src) /* Clone arcs */ for (arc = src->arcs.first; arc; arc = arc->next) { - cloneArc(rg, arc, ptr_hash); + cloneArc(rg, src, arc, ptr_hash); } /* Clone controls */ for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next) { - cloneControl(rg, ctrl, ptr_hash); + cloneControl(rg, src, ctrl, ptr_hash); } /* Relink bones properly */ @@ -512,7 +513,7 @@ static RigGraph *cloneRigGraph(RigGraph *src) { EditBone *bone; - updateDuplicateSubtarget(edge->bone, rg->ob); + updateDuplicateSubtargetObjects(edge->bone, src->editbones, src->ob, rg->ob); bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent); @@ -528,7 +529,7 @@ static RigGraph *cloneRigGraph(RigGraph *src) { EditBone *bone; - updateDuplicateSubtarget(ctrl->bone, rg->ob); + updateDuplicateSubtargetObjects(ctrl->bone, src->editbones, src->ob, rg->ob); bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent); @@ -2804,23 +2805,32 @@ void BIF_retargetArmature() void BIF_retargetArc(ReebArc *earc) { Object *ob; - RigGraph *template; + RigGraph *template_rigg; RigGraph *rigg; RigArc *iarc; bArmature *arm; - - ob = G.obedit; - arm = ob->data; - template = armatureSelectedToGraph(ob, arm); - - if (template->arcs.first == NULL) + if (G.scene->toolsettings->skgen_template && + G.scene->toolsettings->skgen_template->type == OB_ARMATURE) { - error("No deforming bones selected"); + ob = G.scene->toolsettings->skgen_template; + arm = ob->data; + template_rigg = armatureToGraph(ob, arm); + } + else + { + ob = G.obedit; + arm = ob->data; + template_rigg = armatureSelectedToGraph(ob, arm); + } + + if (template_rigg->arcs.first == NULL) + { + error("No Template and no deforming bones selected"); return; } - rigg = cloneRigGraph(template); + rigg = cloneRigGraph(template_rigg, &G.edbo, G.obedit); iarc = rigg->arcs.first; @@ -2832,7 +2842,7 @@ void BIF_retargetArc(ReebArc *earc) finishRetarget(rigg); - RIG_freeRigGraph((BGraph*)template); + RIG_freeRigGraph((BGraph*)template_rigg); RIG_freeRigGraph((BGraph*)rigg); BIF_undo_push("Retarget Arc"); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 2b4bc9b89b0..5da96cd61d5 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -355,12 +355,13 @@ int peelObjects(ListBase *depth_peels, short mval[2]) } /*********************** CONVERSION ***************************/ -ReebNode *sk_pointToNode(SK_Point *pt) +ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4]) { ReebNode *node; node = MEM_callocN(sizeof(ReebNode), "reeb node"); VECCOPY(node->p, pt->p); + Mat4MulVecfl(imat, node->p); if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_ROLL) { @@ -370,14 +371,14 @@ ReebNode *sk_pointToNode(SK_Point *pt) return node; } -ReebArc *sk_strokeToArc(SK_Stroke *stk) +ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4]) { ReebArc *arc; int i; arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); - arc->head = sk_pointToNode(stk->points); - arc->tail = sk_pointToNode(sk_lastStrokePoint(stk)); + arc->head = sk_pointToNode(stk->points, imat); + arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat); arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */ arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets"); @@ -385,6 +386,8 @@ ReebArc *sk_strokeToArc(SK_Stroke *stk) for (i = 0; i < arc->bcount; i++) { VECCOPY(arc->buckets[i].p, stk->points[i + 1].p); + Mat4MulVecfl(imat, arc->buckets[i].p); + if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_ROLL) { arc->buckets[i].no = stk->points[i + 1].no; @@ -396,7 +399,12 @@ ReebArc *sk_strokeToArc(SK_Stroke *stk) void sk_retargetStroke(SK_Stroke *stk) { - ReebArc *arc = sk_strokeToArc(stk); + float imat[4][4]; + ReebArc *arc; + + Mat4Invert(imat, G.obedit->obmat); + + arc = sk_strokeToArc(stk, imat); BIF_retargetArc(arc); From d99550e35efc470af395760faebcd976ecc6167c Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 6 Nov 2008 01:30:24 +0000 Subject: [PATCH 039/252] merging 17300:17342 --- SConstruct | 2 +- config/darwin-config.py | 4 +- config/linux2-config.py | 4 +- config/linuxcross-config.py | 2 +- config/openbsd3-config.py | 4 +- config/sunos5-config.py | 6 +- config/win32-mingw-config.py | 4 +- config/win32-vc-config.py | 5 + extern/libopenjpeg/SConscript | 14 +- extern/libredcode/SConscript | 12 - extern/libredcode/format.c | 5 + release/scripts/export_m3g.py | 2 +- release/scripts/image_auto_layout.py | 9 +- release/scripts/import_lightwave_motion.py | 2 +- release/scripts/scripttemplate_gamelogic.py | 3 +- source/blender/blenkernel/BKE_lattice.h | 3 + source/blender/blenkernel/BKE_shrinkwrap.h | 4 + source/blender/blenkernel/BKE_writeffmpeg.h | 2 - source/blender/blenkernel/intern/blender.c | 12 +- source/blender/blenkernel/intern/deform.c | 5 +- source/blender/blenkernel/intern/exotic.c | 6 +- source/blender/blenkernel/intern/lattice.c | 12 + source/blender/blenkernel/intern/modifier.c | 12 +- source/blender/blenkernel/intern/shrinkwrap.c | 29 +-- .../blender/blenkernel/intern/simple_deform.c | 10 +- source/blender/blenkernel/intern/texture.c | 9 + .../blender/blenkernel/intern/writeffmpeg.c | 13 -- source/blender/imbuf/intern/IMB_anim.h | 6 +- source/blender/imbuf/intern/amiga.c | 6 +- source/blender/imbuf/intern/anim.c | 9 +- source/blender/imbuf/intern/readimage.c | 5 +- source/blender/imbuf/intern/util.c | 25 +- source/blender/src/buttons_shading.c | 16 +- source/blender/src/editmesh_mods.c | 2 +- source/blender/src/reeb.c | 1 + source/gameengine/Ketsji/KX_BlenderMaterial.h | 3 + source/gameengine/VideoTexture/Exception.cpp | 6 +- source/gameengine/VideoTexture/FilterBase.h | 6 + .../VideoTexture/FilterBlueScreen.cpp | 6 +- .../VideoTexture/FilterBlueScreen.h | 15 +- .../gameengine/VideoTexture/FilterColor.cpp | 22 +- source/gameengine/VideoTexture/FilterColor.h | 36 +-- .../gameengine/VideoTexture/FilterNormal.cpp | 10 +- source/gameengine/VideoTexture/FilterNormal.h | 27 ++- .../gameengine/VideoTexture/FilterSource.cpp | 46 ++++ source/gameengine/VideoTexture/FilterSource.h | 43 +++- source/gameengine/VideoTexture/ImageBuff.cpp | 12 +- source/gameengine/VideoTexture/ImageMix.cpp | 10 +- .../gameengine/VideoTexture/ImageRender.cpp | 12 +- .../gameengine/VideoTexture/ImageViewport.cpp | 18 +- source/gameengine/VideoTexture/PyTypeList.cpp | 2 +- source/gameengine/VideoTexture/Texture.cpp | 22 +- source/gameengine/VideoTexture/Texture.h | 7 +- .../gameengine/VideoTexture/VideoFFmpeg.cpp | 216 ++++++++++++++---- source/gameengine/VideoTexture/VideoFFmpeg.h | 15 +- .../gameengine/VideoTexture/blendVideoTex.cpp | 6 +- tools/Blender.py | 10 +- 57 files changed, 565 insertions(+), 250 deletions(-) diff --git a/SConstruct b/SConstruct index 91603ce7724..968266bd6d1 100644 --- a/SConstruct +++ b/SConstruct @@ -227,7 +227,7 @@ if env['OURPLATFORM'] == 'linux2' : context.Result(result) return result - env2 = env.Copy( LIBPATH = env['BF_OPENAL'] ) + env2 = env.Clone( LIBPATH = env['BF_OPENAL'] ) sconf_temp = mkdtemp() conf = Configure( env2, {'CheckFreeAlut' : CheckFreeAlut}, sconf_temp, '/dev/null' ) if conf.CheckFreeAlut( env2 ): diff --git a/config/darwin-config.py b/config/darwin-config.py index 547d655b531..7c118b78861 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -260,11 +260,11 @@ CC_WARN = ['-Wall', '-Wno-long-double'] ##LOPTS = --dynamic ##DYNLDFLAGS = -shared $(LDFLAGS) -BF_PROFILE_FLAGS = ' -pg -g ' +BF_PROFILE_CCFLAGS = ['-pg', '-g '] BF_PROFILE = False BF_DEBUG = False -BF_DEBUG_FLAGS = '-g' +BF_DEBUG_CCFLAGS = ['-g'] BF_BUILDDIR='../build/darwin' BF_INSTALLDIR='../install/darwin' diff --git a/config/linux2-config.py b/config/linux2-config.py index ca07bf10ab8..19b62dd2395 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -197,11 +197,11 @@ LLIBS = 'util c m dl pthread stdc++' ##LOPTS = --dynamic ##DYNLDFLAGS = -shared $(LDFLAGS) -BF_PROFILE_FLAGS = ['-pg','-g'] BF_PROFILE = False +BF_PROFILE_CCFLAGS = ['-pg','-g'] BF_DEBUG = False -BF_DEBUG_FLAGS = '-g' +BF_DEBUG_CCFLAGS = ['-g'] BF_BUILDDIR = '../build/linux2' BF_INSTALLDIR='../install/linux2' diff --git a/config/linuxcross-config.py b/config/linuxcross-config.py index c10e9d76cb5..4c5f4859a6c 100644 --- a/config/linuxcross-config.py +++ b/config/linuxcross-config.py @@ -144,7 +144,7 @@ CC_WARN = [ '-Wall' ] LLIBS = [ '-ldxguid', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz'] #'-lutil', '-lc', '-lm', '-ldl', '-lpthread' ] BF_DEBUG = False -BF_DEBUG_FLAGS= '' +BF_DEBUG_CCFLAGS= [] BF_BUILDDIR = '../build/linuxcross' BF_INSTALLDIR='../install/linuxcross' diff --git a/config/openbsd3-config.py b/config/openbsd3-config.py index 0a4f75e3bcc..cd46d11867e 100644 --- a/config/openbsd3-config.py +++ b/config/openbsd3-config.py @@ -155,11 +155,11 @@ LLIBS = 'm stdc++ pthread util' ##LOPTS = --dynamic ##DYNLDFLAGS = -shared $(LDFLAGS) -BF_PROFILE_FLAGS = ' -pg -g ' +BF_PROFILE_CCFLAGS = ['-pg', '-g'] BF_PROFILE = False BF_DEBUG = False -BF_DEBUG_FLAGS = '-g' +BF_DEBUG_CCFLAGS = ['-g'] BF_BUILDDIR='../build/openbsd3' BF_INSTALLDIR='../install/openbsd3' diff --git a/config/sunos5-config.py b/config/sunos5-config.py index 2343ce69060..4e7e99bc884 100644 --- a/config/sunos5-config.py +++ b/config/sunos5-config.py @@ -169,15 +169,15 @@ LLIBS = 'c m dl pthread stdc++' ##LOPTS = --dynamic ##DYNLDFLAGS = -shared $(LDFLAGS) -BF_PROFILE_FLAGS = ['-pg','-g'] +BF_PROFILE_CCFLAGS = ['-pg','-g'] BF_PROFILE = False BF_DEBUG = False -BF_DEBUG_FLAGS = '' +BF_DEBUG_CCFLAGS = [] BF_BUILDDIR = '../build/sunos5' BF_INSTALLDIR='../install/sunos5' BF_DOCDIR='../install/doc' -PLATFORM_LINKFLAGS = [''] +PLATFORM_LINKFLAGS = [] diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py index bdeca1ddc91..15bfce80f89 100644 --- a/config/win32-mingw-config.py +++ b/config/win32-mingw-config.py @@ -160,9 +160,9 @@ CC_WARN = [ '-Wall' ] LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32', '-lm', '-lws2_32', '-lz', '-lstdc++'] BF_DEBUG = False -BF_DEBUG_FLAGS= '-g' +BF_DEBUG_CCFLAGS= ['-g'] -BF_PROFILE_FLAGS = ['-pg','-g'] +BF_PROFILE_CCFLAGS = ['-pg','-g'] BF_PROFILE = False BF_BUILDDIR = '..\\build\\win32-mingw' diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index a5aa76c2868..9a41f7ee557 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -150,6 +150,11 @@ BF_QUICKTIME_INC = '${BF_QUICKTIME}/CIncludes' BF_QUICKTIME_LIB = 'qtmlClient' BF_QUICKTIME_LIBPATH = '${BF_QUICKTIME}/Libraries' +WITH_BF_OPENJPEG = True + +WITH_BF_REDCODE = False +BF_REDCODE_INC = '#extern' + WITH_BF_STATICOPENGL = False BF_OPENGL_INC = '${BF_OPENGL}/include' BF_OPENGL_LIBINC = '${BF_OPENGL}/lib' diff --git a/extern/libopenjpeg/SConscript b/extern/libopenjpeg/SConscript index f0a93f6e2d9..837701eeae0 100644 --- a/extern/libopenjpeg/SConscript +++ b/extern/libopenjpeg/SConscript @@ -7,14 +7,18 @@ Import('env') sources = env.Glob('*.c') incs = '.' -flags = "-Wall -O3 -ffast-math -std=c99" +if env['OURPLATFORM'] == 'win32-vc': + flags = [] +else: + flags = ['-Wall', '-O3', '-ffast-math', '-std=c99'] -oj_env = env.Copy(); -oj_env.Replace(CCFLAGS = '') -oj_env.Replace(BF_DEBUG_FLAGS = '') +oj_env = env.Clone() +if not env['OURPLATFORM'] == 'win32-vc': + oj_env.Replace(CCFLAGS = '') + oj_env.Replace(BF_DEBUG_FLAGS = '') oj_env.BlenderLib ( libname='extern_openjpeg', sources=sources, includes=Split(incs), defines=[], libtype=['core','intern','player'], - priority=[10, 10, 300], compileflags = Split(flags)) + priority=[10, 10, 300], compileflags = flags) diff --git a/extern/libredcode/SConscript b/extern/libredcode/SConscript index 4e83ba5cbb4..9fd25ad63c7 100644 --- a/extern/libredcode/SConscript +++ b/extern/libredcode/SConscript @@ -9,18 +9,6 @@ Import('env') sources = env.Glob('*.c') incs = '. ../libopenjpeg' -root = "extern/libredcode" - -if not os.path.isdir(root + "/include"): - os.mkdir(root + "/include"); -if not os.path.isdir(root + "/include/redcode"): - os.mkdir(root + "/include/redcode"); - -for h in env.Glob('*.h'): - shutil.copyfile(root + "/" + h, - root + "/include/redcode/" + h) - - env.BlenderLib ( libname='extern_redcode', sources=sources, includes=Split(incs), defines=[], diff --git a/extern/libredcode/format.c b/extern/libredcode/format.c index 35410e9e269..4677c49b8a5 100644 --- a/extern/libredcode/format.c +++ b/extern/libredcode/format.c @@ -1,4 +1,9 @@ +#ifdef _WIN32 +#include +#else #include +#endif + #include #include #include diff --git a/release/scripts/export_m3g.py b/release/scripts/export_m3g.py index 86ac03cc407..c74e7acbcd3 100644 --- a/release/scripts/export_m3g.py +++ b/release/scripts/export_m3g.py @@ -11,7 +11,7 @@ Tooltip: 'Export to M3G' # # Source: http://www.nelson-games.de/bl2m3g/source # -# $Id: m3g_export.py,v 0.1 2005/04/19 12:25 gerhardv Exp gerhardv $ +# $Id$ # # Author: Gerhard Völkl # diff --git a/release/scripts/image_auto_layout.py b/release/scripts/image_auto_layout.py index 19ee396c3b1..c6f97a25434 100644 --- a/release/scripts/image_auto_layout.py +++ b/release/scripts/image_auto_layout.py @@ -265,8 +265,8 @@ def consolidate_mesh_images(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PR render_context.setRenderWinSize(100) render_context.setImageType(Render.PNG) render_context.enableExtensions(True) - render_context.enableSky() # No alpha needed. - render_context.enableRGBColor() + render_context.enablePremultiply() # No alpha needed. + render_context.enableRGBAColor() render_context.threads = 2 #Render.EnableDispView() # Broken?? @@ -275,8 +275,9 @@ def consolidate_mesh_images(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PR render_mat= B.Material.New() render_mat.mode |= B.Material.Modes.SHADELESS render_mat.mode |= B.Material.Modes.TEXFACE - - + render_mat.mode |= B.Material.Modes.ZTRANSP + render_mat.setAlpha(0.0) + render_me= B.Mesh.New() render_me.verts.extend([Vector(0,0,0)]) # Stupid, dummy vert, preverts errors. when assigning UV's/ render_ob= B.Object.New('Mesh') diff --git a/release/scripts/import_lightwave_motion.py b/release/scripts/import_lightwave_motion.py index c242a9f6bd3..20c87dfd5c6 100644 --- a/release/scripts/import_lightwave_motion.py +++ b/release/scripts/import_lightwave_motion.py @@ -22,7 +22,7 @@ Be sure to set the framerate correctly """ -# $Id: export_lightwave_motion.py 9924 2007-01-27 02:15:14Z campbellbarton $ +# $Id$ # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/release/scripts/scripttemplate_gamelogic.py b/release/scripts/scripttemplate_gamelogic.py index 17095251155..7184d7e424f 100644 --- a/release/scripts/scripttemplate_gamelogic.py +++ b/release/scripts/scripttemplate_gamelogic.py @@ -83,7 +83,8 @@ def main(): own.life += ob.life ob.life = 0 print own.life - """ + """ + main() ''' diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 5620674e791..dc7c9dcd5e5 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -35,6 +35,7 @@ struct Lattice; struct Object; struct DerivedMesh; struct BPoint; +struct MDeformVert; extern struct Lattice *editLatt; @@ -67,5 +68,7 @@ float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3]; void lattice_applyVertexCos(struct Object *ob, float (*vertexCos)[3]); void lattice_calc_modifiers(struct Object *ob); +struct MDeformVert* lattice_get_deform_verts(struct Object *lattice); + #endif diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index e8276238ff2..eed22ff9d8e 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -96,6 +96,7 @@ void space_transform_invert_normal(const SpaceTransform *data, float *no); struct Object; struct DerivedMesh; struct ShrinkwrapModifierData; +struct MDeformVert; struct BVHTree; @@ -109,6 +110,9 @@ typedef struct ShrinkwrapCalcData float (*vertexCos)[3]; //vertexs being shrinkwraped int numVerts; + struct MDeformVert* dvert; //Pointer to mdeform array + int vgroup; //Vertex group num + struct DerivedMesh *target; //mesh we are shrinking to SpaceTransform local2target; //transform to move bettwem local and target space diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 50053446294..02f7ba6f860 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -59,8 +59,6 @@ extern void start_ffmpeg(struct RenderData *rd, int rectx, int recty); extern void end_ffmpeg(void); extern void append_ffmpeg(int frame, int *pixels, int rectx, int recty); -void silence_log_ffmpeg(int quiet); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 1fe6447752e..5dcccc56d06 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -30,11 +30,15 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifndef WIN32 - #include // for read close - #include // for MAXPATHLEN +#ifndef _WIN32 + #include // for read close + #include // for MAXPATHLEN #else - #include // for open close read + #include // for open close read + #define open _open + #define read _read + #define close _close + #define write _write #endif #include diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 3143c5e4df2..47736865273 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -239,12 +239,9 @@ float deformvert_get_weight(const struct MDeformVert *dvert, int group_num) float vertexgroup_get_vertex_weight(const struct MDeformVert *dvert, int index, int group_num) { - if(group_num == -1) + if(group_num == -1 || dvert == NULL) return 1.0; - if(dvert == 0) - return 0.0; - return deformvert_get_weight(dvert+index, group_num); } diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index 9fb8d17d730..ee3fd59fe9f 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -76,10 +76,14 @@ #include #include -#ifndef WIN32 +#ifndef _WIN32 #include #else #include +#define open _open +#define read _read +#define close _close +#define write _write #endif #include "MEM_guardedalloc.h" diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 54915058bab..6614c657647 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -928,3 +928,15 @@ void lattice_calc_modifiers(Object *ob) BLI_addtail(&ob->disp, dl); } } + +struct MDeformVert* lattice_get_deform_verts(struct Object *oblatt) +{ + if(oblatt->type == OB_LATTICE) + { + Lattice *lt = (oblatt==G.obedit)?editLatt:(Lattice*)oblatt->data; + return lt->dvert; + } + + return NULL; +} + diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 13dc2e834f2..6bdd395a2ac 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7804,9 +7804,10 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived { if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + else if(ob->type==OB_LATTICE) dm = NULL; else return; - if(dataMask & CD_MVERT) + if(dm != NULL && (dataMask & CD_MVERT)) { CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); @@ -7828,9 +7829,10 @@ static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditM { if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data); + else if(ob->type==OB_LATTICE) dm = NULL; else return; - if(dataMask & CD_MVERT) + if(dm != NULL && (dataMask & CD_MVERT)) { CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); @@ -7916,9 +7918,10 @@ static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, Deriv { if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + else if(ob->type==OB_LATTICE) dm = NULL; else return; - if(dataMask & CD_MVERT) + if(dm != NULL && (dataMask & CD_MVERT)) { CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); @@ -7942,9 +7945,10 @@ static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, Edi { if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data); + else if(ob->type==OB_LATTICE) dm = NULL; else return; - if(dataMask & CD_MVERT) + if(dm != NULL && (dataMask & CD_MVERT)) { CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 28bf7aee884..ab98fb1f007 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -41,6 +41,7 @@ #include "BKE_shrinkwrap.h" #include "BKE_DerivedMesh.h" +#include "BKE_lattice.h" #include "BKE_utildefines.h" #include "BKE_deform.h" #include "BKE_cdderivedmesh.h" @@ -161,6 +162,18 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM calc.numVerts = numVerts; calc.vertexCos = vertexCos; + //DeformVertex + calc.vgroup = get_named_vertexgroup_num(calc.ob, calc.smd->vgroup_name); + if(calc.original) + { + calc.dvert = calc.original->getVertDataArray(calc.original, CD_MDEFORMVERT); + } + else if(calc.ob->type == OB_LATTICE) + { + calc.dvert = lattice_get_deform_verts(calc.ob); + } + + 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 @@ -207,8 +220,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; @@ -230,7 +241,7 @@ 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); @@ -342,11 +353,6 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) 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; - - //Raycast and tree stuff BVHTreeRayHit hit; BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; //target @@ -441,7 +447,7 @@ do 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); + float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup); if(weight == 0.0f) continue; @@ -520,9 +526,6 @@ 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; @@ -547,7 +550,7 @@ 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 diff --git a/source/blender/blenkernel/intern/simple_deform.c b/source/blender/blenkernel/intern/simple_deform.c index 0eb710fa48e..2978a6f7f01 100644 --- a/source/blender/blenkernel/intern/simple_deform.c +++ b/source/blender/blenkernel/intern/simple_deform.c @@ -32,6 +32,7 @@ #include "BKE_simple_deform.h" #include "BKE_DerivedMesh.h" +#include "BKE_lattice.h" #include "BKE_deform.h" #include "BKE_utildefines.h" #include "BLI_arithb.h" @@ -204,7 +205,14 @@ void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, s if(dm) - dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + { + dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + } + else if(ob->type == OB_LATTICE) + { + dvert = lattice_get_deform_verts(ob); + } + switch(smd->mode) diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index bb726887d32..ab9e6f9af41 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -348,6 +348,15 @@ int do_colorband(ColorBand *coba, float in, float out[4]) else fac= 0.0f; + if (coba->ipotype==4) { + /* constant */ + out[0]= cbd2->r; + out[1]= cbd2->g; + out[2]= cbd2->b; + out[3]= cbd2->a; + return 1; + } + if(coba->ipotype>=2) { /* ipo from right to left: 3 2 1 0 */ diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 642b4fd1b19..cef6f802729 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -34,7 +34,6 @@ #include #include #include -#include #if LIBAVFORMAT_VERSION_INT < (49 << 16) #define FFMPEG_OLD_FRAME_RATE 1 @@ -105,18 +104,6 @@ static RenderData *ffmpeg_renderdata = 0; #define FFMPEG_AUTOSPLIT_SIZE 2000000000 -void silence_log_ffmpeg(int quiet) -{ - if (quiet) - { - av_log_set_level(AV_LOG_QUIET); - } - else - { - av_log_set_level(AV_LOG_INFO); - } -} - /* Delete a picture buffer */ static void delete_picture(AVFrame* f) diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index 7dc1f966b71..745248d3218 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -82,7 +82,11 @@ #endif #ifdef WITH_REDCODE -#include +#ifdef _WIN32 /* on windows we use the one in extern instead */ +#include "libredcode/format.h" +#else +#include "libredcode/format.h" +#endif #endif #include "IMB_imbuf_types.h" diff --git a/source/blender/imbuf/intern/amiga.c b/source/blender/imbuf/intern/amiga.c index 3d52a287a31..534e4945aa3 100644 --- a/source/blender/imbuf/intern/amiga.c +++ b/source/blender/imbuf/intern/amiga.c @@ -29,8 +29,12 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef WIN32 +#ifdef _WIN32 #include +#define open _open +#define read _read +#define close _close +#define write _write #endif #include "imbuf.h" #include "imbuf_patch.h" diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c index c0e84b73e47..80bf401bec0 100644 --- a/source/blender/imbuf/intern/anim.c +++ b/source/blender/imbuf/intern/anim.c @@ -97,8 +97,13 @@ #endif #ifdef WITH_REDCODE -#include -#include +#ifdef _WIN32 /* on windows we use the ones in extern instead */ +#include "libredcode/format.h" +#include "libredcode/codec.h" +#else +#include "libredcode/format.h" +#include "libredcode/codec.h" +#endif #endif /****/ diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 566df53a25e..05e7921665b 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -29,11 +29,14 @@ * $Id$ */ -#ifdef WIN32 +#ifdef _WIN32 #include #include #include #include "mmap_win.h" +#define open _open +#define read _read +#define close _close #endif #include "BLI_blenlib.h" diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 05d594019a5..c86f9b017bf 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -29,11 +29,17 @@ * $Id$ */ +#ifdef _WIN32 +#include +#define open _open +#define read _read +#define close _close +#endif + #include "BLI_blenlib.h" #include "DNA_userdef_types.h" #include "BKE_global.h" -#include "BKE_writeffmpeg.h" /* for silence_log_ffmpeg */ #include "imbuf.h" #include "imbuf_patch.h" @@ -66,6 +72,7 @@ #include #include //#include +#include #if LIBAVFORMAT_VERSION_INT < (49 << 16) #define FFMPEG_OLD_FRAME_RATE 1 @@ -231,6 +238,19 @@ static int isqtime (char *name) { #endif #ifdef WITH_FFMPEG + +void silence_log_ffmpeg(int quiet) +{ + if (quiet) + { + av_log_set_level(AV_LOG_QUIET); + } + else + { + av_log_set_level(AV_LOG_INFO); + } +} + extern void do_init_ffmpeg(); void do_init_ffmpeg() { @@ -262,7 +282,8 @@ static AVCodecContext* get_codec_from_stream(AVStream* stream) static int isffmpeg (char *filename) { AVFormatContext *pFormatCtx; - int i, videoStream; + unsigned int i; + int videoStream; AVCodec *pCodec; AVCodecContext *pCodecCtx; diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 5687651a6c5..f1250c975fb 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1468,10 +1468,9 @@ static void draw_colorband_buts(uiBlock *block, ColorBand *coba, int xoffs, int uiDefButS(block, NUM, redraw, "Cur:", 117+xoffs,95+yoffs,81,20, &coba->cur, 0.0, (float)(coba->tot-1), 0, 0, "Displays the active color from the colorband"); bt= uiDefBut(block, BUT, redraw, "Del", 199+xoffs,95+yoffs,37,20, 0, 0, 0, 0, 0, "Deletes the active position"); uiButSetFunc(bt, colorband_del_cb, coba, NULL); - uiDefButS(block, ROW, redraw, "E", 236+xoffs,95+yoffs,16,20, &coba->ipotype, 5.0, 1.0, 0, 0, "Sets interpolation type 'Ease' (quadratic) "); - uiDefButS(block, ROW, redraw, "C", 252+xoffs,95+yoffs,16,20, &coba->ipotype, 5.0, 3.0, 0, 0, "Sets interpolation type Cardinal"); - uiDefButS(block, ROW, redraw, "L", 268+xoffs,95+yoffs,16,20, &coba->ipotype, 5.0, 0.0, 0, 0, "Sets interpolation type Linear"); - uiDefButS(block, ROW, redraw, "S", 284+xoffs,95+yoffs,16,20, &coba->ipotype, 5.0, 2.0, 0, 0, "Sets interpolation type B-Spline"); + + uiDefButS(block, MENU, redraw, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", + 236+xoffs, 95+yoffs, 64, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Sets interpolation type"); uiDefBut(block, BUT_COLORBAND, redraw, "", xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, ""); @@ -1506,11 +1505,10 @@ void draw_colorband_buts_small(uiBlock *block, ColorBand *coba, rctf *butr, int uiButSetFunc(bt, colorband_add_cb, coba, NULL); bt= uiDefBut(block, BUT, event, "Del", xs+8.0f*unit,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Deletes the active position"); uiButSetFunc(bt, colorband_del_cb, coba, NULL); - uiDefButS(block, ROW, event, "E", xs+10.0f*unit,butr->ymin+20.0f,unit,20, &coba->ipotype, 5.0, 1.0, 0, 0, "Sets interpolation type 'Ease' (quadratic) "); - uiDefButS(block, ROW, event, "C", xs+11.0f*unit,butr->ymin+20.0f,unit,20, &coba->ipotype, 5.0, 3.0, 0, 0, "Sets interpolation type Cardinal"); - uiDefButS(block, ROW, event, "L", xs+12.0f*unit,butr->ymin+20.0f,unit,20, &coba->ipotype, 5.0, 0.0, 0, 0, "Sets interpolation type Linear"); - uiDefButS(block, ROW, event, "S", xs+13.0f*unit,butr->ymin+20.0f,unit,20, &coba->ipotype, 5.0, 2.0, 0, 0, "Sets interpolation type B-Spline"); - + + uiDefButS(block, MENU, event, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", + xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Sets interpolation type"); + uiDefBut(block, BUT_COLORBAND, event, "", xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, ""); uiBlockEndAlign(block); diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 81d0ffeeb3b..3dbbe7d7336 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -1864,7 +1864,7 @@ void faceloop_select(EditEdge *startedge, int select) looking= 0; for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->e4 && efa->f1==0) { /* not done quad */ + if(efa->h==0 && efa->e4 && efa->f1==0) { /* not done quad */ if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */ /* if edge tagged, select opposing edge and mark face ok */ diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index 3678106e9ef..b37087064cb 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -69,6 +69,7 @@ #include "reeb.h" + ReebGraph *GLOBAL_RG = NULL; ReebGraph *FILTERED_RG = NULL; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index b858fa3754c..6e5db1b56c1 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -70,6 +70,9 @@ public: BL_Texture * getTex (unsigned int idx) { return (idx < MAXTEX) ? mTextures + idx : NULL; } + Image * getImage (unsigned int idx) { + return (idx < MAXTEX && mMaterial) ? mMaterial->img[idx] : NULL; + } // for ipos void UpdateIPO( diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp index 3ac8b8e321d..3f939de6bc2 100644 --- a/source/gameengine/VideoTexture/Exception.cpp +++ b/source/gameengine/VideoTexture/Exception.cpp @@ -168,15 +168,15 @@ void Exception::setXptDesc (void) } // add result code // length of result code - const size_t rsltSize = 10; + const size_t rsltSize = 11; // delimit description const char delimRslt[] = ": "; // set text of description char rsltTxt[rsltSize]; std::ostrstream os(rsltTxt, rsltSize); - os << std::hex << m_hRslt << delimRslt; + os << std::hex << m_hRslt << delimRslt << '\0'; // copy result to description - m_desc.insert(0, rsltTxt, rsltSize); + m_desc.insert(0, rsltTxt); // copy exception description to last exception string m_lastError = m_desc; } diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h index c530e385ada..b6080f018d5 100644 --- a/source/gameengine/VideoTexture/FilterBase.h +++ b/source/gameengine/VideoTexture/FilterBase.h @@ -29,6 +29,12 @@ http://www.gnu.org/copyleft/lesser.txt. #include "PyTypeList.h" +#define VT_C(v,idx) ((unsigned char*)&v)[idx] +#define VT_R(v) ((unsigned char*)&v)[0] +#define VT_G(v) ((unsigned char*)&v)[1] +#define VT_B(v) ((unsigned char*)&v)[2] +#define VT_A(v) ((unsigned char*)&v)[3] +#define VT_RGBA(v,r,g,b,a) VT_R(v)=(unsigned char)r, VT_G(v)=(unsigned char)g, VT_B(v)=(unsigned char)b, VT_A(v)=(unsigned char)a // forward declaration class FilterBase; diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 50c3a87ffc4..43d7566102a 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -125,10 +125,10 @@ static int setLimits (PyFilter * self, PyObject * value, void * closure) // attributes structure static PyGetSetDef filterBSGetSets[] = { - {"color", (getter)getColor, (setter)setColor, "blue screen color", NULL}, - {"limits", (getter)getLimits, (setter)setLimits, "blue screen color limits", NULL}, + {(char*)"color", (getter)getColor, (setter)setColor, (char*)"blue screen color", NULL}, + {(char*)"limits", (getter)getLimits, (setter)setLimits, (char*)"blue screen color limits", NULL}, // attributes from FilterBase class - {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL}, + {(char*)"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, (char*)"previous pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.h b/source/gameengine/VideoTexture/FilterBlueScreen.h index 20660804f78..820e4a44501 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.h +++ b/source/gameengine/VideoTexture/FilterBlueScreen.h @@ -63,25 +63,24 @@ protected: short * size, unsigned int pixSize, unsigned int val) { // calculate differences - int difRed = int((val >> 16) & 0xFF) - int(m_color[0]); - int difGreen = int((val >> 8) & 0xFF) - int(m_color[1]); - int difBlue = int(val & 0xFF) - int(m_color[2]); + int difRed = int(VT_R(val)) - int(m_color[0]); + int difGreen = int(VT_G(val)) - int(m_color[1]); + int difBlue = int(VT_B(val)) - int(m_color[2]); // calc distance from "blue screen" color unsigned int dist = (unsigned int)(difRed * difRed + difGreen * difGreen + difBlue * difBlue); // condition for fully transparent color if (m_squareLimits[0] >= dist) // return color with zero alpha - //return 0xFF000000; - return val & 0x00FFFFFF; + VT_A(val) = 0; // condition for fully opaque color else if (m_squareLimits[1] <= dist) // return normal colour - return val | 0xFF000000; + VT_A(val) = 0xFF; // otherwise calc alpha else - return (val & 0x00FFFFFF) | ((((dist - m_squareLimits[0]) << 8) - / m_limitDist) << 24); + VT_A(val) = (((dist - m_squareLimits[0]) << 8) / m_limitDist); + return val; } /// virtual filtering function for byte source diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index a1ddf581aef..22ee729b200 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -34,7 +34,7 @@ http://www.gnu.org/copyleft/lesser.txt. // attributes structure static PyGetSetDef filterGrayGetSets[] = { // attributes from FilterBase class - {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL}, + {(char*)"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, (char*)"previous pixel filter", NULL}, {NULL} }; @@ -164,9 +164,9 @@ static int setMatrix (PyFilter * self, PyObject * value, void * closure) // attributes structure static PyGetSetDef filterColorGetSets[] = { - {"matrix", (getter)getMatrix, (setter)setMatrix, "matrix [4][5] for color calculation", NULL}, + {(char*)"matrix", (getter)getMatrix, (setter)setMatrix, (char*)"matrix [4][5] for color calculation", NULL}, // attributes from FilterBase class - {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL}, + {(char*)"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, (char*)"previous pixel filter", NULL}, {NULL} }; @@ -223,7 +223,7 @@ FilterLevel::FilterLevel (void) for (int r = 0; r < 4; ++r) { levels[r][0] = 0; - levels[r][1] = 0xFF << (r << 3); + levels[r][1] = 0xFF; levels[r][2] = 0xFF; } } @@ -235,7 +235,7 @@ void FilterLevel::setLevels (ColorLevel & lev) for (int r = 0; r < 4; ++r) { for (int c = 0; c < 2; ++c) - levels[r][c] = lev[r][c] << (r << 3); + levels[r][c] = lev[r][c]; levels[r][2] = lev[r][0] < lev[r][1] ? lev[r][1] - lev[r][0] : 1; } } @@ -252,9 +252,9 @@ inline FilterLevel * getFilterLevel (PyFilter * self) static PyObject * getLevels (PyFilter * self, void * closure) { ColorLevel & lev = getFilterLevel(self)->getLevels(); - return Py_BuildValue("((kk)(kk)(kk)(kk))", - lev[0][0], lev[0][1], lev[1][0] >> 8, lev[1][1] >> 8, - lev[2][0] >> 16, lev[2][1] >> 16, lev[3][0] >> 24, lev[3][1] >> 24); + return Py_BuildValue("((HH)(HH)(HH)(HH))", + lev[0][0], lev[0][1], lev[1][0], lev[1][1], + lev[2][0], lev[2][1], lev[3][0], lev[3][1]); } // set color levels @@ -279,7 +279,7 @@ static int setLevels (PyFilter * self, PyObject * value, void * closure) valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - lev[r][c] = (unsigned long)(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c))); + lev[r][c] = (unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error @@ -298,9 +298,9 @@ static int setLevels (PyFilter * self, PyObject * value, void * closure) // attributes structure static PyGetSetDef filterLevelGetSets[] = { - {"levels", (getter)getLevels, (setter)setLevels, "levels matrix [4] (min, max)", NULL}, + {(char*)"levels", (getter)getLevels, (setter)setLevels, (char*)"levels matrix [4] (min, max)", NULL}, // attributes from FilterBase class - {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL}, + {(char*)"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, (char*)"previous pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/FilterColor.h b/source/gameengine/VideoTexture/FilterColor.h index ae2e98fa942..b7e52c4521c 100644 --- a/source/gameengine/VideoTexture/FilterColor.h +++ b/source/gameengine/VideoTexture/FilterColor.h @@ -43,10 +43,13 @@ protected: short * size, unsigned int pixSize, unsigned int val) { // calculate gray value - unsigned int gray = (28 * ((val >> 16) & 0xFF) + 151 * ((val >> 8) & 0xFF) - + 77 * (val & 0xFF)) & 0xFF00; + unsigned int gray = (28 * (VT_B(val)) + 151 * (VT_G(val)) + + 77 * (VT_R(val))) >> 8; // return gray scale value - return (val & 0xFF000000) | gray << 8 | gray | gray >> 8; + VT_R(val) = gray; + VT_G(val) = gray; + VT_B(val) = gray; + return val; } /// virtual filtering function for byte source @@ -82,11 +85,11 @@ protected: ColorMatrix m_matrix; /// calculate one color component - unsigned int calcColor (unsigned int val, short idx) + unsigned char calcColor (unsigned int val, short idx) { - return (((m_matrix[idx][0] * (val & 0xFF) + m_matrix[idx][1] * ((val >> 8) & 0xFF) - + m_matrix[idx][2] * ((val >> 16) & 0xFF) + m_matrix[idx][3] * ((val >> 24) & 0xFF) - + m_matrix[idx][4]) >> 8) & 0xFF) << (idx << 3); + return (((m_matrix[idx][0] * (VT_R(val)) + m_matrix[idx][1] * (VT_G(val)) + + m_matrix[idx][2] * (VT_B(val)) + m_matrix[idx][3] * (VT_A(val)) + + m_matrix[idx][4]) >> 8) & 0xFF); } /// filter pixel template, source int buffer @@ -94,8 +97,9 @@ protected: short * size, unsigned int pixSize, unsigned int val) { // return calculated color - return calcColor(val, 0) | calcColor(val, 1) | calcColor(val, 2) - | calcColor(val, 3); + int color; + VT_RGBA(color, calcColor(val, 0), calcColor(val, 1), calcColor(val, 2), calcColor(val, 3)); + return color; } /// virtual filtering function for byte source @@ -110,7 +114,7 @@ protected: /// type for color levels -typedef unsigned long ColorLevel[4][3]; +typedef unsigned short ColorLevel[4][3]; /// pixel filter for color calculation class FilterLevel : public FilterBase @@ -133,11 +137,10 @@ protected: /// calculate one color component unsigned int calcColor (unsigned int val, short idx) { - unsigned int col = val & (0xFF << (idx << 3)); + unsigned int col = VT_C(val,idx);; if (col <= levels[idx][0]) col = 0; - else if (col >= levels[idx][1]) col = 0xFF << (idx << 3); - else if (idx < 3) col = (((col - levels[idx][0]) << 8) / levels[idx][2]) & (0xFF << (idx << 3)); - else col = (((col - levels[idx][0]) / levels[idx][2]) << 8) & (0xFF << (idx << 3)); + else if (col >= levels[idx][1]) col = 0xFF; + else col = (((col - levels[idx][0]) << 8) / levels[idx][2]) & 0xFF; return col; } @@ -146,8 +149,9 @@ protected: short * size, unsigned int pixSize, unsigned int val) { // return calculated color - return calcColor(val, 0) | calcColor(val, 1) | calcColor(val, 2) - | calcColor(val, 3); + int color; + VT_RGBA(color, calcColor(val, 0), calcColor(val, 1), calcColor(val, 2), calcColor(val, 3)); + return color; } /// virtual filtering function for byte source diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index 514214bec8b..03a79c1c8ce 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -32,7 +32,7 @@ http://www.gnu.org/copyleft/lesser.txt. // implementation FilterNormal // constructor -FilterNormal::FilterNormal (void) : m_colShift(0) +FilterNormal::FilterNormal (void) : m_colIdx(0) { // set default depth setDepth(4); @@ -44,7 +44,7 @@ void FilterNormal::setColor (unsigned short colIdx) // check validity of index if (colIdx < 3) // set color shift - m_colShift = colIdx << 3; + m_colIdx = colIdx; } // set depth @@ -109,10 +109,10 @@ static int setDepth (PyFilter * self, PyObject * value, void * closure) // attributes structure static PyGetSetDef filterNormalGetSets[] = { - {"colorIdx", (getter)getColor, (setter)setColor, "index of color used to calculate normal (0 - red, 1 - green, 2 - blue)", NULL}, - {"depth", (getter)getDepth, (setter)setDepth, "depth of relief", NULL}, + {(char*)"colorIdx", (getter)getColor, (setter)setColor, (char*)"index of color used to calculate normal (0 - red, 1 - green, 2 - blue)", NULL}, + {(char*)"depth", (getter)getDepth, (setter)setDepth, (char*)"depth of relief", NULL}, // attributes from FilterBase class - {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL}, + {(char*)"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, (char*)"previous pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/FilterNormal.h b/source/gameengine/VideoTexture/FilterNormal.h index ec51ca39db9..840043be9a1 100644 --- a/source/gameengine/VideoTexture/FilterNormal.h +++ b/source/gameengine/VideoTexture/FilterNormal.h @@ -43,7 +43,7 @@ public: virtual ~FilterNormal (void) {} /// get index of color used to calculate normals - unsigned short getColor (void) { return m_colShift >> 3; } + unsigned short getColor (void) { return m_colIdx; } /// set index of color used to calculate normals void setColor (unsigned short colIdx); @@ -58,20 +58,28 @@ protected: /// scale to calculate normals float m_depthScale; - /// shift to used color component - unsigned short m_colShift; + /// color index, 0=red, 1=green, 2=blue, 3=alpha + unsigned short m_colIdx; /// filter pixel, source int buffer template unsigned int tFilter (SRC * src, short x, short y, short * size, unsigned int pixSize, unsigned int val = 0) { // get value of required color - int actPix = int((val >> m_colShift) & 0xFF); + int actPix = int(VT_C(val,m_colIdx)); + int upPix = actPix; + int leftPix = actPix; // get upper and left pixel from actual pixel - int upPix = y > 0 ? int((convertPrevious(src - pixSize * size[0], x, y - 1, - size, pixSize) >> m_colShift) & 0xFF) : actPix; - int leftPix = x > 0 ? int((convertPrevious(src - pixSize, x - 1, y, size, pixSize) - >> m_colShift) & 0xFF) : actPix; + if (y > 0) + { + val = convertPrevious(src - pixSize * size[0], x, y - 1, size, pixSize); + upPix = VT_C(val,m_colIdx); + } + if (x > 0) + { + val = convertPrevious(src - pixSize, x - 1, y, size, pixSize); + leftPix = VT_C(val,m_colIdx); + } // height differences (from blue color) float dx = (actPix - leftPix) * m_depthScale; float dy = (actPix - upPix) * m_depthScale; @@ -81,7 +89,8 @@ protected: dy = dy * dz + normScaleKoef; dz += normScaleKoef; // return normal vector converted to color - return 0xFF000000 | int(dz) << 16 | int(dy) << 8 | int(dx); + VT_RGBA(val, dx, dy, dz, 0xFF); + return val; } /// filter pixel, source byte buffer diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp index 8d8749dbc8f..f3676e93a6d 100644 --- a/source/gameengine/VideoTexture/FilterSource.cpp +++ b/source/gameengine/VideoTexture/FilterSource.cpp @@ -77,6 +77,52 @@ PyTypeObject FilterRGB24Type = Filter_allocNew, /* tp_new */ }; +// FilterRGBA32 + +// define python type +PyTypeObject FilterRGBA32Type = +{ + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "VideoTexture.FilterRGBA32", /*tp_name*/ + sizeof(PyFilter), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)Filter_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Source filter RGBA32 objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + NULL, /* tp_methods */ + 0, /* tp_members */ + NULL, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Filter_init, /* tp_init */ + 0, /* tp_alloc */ + Filter_allocNew, /* tp_new */ +}; + // FilterBGR24 // define python type diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h index c3d4e0079f9..7e90747d252 100644 --- a/source/gameengine/VideoTexture/FilterSource.h +++ b/source/gameengine/VideoTexture/FilterSource.h @@ -44,7 +44,34 @@ protected: /// filter pixel, source byte buffer virtual unsigned int filter (unsigned char * src, short x, short y, short * size, unsigned int pixSize, unsigned int val) - { return 0xFF000000 | src[0] << 16 | src[1] << 8 | src[2]; } + { VT_RGBA(val,src[0],src[1],src[2],0xFF); return val; } +}; + +/// class for RGBA32 conversion +class FilterRGBA32 : public FilterBase +{ +public: + /// constructor + FilterRGBA32 (void) {} + /// destructor + virtual ~FilterRGBA32 (void) {} + + /// get source pixel size + virtual unsigned int getPixelSize (void) { return 4; } + +protected: + /// filter pixel, source byte buffer + virtual unsigned int filter (unsigned char * src, short x, short y, + short * size, unsigned int pixSize, unsigned int val) + { + if ((intptr_t(src)&0x3) == 0) + return *(unsigned int*)src; + else + { + VT_RGBA(val,src[0],src[1],src[2],src[3]); + return val; + } + } }; /// class for BGR24 conversion @@ -63,7 +90,7 @@ protected: /// filter pixel, source byte buffer virtual unsigned int filter (unsigned char * src, short x, short y, short * size, unsigned int pixSize, unsigned int val) - { return 0xFF000000 | src[2] << 16 | src[1] << 8 | src[0]; } + { VT_RGBA(val,src[2],src[1],src[0],0xFF); return val; } }; /// class for YV12 conversion @@ -215,15 +242,15 @@ protected: int red = (298 * c + 409 * e + 128) >> 8; if (red >= 0x100) red = 0xFF; else if (red < 0) red = 0; - int green = 298 * c - 100 * d - 208 * e; - if (green > 0x10000) green = 0xFF00; + int green = (298 * c - 100 * d - 208 * e) >> 8; + if (green >= 0x100) green = 0xFF; else if (green < 0) green = 0; - int blue = (298 * c + 516 * d + 128) << 8; - if (blue > 0x1000000) blue = 0xFF0000; + int blue = (298 * c + 516 * d + 128) >> 8; + if (blue >= 0x100) blue = 0xFF; else if (blue < 0) blue = 0; // return result - return 0xFF000000 | blue & 0xFF0000 | green & 0xFF00 - | red & 0xFF; + VT_RGBA(val, red, green, blue, 0xFF); + return val; } }; diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp index a0c6e1f6f74..19ad17ac643 100644 --- a/source/gameengine/VideoTexture/ImageBuff.cpp +++ b/source/gameengine/VideoTexture/ImageBuff.cpp @@ -32,7 +32,7 @@ http://www.gnu.org/copyleft/lesser.txt. // default filter -FilterBGR24 defFilter; +FilterRGB24 defFilter; // load image from buffer @@ -111,11 +111,11 @@ static PyMethodDef imageBuffMethods[] = // attributes structure static PyGetSetDef imageBuffGetSets[] = { // attributes from ImageBase class - {"image", (getter)Image_getImage, NULL, "image data", NULL}, - {"size", (getter)Image_getSize, NULL, "image size", NULL}, - {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL}, - {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL}, - {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL}, + {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, + {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, + {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, + {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp index 8532249f7d8..b07b362818c 100644 --- a/source/gameengine/VideoTexture/ImageMix.cpp +++ b/source/gameengine/VideoTexture/ImageMix.cpp @@ -150,11 +150,11 @@ static PyMethodDef imageMixMethods[] = // attributes structure static PyGetSetDef imageMixGetSets[] = { // attributes from ImageBase class - {"image", (getter)Image_getImage, NULL, "image data", NULL}, - {"size", (getter)Image_getSize, NULL, "image size", NULL}, - {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL}, - {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL}, - {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL}, + {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, + {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, + {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, + {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index fb284261d70..2f2d9debd48 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -207,13 +207,13 @@ static PyMethodDef imageRenderMethods[] = // attributes structure static PyGetSetDef imageRenderGetSets[] = { - {"background", (getter)getBackground, (setter)setBackground, "background color", NULL}, + {(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL}, // attributes from ImageBase class - {"image", (getter)Image_getImage, NULL, "image data", NULL}, - {"size", (getter)Image_getSize, NULL, "image size", NULL}, - {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL}, - {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL}, - {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL}, + {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, + {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, + {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, + {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index 4ed1cd9e801..deb66ffb6ba 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -135,7 +135,7 @@ void ImageViewport::calcImage (unsigned int texId) glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, GL_UNSIGNED_BYTE, m_viewportImage); // filter loaded data - FilterBGR24 filt; + FilterRGB24 filt; filterImage(filt, m_viewportImage, m_capSize); } } @@ -239,15 +239,15 @@ static PyMethodDef imageViewportMethods[] = // attributes structure static PyGetSetDef imageViewportGetSets[] = { - {"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, "use whole viewport to capture", NULL}, - {"position", (getter)ImageViewport_getPosition, (setter)ImageViewport_setPosition, "upper left corner of captured area", NULL}, - {"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, "size of viewport area being captured", NULL}, + {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to capture", NULL}, + {(char*)"position", (getter)ImageViewport_getPosition, (setter)ImageViewport_setPosition, (char*)"upper left corner of captured area", NULL}, + {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of viewport area being captured", NULL}, // attributes from ImageBase class - {"image", (getter)Image_getImage, NULL, "image data", NULL}, - {"size", (getter)Image_getSize, NULL, "image size", NULL}, - {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL}, - {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL}, - {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL}, + {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, + {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, + {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, + {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp index 0451d74c8ad..6d2676dce09 100644 --- a/source/gameengine/VideoTexture/PyTypeList.cpp +++ b/source/gameengine/VideoTexture/PyTypeList.cpp @@ -78,6 +78,6 @@ void PyTypeList::reg (PyObject * module) // increase ref count Py_INCREF((*it)->getType()); // add type to module - PyModule_AddObject(module, (*it)->getName(), (PyObject*)(*it)->getType()); + PyModule_AddObject(module, (char*)(*it)->getName(), (PyObject*)(*it)->getType()); } } diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index ceda39aeff4..88a26e3c088 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -54,9 +54,6 @@ http://www.gnu.org/copyleft/lesser.txt. { exp.report(); } -// are Blender materials used -bool blendMats = false; - // Blender GameObject type BlendType gameObjectType ("KX_GameObject"); @@ -198,15 +195,22 @@ int Texture_init (Texture *self, PyObject *args, PyObject *kwds) if (mat != NULL) { // is it blender material or polygon material - blendMats = (mat->GetFlag() & RAS_BLENDERMAT) != 0; - if (blendMats) + if (mat->GetFlag() & RAS_BLENDERGLSL) + { + self->m_imgTexture = static_cast(mat)->getImage(texID); + self->m_useMatTexture = false; + } else if (mat->GetFlag() & RAS_BLENDERMAT) + { // get blender material texture self->m_matTexture = static_cast(mat)->getTex(texID); + self->m_useMatTexture = true; + } else { // get texture pointer from polygon material MTFace * tface = static_cast(mat)->GetMTFace(); self->m_imgTexture = (Image*)tface->tpage; + self->m_useMatTexture = false; } } // check if texture is available, if not, initialization failed @@ -246,7 +250,7 @@ PyObject * Texture_close(Texture * self) { self->m_orgSaved = false; // restore original texture code - if (blendMats) + if (self->m_useMatTexture) self->m_matTexture->swapTexture(self->m_orgTex); else self->m_imgTexture->bindcode = self->m_orgTex; @@ -292,7 +296,7 @@ PyObject * Texture_refresh (Texture * self, PyObject * args) { self->m_orgSaved = true; // save original image code - if (blendMats) + if (self->m_useMatTexture) self->m_orgTex = self->m_matTexture->swapTexture(self->m_actTex); else { @@ -412,8 +416,8 @@ static PyMethodDef textureMethods[] = // class Texture attributes static PyGetSetDef textureGetSets[] = { - {"source", (getter)Texture_getSource, (setter)Texture_setSource, "source of texture", NULL}, - {"mipmap", (getter)Texture_getMipmap, (setter)Texture_setMipmap, "mipmap texture", NULL}, + {(char*)"source", (getter)Texture_getSource, (setter)Texture_setSource, (char*)"source of texture", NULL}, + {(char*)"mipmap", (getter)Texture_getMipmap, (setter)Texture_setMipmap, (char*)"mipmap texture", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h index 569e34da121..3c371e51537 100644 --- a/source/gameengine/VideoTexture/Texture.h +++ b/source/gameengine/VideoTexture/Texture.h @@ -39,9 +39,11 @@ struct Texture { PyObject_HEAD + // texture is using blender material + bool m_useMatTexture; + // video texture bind code unsigned int m_actTex; - // original texture bind code unsigned int m_orgTex; // original texture saved @@ -70,9 +72,6 @@ struct Texture // Texture type description extern PyTypeObject TextureType; -// usage of Blender materials -extern bool blendMats; - // load texture void loadTexture (unsigned int texId, unsigned int * texture, short * size, bool mipmap = false); diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 272d2695c4b..dfbd61daee8 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -20,6 +20,11 @@ http://www.gnu.org/copyleft/lesser.txt. ----------------------------------------------------------------------------- */ +// INT64_C fix for some linux machines (C99ism) +#define __STDC_CONSTANT_MACROS +#include + + #include "MEM_guardedalloc.h" #include "PIL_time.h" @@ -46,10 +51,10 @@ extern "C" void do_init_ffmpeg(); // constructor VideoFFmpeg::VideoFFmpeg (HRESULT * hRslt) : VideoBase(), m_codec(NULL), m_formatCtx(NULL), m_codecCtx(NULL), -m_frame(NULL), m_frameDeinterlaced(NULL), m_frameBGR(NULL), m_imgConvertCtx(NULL), +m_frame(NULL), m_frameDeinterlaced(NULL), m_frameRGB(NULL), m_imgConvertCtx(NULL), m_deinterlace(false), m_preseek(0), m_videoStream(-1), m_baseFrameRate(25.0), m_lastFrame(-1), m_curPosition(-1), m_startTime(0), -m_captWidth(0), m_captHeight(0), m_captRate(0.f) +m_captWidth(0), m_captHeight(0), m_captRate(0.f), m_isImage(false) { // set video format m_format = RGB24; @@ -72,49 +77,48 @@ bool VideoFFmpeg::release() if (m_codecCtx) { avcodec_close(m_codecCtx); + m_codecCtx = NULL; } if (m_formatCtx) { av_close_input_file(m_formatCtx); + m_formatCtx = NULL; } if (m_frame) { av_free(m_frame); + m_frame = NULL; } if (m_frameDeinterlaced) { MEM_freeN(m_frameDeinterlaced->data[0]); av_free(m_frameDeinterlaced); + m_frameDeinterlaced = NULL; } - if (m_frameBGR) + if (m_frameRGB) { - MEM_freeN(m_frameBGR->data[0]); - av_free(m_frameBGR); + MEM_freeN(m_frameRGB->data[0]); + av_free(m_frameRGB); + m_frameRGB = NULL; } if (m_imgConvertCtx) { sws_freeContext(m_imgConvertCtx); + m_imgConvertCtx = NULL; } - m_codec = NULL; - m_codecCtx = NULL; - m_formatCtx = NULL; - m_frame = NULL; - m_frame = NULL; - m_frameBGR = NULL; - m_imgConvertCtx = NULL; - - // object will be deleted after that + m_status = SourceStopped; return true; } // set initial parameters -void VideoFFmpeg::initParams (short width, short height, float rate) +void VideoFFmpeg::initParams (short width, short height, float rate, bool image) { m_captWidth = width; m_captHeight = height; m_captRate = rate; + m_isImage = image; } int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams) @@ -184,7 +188,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV m_videoStream = videoStream; m_frame = avcodec_alloc_frame(); m_frameDeinterlaced = avcodec_alloc_frame(); - m_frameBGR = avcodec_alloc_frame(); + m_frameRGB = avcodec_alloc_frame(); // allocate buffer if deinterlacing is required @@ -196,12 +200,12 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height); // allocate buffer to store final decoded frame - avpicture_fill((AVPicture*)m_frameBGR, + avpicture_fill((AVPicture*)m_frameRGB, (uint8_t*)MEM_callocN(avpicture_get_size( - PIX_FMT_BGR24, + PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height), - "ffmpeg bgr"), - PIX_FMT_BGR24, m_codecCtx->width, m_codecCtx->height); + "ffmpeg rgb"), + PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height); // allocate sws context m_imgConvertCtx = sws_getContext( m_codecCtx->width, @@ -209,7 +213,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height, - PIX_FMT_BGR24, + PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL); @@ -219,8 +223,8 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV av_free(m_frame); MEM_freeN(m_frameDeinterlaced->data[0]); av_free(m_frameDeinterlaced); - MEM_freeN(m_frameBGR->data[0]); - av_free(m_frameBGR); + MEM_freeN(m_frameRGB->data[0]); + av_free(m_frameRGB); return -1; } return 0; @@ -250,7 +254,7 @@ void VideoFFmpeg::openFile (char * filename) if ( #ifdef FFMPEG_PB_IS_POINTER - m_formatCtx->pb->is_streamed + m_formatCtx->pb && m_formatCtx->pb->is_streamed #else m_formatCtx->pb.is_streamed #endif @@ -261,6 +265,18 @@ void VideoFFmpeg::openFile (char * filename) // for streaming it is important to do non blocking read m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK; } + + if (m_isImage) + { + // the file is to be treated as an image, i.e. load the first frame only + m_isFile = false; + // in case of reload, the filename is taken from m_imageName, no need to change it + if (m_imageName.Ptr() != filename) + m_imageName = filename; + m_preseek = 0; + play(); + } + } @@ -343,7 +359,6 @@ void VideoFFmpeg::openCam (char * file, short camIdx) VideoBase::openCam(file, camIdx); } - // play video bool VideoFFmpeg::play (void) { @@ -445,6 +460,13 @@ void VideoFFmpeg::loadFrame (void) init(short(m_codecCtx->width), short(m_codecCtx->height)); // process image process((BYTE*)(frame->data[0])); + // in case it is an image, automatically stop reading it + if (m_isImage) + { + m_status = SourceStopped; + // close the file as we don't need it anymore + release(); + } } } } @@ -560,14 +582,14 @@ bool VideoFFmpeg::grabFrame(long position) input = m_frameDeinterlaced; } } - // convert to BGR24 + // convert to RGB24 sws_scale(m_imgConvertCtx, input->data, input->linesize, 0, m_codecCtx->height, - m_frameBGR->data, - m_frameBGR->linesize); + m_frameRGB->data, + m_frameRGB->linesize); av_free_packet(&packet); frameLoaded = true; break; @@ -687,18 +709,18 @@ static PyMethodDef videoMethods[] = // attributes structure static PyGetSetDef videoGetSets[] = { // methods from VideoBase class - {"status", (getter)Video_getStatus, NULL, "video status", NULL}, - {"range", (getter)Video_getRange, (setter)Video_setRange, "replay range", NULL}, - {"repeat", (getter)Video_getRepeat, (setter)Video_setRepeat, "repeat count, -1 for infinite repeat", NULL}, - {"framerate", (getter)Video_getFrameRate, (setter)Video_setFrameRate, "frame rate", NULL}, + {(char*)"status", (getter)Video_getStatus, NULL, (char*)"video status", NULL}, + {(char*)"range", (getter)Video_getRange, (setter)Video_setRange, (char*)"replay range", NULL}, + {(char*)"repeat", (getter)Video_getRepeat, (setter)Video_setRepeat, (char*)"repeat count, -1 for infinite repeat", NULL}, + {(char*)"framerate", (getter)Video_getFrameRate, (setter)Video_setFrameRate, (char*)"frame rate", NULL}, // attributes from ImageBase class - {"image", (getter)Image_getImage, NULL, "image data", NULL}, - {"size", (getter)Image_getSize, NULL, "image size", NULL}, - {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL}, - {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL}, - {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL}, - {"preseek", (getter)VideoFFmpeg_getPreseek, (setter)VideoFFmpeg_setPreseek, "nb of frames of preseek", NULL}, - {"deinterlace", (getter)VideoFFmpeg_getDeinterlace, (setter)VideoFFmpeg_setDeinterlace, "deinterlace image", NULL}, + {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, + {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, + {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, + {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, + {(char*)"preseek", (getter)VideoFFmpeg_getPreseek, (setter)VideoFFmpeg_setPreseek, (char*)"nb of frames of preseek", NULL}, + {(char*)"deinterlace", (getter)VideoFFmpeg_getDeinterlace, (setter)VideoFFmpeg_setDeinterlace, (char*)"deinterlace image", NULL}, {NULL} }; @@ -746,7 +768,123 @@ PyTypeObject VideoFFmpegType = Image_allocNew, /* tp_new */ }; +// object initialization +static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +{ + PyImage * self = reinterpret_cast(pySelf); + // parameters - video source + // file name or format type for capture (only for Linux: video4linux or dv1394) + char * file = NULL; + // get parameters + if (!PyArg_ParseTuple(args, "s", &file)) + return -1; + + try + { + // create video object + Video_init(self); + + getVideoFFmpeg(self)->initParams(0, 0, 1.0, true); + + // open video source + Video_open(getVideo(self), file, -1); + } + catch (Exception & exp) + { + exp.report(); + return -1; + } + // initialization succeded + return 0; +} + +PyObject * Image_reload (PyImage * self, PyObject *args) +{ + char * newname = NULL; + + if (self->m_image != NULL && PyArg_ParseTuple(args, "|s", &newname)) + { + VideoFFmpeg* video = getFFmpeg(self); + // check type of object + if (!newname) + newname = video->getImageName(); + if (!newname) { + // if not set, retport error + PyErr_SetString(PyExc_RuntimeError, "No image file name given"); + return NULL; + } + // make sure the previous file is cleared + video->release(); + // open the new file + video->openFile(newname); + } + Py_RETURN_NONE; +} + +// methods structure +static PyMethodDef imageMethods[] = +{ // methods from VideoBase class + {"refresh", (PyCFunction)Video_refresh, METH_NOARGS, "Refresh image, i.e. load it"}, + {"reload", (PyCFunction)Image_reload, METH_VARARGS, "Reload image, i.e. reopen it"}, + {NULL} +}; +// attributes structure +static PyGetSetDef imageGetSets[] = +{ // methods from VideoBase class + {(char*)"status", (getter)Video_getStatus, NULL, (char*)"video status", NULL}, + // attributes from ImageBase class + {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, + {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, + {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, + {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, + {NULL} +}; + +// python type declaration +PyTypeObject ImageFFmpegType = +{ + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "VideoTexture.ImageFFmpeg", /*tp_name*/ + sizeof(PyImage), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)Image_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "FFmpeg image source", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + imageMethods, /* tp_methods */ + 0, /* tp_members */ + imageGetSets, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ImageFFmpeg_init, /* tp_init */ + 0, /* tp_alloc */ + Image_allocNew, /* tp_new */ +}; #endif //WITH_FFMPEG diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index 4720bef1841..db2cb293d8b 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -65,8 +65,8 @@ public: virtual ~VideoFFmpeg (); /// set initial parameters - void initParams (short width, short height, float rate); - /// open video file + void initParams (short width, short height, float rate, bool image=false); + /// open video/image file virtual void openFile (char * file); /// open video capture device virtual void openCam (char * driver, short camIdx); @@ -88,6 +88,7 @@ public: void setPreseek(int preseek) { if (preseek >= 0) m_preseek = preseek; } bool getDeinterlace(void) { return m_deinterlace; } void setDeinterlace(bool deinterlace) { m_deinterlace = deinterlace; } + char *getImageName(void) { return (m_isImage) ? m_imageName.Ptr() : NULL; } protected: @@ -100,7 +101,7 @@ protected: // deinterlaced frame if codec requires it AVFrame *m_frameDeinterlaced; // decoded RGB24 frame if codec requires it - AVFrame *m_frameBGR; + AVFrame *m_frameRGB; // conversion from raw to RGB is done with sws_scale struct SwsContext *m_imgConvertCtx; // should the codec be deinterlaced? @@ -131,6 +132,12 @@ protected: /// frame rate of capture in frames per seconds float m_captRate; + /// is file an image? + bool m_isImage; + + /// keep last image name + STR_String m_imageName; + /// image calculation virtual void calcImage (unsigned int texId); @@ -150,7 +157,7 @@ protected: bool grabFrame(long frame); /// return the frame in RGB24 format, the image data is found in AVFrame.data[0] - AVFrame* getFrame(void) { return m_frameBGR; } + AVFrame* getFrame(void) { return m_frameRGB; } }; inline VideoFFmpeg * getFFmpeg (PyImage * self) diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index 629b589c0e6..b38882f8164 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -119,6 +119,7 @@ static PyMethodDef moduleMethods[] = #if WITH_FFMPEG extern PyTypeObject VideoFFmpegType; +extern PyTypeObject ImageFFmpegType; #endif extern PyTypeObject FilterBlueScreenType; extern PyTypeObject FilterGrayType; @@ -126,6 +127,7 @@ extern PyTypeObject FilterColorType; extern PyTypeObject FilterLevelType; extern PyTypeObject FilterNormalType; extern PyTypeObject FilterRGB24Type; +extern PyTypeObject FilterRGBA32Type; extern PyTypeObject FilterBGR24Type; extern PyTypeObject ImageBuffType; extern PyTypeObject ImageMixType; @@ -138,6 +140,7 @@ static void registerAllTypes(void) { #if WITH_FFMPEG pyImageTypes.add(&VideoFFmpegType, "VideoFFmpeg"); + pyImageTypes.add(&ImageFFmpegType, "ImageFFmpeg"); #endif pyImageTypes.add(&ImageBuffType, "ImageBuff"); pyImageTypes.add(&ImageMixType, "ImageMix"); @@ -150,6 +153,7 @@ static void registerAllTypes(void) pyFilterTypes.add(&FilterLevelType, "FilterLevel"); pyFilterTypes.add(&FilterNormalType, "FilterNormal"); pyFilterTypes.add(&FilterRGB24Type, "FilterRGB24"); + pyFilterTypes.add(&FilterRGBA32Type, "FilterRGBA32"); pyFilterTypes.add(&FilterBGR24Type, "FilterBGR24"); } @@ -180,7 +184,7 @@ PyObject* initVideoTexture(void) pyFilterTypes.reg(m); Py_INCREF(&TextureType); - PyModule_AddObject(m, "Texture", (PyObject*)&TextureType); + PyModule_AddObject(m, (char*)"Texture", (PyObject*)&TextureType); // init last error description Exception::m_lastError[0] = '\0'; diff --git a/tools/Blender.py b/tools/Blender.py index af2a20eb95a..857d5c4d780 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -416,14 +416,10 @@ class BlenderEnvironment(SConsEnvironment): lenv.Append(CPPDEFINES=['GAMEBLENDER=1']) if lenv['WITH_BF_BULLET']: lenv.Append(CPPDEFINES=['WITH_BULLET=1']) - # debug or not - # CXXFLAGS defaults to CCFLAGS, therefore - # we Replace() rather than Append() to CXXFLAGS the first time - #lenv.Replace(CXXFLAGS = lenv['CCFLAGS']) if lenv['BF_DEBUG'] or (libname in quickdebug): - lenv.Append(CFLAGS = Split(lenv['BF_DEBUG_CFLAGS'])) - lenv.Append(CCFLAGS = Split(lenv['BF_DEBUG_CCFLAGS'])) - lenv.Append(CXXFLAGS = Split(lenv['BF_DEBUG_CXXFLAGS'])) + lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS']) + lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS']) + lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS']) else: lenv.Append(CFLAGS = lenv['REL_CFLAGS']) lenv.Append(CCFLAGS = lenv['REL_CCFLAGS']) From e76e271e293859c9b35f311dd0d50d4cf1074a25 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 6 Nov 2008 03:31:25 +0000 Subject: [PATCH 040/252] Sketch Retargetting: template selection from dropdown (listing all other armatures) instead of silly object name input. --- source/blender/blenloader/intern/readfile.c | 5 +- source/blender/include/BIF_sketch.h | 6 + source/blender/src/drawview.c | 14 ++- source/blender/src/editarmature_sketch.c | 117 ++++++++++++++++++++ source/blender/src/usiblender.c | 1 + 5 files changed, 140 insertions(+), 3 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 154f6d7264a..5a12342bb1b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3459,6 +3459,9 @@ static void lib_link_scene(FileData *fd, Main *main) sce->toolsettings->imapaint.brush= newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.brush); + + sce->toolsettings->skgen_template = newlibadr_us(fd, sce->id.lib, sce->toolsettings->skgen_template); + /* Sculptdata textures */ for(a=0; asculptdata.mtex[a]; @@ -3549,8 +3552,6 @@ static void direct_link_scene(FileData *fd, Scene *sce) sce->radio= newdataadr(fd, sce->radio); sce->toolsettings= newdataadr(fd, sce->toolsettings); - - sce->toolsettings->skgen_template = newdataadr(fd, sce->toolsettings->skgen_template); sce->sculptdata.session= NULL; /* SculptData textures */ diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h index 530f0001b15..6295ce41788 100644 --- a/source/blender/include/BIF_sketch.h +++ b/source/blender/include/BIF_sketch.h @@ -32,4 +32,10 @@ int BIF_validSketchMode(); int BIF_fullSketchMode(); /* full sketch turned on (not Quick) */ void BIF_cancelStrokeSketch(); +void BIF_makeListTemplates(); +char *BIF_listTemplates(); +int BIF_currentTemplate(); +void BIF_freeTemplates(); +void BIF_setTemplate(int); + #endif /* BIF_SKETCH_H */ diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 59a96bed319..50fa80ca68f 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2283,8 +2283,14 @@ static void convert_sketch_armature(void *arg1, void *arg2) BIF_convertSketch(); } +static void assign_template_sketch_armature(void *arg1, void *arg2) +{ + int index = *(int*)arg1; + BIF_setTemplate(index); +} static void view3d_panel_bonesketch_spaces(short cntrl) { + static int template_index; uiBlock *block; uiBut *but; int yco = 70, height = 140; @@ -2342,7 +2348,13 @@ static void view3d_panel_bonesketch_spaces(short cntrl) yco -= 10; uiBlockBeginAlign(block); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_DIFF, "OB:", 10, yco, 150, 19, &G.scene->toolsettings->skgen_template, "Template Object"); + BIF_makeListTemplates(); + template_index = BIF_currentTemplate(); + + but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(), 10,yco,150,19, &template_index, 0, 0, 0, 0, "Template"); + uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL); + + //uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_DIFF, "OB:", 10, yco, 150, 19, &G.scene->toolsettings->skgen_template, "Template Object"); yco -= 20; uiDefButF(block, NUM, B_DIFF, "Ang:", 10, yco, 50,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 5da96cd61d5..7becb6e03bd 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -35,6 +35,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_graph.h" +#include "BLI_ghash.h" #include "BKE_utildefines.h" #include "BKE_global.h" @@ -135,6 +136,122 @@ int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], floa int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); +/******************** TEMPLATES UTILS *************************/ + +char *TEMPLATES_MENU = NULL; +int TEMPLATES_CURRENT = 0; +GHash *TEMPLATES_HASH = NULL; + +void BIF_makeListTemplates() +{ + Base *base; + int index = 0; + + if (TEMPLATES_HASH != NULL) + { + BLI_ghash_free(TEMPLATES_HASH, NULL, NULL); + } + + TEMPLATES_HASH = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + TEMPLATES_CURRENT = 0; + + for ( base = FIRSTBASE; base; base = base->next ) + { + Object *ob = base->object; + + if (ob != G.obedit && ob->type == OB_ARMATURE) + { + index++; + BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob); + + if (ob == G.scene->toolsettings->skgen_template) + { + TEMPLATES_CURRENT = index; + } + } + } +} + +char *BIF_listTemplates() +{ + GHashIterator ghi; + char menu_header[] = "Template%t|None%x0|"; + char *p; + + TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu"); + + p = TEMPLATES_MENU; + + p += sprintf(TEMPLATES_MENU, "%s", menu_header); + + BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); + + while (!BLI_ghashIterator_isDone(&ghi)) + { + Object *ob = BLI_ghashIterator_getValue(&ghi); + int key = (int)BLI_ghashIterator_getKey(&ghi); + + p += sprintf(p, "|%s%%x%i", ob->id.name+2, key); + + BLI_ghashIterator_step(&ghi); + } + + return TEMPLATES_MENU; +} + +int BIF_currentTemplate() +{ + if (TEMPLATES_CURRENT == 0 && G.scene->toolsettings->skgen_template != NULL) + { + GHashIterator ghi; + int index = 0; + BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); + + while (!BLI_ghashIterator_isDone(&ghi)) + { + Object *ob = BLI_ghashIterator_getValue(&ghi); + int key = (int)BLI_ghashIterator_getKey(&ghi); + + index++; + + if (ob == G.scene->toolsettings->skgen_template) + { + TEMPLATES_CURRENT = index; + break; + } + + BLI_ghashIterator_step(&ghi); + } + } + + return TEMPLATES_CURRENT; +} + +void BIF_freeTemplates() +{ + if (TEMPLATES_MENU != NULL) + { + MEM_freeN(TEMPLATES_MENU); + } + + if (TEMPLATES_HASH != NULL) + { + BLI_ghash_free(TEMPLATES_HASH, NULL, NULL); + } +} + +void BIF_setTemplate(int index) +{ + if (index > 0) + { + G.scene->toolsettings->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index)); + } + else + { + G.scene->toolsettings->skgen_template = NULL; + } +} + /******************** PEELING *********************************/ typedef struct SK_DepthPeel diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 16c26336b89..7ebdc3a11cd 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -1103,6 +1103,7 @@ void exit_usiblender(void) BIF_GlobalReebFree(); BIF_freeRetarget(); + BIF_freeTemplates(); tf= G.ttfdata.first; while(tf) From 4114ce74078ac86d15046715ed70c310dafdde77 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 7 Nov 2008 19:44:02 +0000 Subject: [PATCH 041/252] Correct stroke normal alignment for retargetting (transform into edit armature local space) --- source/blender/include/reeb.h | 4 ++-- source/blender/src/editarmature_retarget.c | 13 ++++++------- source/blender/src/editarmature_sketch.c | 20 +++++++++++++------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index 6496eb34836..927eded62d4 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -63,7 +63,7 @@ typedef struct EmbedBucket { float val; int nv; float p[3]; - float *no; /* if present, normal of the bucket */ + float no[3]; /* if non-null, normal of the bucket */ } EmbedBucket; typedef struct ReebNode { @@ -81,7 +81,7 @@ typedef struct ReebNode { float symmetry_axis[3]; /*********************************/ - float *no; + float no[3]; int index; float weight; diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index fb9ba740ec3..562ba74b70b 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -162,12 +162,12 @@ void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3]) VECCOPY(up_axis, mat[2]); } -float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float quat[4], float qroll[4], float aligned_axis[3]) +float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], float qroll[4], float aligned_axis[3]) { float nor[3], new_up_axis[3], x_axis[3], z_axis[3]; VECCOPY(new_up_axis, old_up_axis); - QuatMulVecf(quat, new_up_axis); + QuatMulVecf(qrot, new_up_axis); VecSubf(nor, bone->tail, bone->head); @@ -207,6 +207,8 @@ float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float quat[4]) VECCOPY(new_up_axis, old_up_axis); QuatMulVecf(quat, new_up_axis); + Normalize(new_up_axis); + return rollBoneToVector(bone, new_up_axis); } @@ -820,7 +822,6 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* if owner is a control bone, link with it */ if (link && link->link) { - printf("%s -constraint- %s\n", ctrl->bone->name, link->bone->name); RIG_parentControl(ctrl, link->bone); found = 1; break; @@ -839,7 +840,6 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* check if parent is already linked */ if (ctrl_parent && ctrl_parent->link) { - printf("%s -parent- %s\n", ctrl->bone->name, ctrl_parent->bone->name); RIG_parentControl(ctrl, ctrl_parent->bone); change = 1; } @@ -851,7 +851,6 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* if a child is linked, link to that one */ if (ctrl_child->link && ctrl_child->bone->parent == ctrl->bone) { - printf("%s -child- %s\n", ctrl->bone->name, ctrl_child->bone->name); RIG_parentControl(ctrl, ctrl_child->bone); change = 1; break; @@ -1656,7 +1655,7 @@ static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], f } -static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float *up_axis) +static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3]) { EditBone *bone; RigControl *ctrl; @@ -1679,7 +1678,7 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v VECCOPY(bone->head, vec0); VECCOPY(bone->tail, vec1); - if (up_axis != NULL) + if (!VecIsNull(up_axis)) { float qroll[4]; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 7becb6e03bd..99c274c6628 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -472,7 +472,7 @@ int peelObjects(ListBase *depth_peels, short mval[2]) } /*********************** CONVERSION ***************************/ -ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4]) +ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3]) { ReebNode *node; @@ -482,20 +482,21 @@ ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4]) if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_ROLL) { - node->no = pt->no; + VECCOPY(node->no, pt->no); + Mat3MulVecfl(tmat, node->no); } return node; } -ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4]) +ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3]) { ReebArc *arc; int i; arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); - arc->head = sk_pointToNode(stk->points, imat); - arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat); + arc->head = sk_pointToNode(stk->points, imat, tmat); + arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat); arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */ arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets"); @@ -507,7 +508,8 @@ ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4]) if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_ROLL) { - arc->buckets[i].no = stk->points[i + 1].no; + VECCOPY(arc->buckets[i].no, stk->points[i + 1].no); + Mat3MulVecfl(tmat, arc->buckets[i].no); } } @@ -517,11 +519,15 @@ ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4]) void sk_retargetStroke(SK_Stroke *stk) { float imat[4][4]; + float tmat[3][3]; ReebArc *arc; Mat4Invert(imat, G.obedit->obmat); - arc = sk_strokeToArc(stk, imat); + Mat3CpyMat4(tmat, G.obedit->obmat); + Mat3Transp(tmat); + + arc = sk_strokeToArc(stk, imat, tmat); BIF_retargetArc(arc); From f0a23dce9a133c3e37e0aa59c1a8ae178ef0dad6 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sat, 8 Nov 2008 22:05:11 +0000 Subject: [PATCH 042/252] Generalized unique_editbone_name to be useable if a name change after the bone has been added to the list (this could probably simplify some code in editarmature, I haven't done that yet). First pass for retargetting template's renaming magic. For now, in new retargetted bone's name: %S (side) and %N (number) will be replaced by user defined strings. Will need to experiment on how useful that is and how it could be better. --- source/blender/include/BIF_editarmature.h | 2 +- source/blender/include/BIF_retarget.h | 13 +++- source/blender/makesdna/DNA_scene_types.h | 2 + source/blender/python/api2_2x/Armature.c | 2 +- source/blender/python/api2_2x/Bone.c | 2 +- source/blender/src/drawview.c | 3 + source/blender/src/editarmature.c | 21 ++--- source/blender/src/editarmature_retarget.c | 90 ++++++++++++++++++---- source/blender/src/gpencil.c | 2 +- 9 files changed, 104 insertions(+), 33 deletions(-) diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 88e6630078f..6acb998e1da 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -133,7 +133,7 @@ void selectconnected_posearmature(void); void armature_select_hierarchy(short direction, short add_to_sel); void setflag_armature(short mode); -void unique_editbone_name (struct ListBase *ebones, char *name); +void unique_editbone_name (struct ListBase *ebones, char *name, EditBone *bone); /* if bone is already in list, pass it as param to ignore it */ void auto_align_armature(short mode); void switch_direction_armature(void); diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h index 867c90460ba..7d1b3e8bc51 100644 --- a/source/blender/include/BIF_retarget.h +++ b/source/blender/include/BIF_retarget.h @@ -113,16 +113,21 @@ typedef struct RigEdge { } RigEdge; /* Control flags */ -#define RIG_CTRL_DONE 1 -#define RIG_CTRL_PARENT_DEFORM 2 -#define RIG_CTRL_FIT_ROOT 4 -#define RIG_CTRL_FIT_BONE 8 +#define RIG_CTRL_HEAD_DONE 1 +#define RIG_CTRL_TAIL_DONE 2 +#define RIG_CTRL_PARENT_DEFORM 4 +#define RIG_CTRL_FIT_ROOT 8 +#define RIG_CTRL_FIT_BONE 16 + +#define RIG_CTRL_DONE (RIG_CTRL_HEAD_DONE|RIG_CTRL_TAIL_DONE) + typedef struct RigControl { struct RigControl *next, *prev; float head[3], tail[3]; EditBone *bone; EditBone *link; + EditBone *link_tail; float up_axis[3]; float offset[3]; int flag; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b92799cdf2a..27696e49615 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -448,6 +448,8 @@ typedef struct ToolSettings { char bone_sketching_convert; char skgen_subdivision_number; char skgen_retarget_options; + char skgen_side_string[8]; + char skgen_num_string[8]; /* Alt+RMB option */ char edge_mode; diff --git a/source/blender/python/api2_2x/Armature.c b/source/blender/python/api2_2x/Armature.c index 99a4398ec89..2ef0c2b4afe 100644 --- a/source/blender/python/api2_2x/Armature.c +++ b/source/blender/python/api2_2x/Armature.c @@ -280,7 +280,7 @@ static int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value //create a new editbone editbone = MEM_callocN(sizeof(EditBone), "eBone"); BLI_strncpy(editbone->name, key_str, 32); - unique_editbone_name(NULL, editbone->name); + unique_editbone_name(NULL, editbone->name, NULL); editbone->dist = ((BPy_EditBone*)value)->dist; editbone->ease1 = ((BPy_EditBone*)value)->ease1; editbone->ease2 = ((BPy_EditBone*)value)->ease2; diff --git a/source/blender/python/api2_2x/Bone.c b/source/blender/python/api2_2x/Bone.c index 948eb007803..cacb3584344 100644 --- a/source/blender/python/api2_2x/Bone.c +++ b/source/blender/python/api2_2x/Bone.c @@ -832,7 +832,7 @@ static PyObject *EditBone_new(PyTypeObject *type, PyObject *args, PyObject *kwds //otherwise this will act as a py_object py_editBone->editbone = NULL; - unique_editbone_name(NULL, name); + unique_editbone_name(NULL, name, NULL); BLI_strncpy(py_editBone->name, name, 32); py_editBone->parent = NULL; py_editBone->weight= 1.0f; diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 50fa80ca68f..45cf79ca390 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2361,6 +2361,9 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiDefButF(block, NUM, B_DIFF, "Len:", 60, yco, 50,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); uiDefButF(block, NUM, B_DIFF, "Dist:", 110,yco, 50,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); yco -= 20; + + uiDefBut(block, TEX,0,"S:", 10, yco, 75, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace %S with"); + uiDefBut(block, TEX,0,"N:", 85, yco, 75, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace %N with"); uiBlockEndAlign(block); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 38d8262ea4d..4ba516259e2 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -699,7 +699,7 @@ int join_armature(void) curbone= editbone_name_exists(&eblist, pchan->name); /* Get new name */ - unique_editbone_name(&ebbase, curbone->name); + unique_editbone_name(&ebbase, curbone->name, NULL); /* Transform the bone */ { @@ -1999,7 +1999,7 @@ EditBone *addEditBone(char *name, ListBase *ebones, bArmature *arm) EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone"); BLI_strncpy(bone->name, name, 32); - unique_editbone_name(ebones, bone->name); + unique_editbone_name(ebones, bone->name, NULL); BLI_addtail(ebones, bone); @@ -2298,7 +2298,7 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, ListBase *editbones, Objec curBone->temp = eBone; eBone->temp = curBone; - unique_editbone_name(editbones, eBone->name); + unique_editbone_name(editbones, eBone->name, NULL); BLI_addtail(editbones, eBone); /* Lets duplicate the list of constraints that the @@ -2388,7 +2388,7 @@ void adduplicate_armature(void) curBone->temp = eBone; eBone->temp = curBone; - unique_editbone_name(&G.edbo, eBone->name); + unique_editbone_name(&G.edbo, eBone->name, NULL); BLI_addtail(&G.edbo, eBone); if (!firstDup) firstDup=eBone; @@ -3152,13 +3152,16 @@ static EditBone *editbone_name_exists (ListBase *ebones, char *name) } /* note: there's a unique_bone_name() too! */ -void unique_editbone_name (ListBase *ebones, char *name) +void unique_editbone_name (ListBase *ebones, char *name, EditBone *bone) { + EditBone *dupli; char tempname[64]; int number; char *dot; - if (editbone_name_exists(ebones, name)) { + dupli = editbone_name_exists(ebones, name); + + if (dupli && bone != dupli) { /* Strip off the suffix, if it's a number */ number= strlen(name); if (number && isdigit(name[number-1])) { @@ -3279,7 +3282,7 @@ void extrude_armature(int forked) else strcat(newbone->name, "_R"); } } - unique_editbone_name(&G.edbo, newbone->name); + unique_editbone_name(&G.edbo, newbone->name, NULL); /* Add the new bone to the list */ BLI_addtail(&G.edbo, newbone); @@ -3366,7 +3369,7 @@ void subdivide_armature(int numcuts) newbone->flag |= BONE_CONNECTED; - unique_editbone_name (&G.edbo, newbone->name); + unique_editbone_name (&G.edbo, newbone->name, NULL); /* correct parent bones */ for (tbone = G.edbo.first; tbone; tbone=tbone->next) { @@ -4400,7 +4403,7 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep) eBone= editbone_name_exists(&G.edbo, oldname); if (eBone) { - unique_editbone_name(&G.edbo, newname); + unique_editbone_name(&G.edbo, newname, NULL); BLI_strncpy(eBone->name, newname, MAXBONENAME); } else return; diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 562ba74b70b..7a72cc93f6c 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -400,6 +400,44 @@ static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone) } /************************************** CLONING TEMPLATES **********************************************/ +static void renameTemplateBone(EditBone *bone, char *template_name, ListBase *editbones) +{ + char *side_string = G.scene->toolsettings->skgen_side_string; + char *num_string = G.scene->toolsettings->skgen_num_string; + int i, j; + + for (i = 0, j = 0; template_name[i] != '\0' && i < 31 && j < 31; i++) + { + if (template_name[i] == '%') + { + if (template_name[i+1] == 'S') + { + j += sprintf(bone->name + j, side_string); + i++; + } + else if (template_name[i+1] == 'N') + { + j += sprintf(bone->name + j, num_string); + i++; + } + else + { + bone->name[j] = template_name[i]; + j++; + } + } + else + { + bone->name[j] = template_name[i]; + j++; + } + } + + bone->name[j] = '\0'; + + unique_editbone_name(editbones, bone->name, bone); +} + static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash) { RigControl *ctrl; @@ -414,6 +452,7 @@ static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ ctrl->flag = src_ctrl->flag; ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, rg->editbones, src_rg->ob, rg->ob); + renameTemplateBone(ctrl->bone, src_ctrl->bone->name, rg->editbones); ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone); @@ -455,6 +494,7 @@ static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash * if (src_edge->bone != NULL) { edge->bone = duplicateEditBoneObjects(src_edge->bone, rg->editbones, src_rg->ob, rg->ob); + renameTemplateBone(edge->bone, src_edge->bone->name, rg->editbones); edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone); } @@ -1456,7 +1496,7 @@ static EditBone *add_editbonetolist(char *name, ListBase *list) EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone"); BLI_strncpy(bone->name, name, 32); - unique_editbone_name(list, bone->name); + unique_editbone_name(list, bone->name, NULL); BLI_addtail(list, bone); @@ -1624,35 +1664,53 @@ void generateMissingArcs(RigGraph *rigg) /************************************ RETARGETTING *****************************************************/ +static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize); + + +static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float qrot[4], float resize) +{ + if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE) + { + RigControl *ctrl_child; + + ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, qrot); + + /* Cascade to connected control bones */ + for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next) + { + if (ctrl_child->link == ctrl->bone) + { + repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, qrot, resize); + } + } + } +} + static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize) { - RigControl *ctrl_child; float parent_offset[3], tail_offset[3]; - VecSubf(tail_offset, ctrl->tail, ctrl->head); - VecMulf(tail_offset, resize); VECCOPY(parent_offset, ctrl->offset); VecMulf(parent_offset, resize); - QuatMulVecf(qrot, parent_offset); - QuatMulVecf(qrot, tail_offset); VecAddf(ctrl->bone->head, head, parent_offset); - VecAddf(ctrl->bone->tail, ctrl->bone->head, tail_offset); - ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, qrot); - - ctrl->flag |= RIG_CTRL_DONE; - /* Cascade to connected control bones */ - for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next) + ctrl->flag |= RIG_CTRL_HEAD_DONE; + + if (ctrl->link_tail == NULL) { - if (ctrl_child->link == ctrl->bone) - { - repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, qrot, resize); - } + VecSubf(tail_offset, ctrl->tail, ctrl->head); + VecMulf(tail_offset, resize); + QuatMulVecf(qrot, tail_offset); + + VecAddf(ctrl->bone->tail, ctrl->bone->head, tail_offset); + + ctrl->flag |= RIG_CTRL_TAIL_DONE; } + finalizeControl(rigg, ctrl, qrot, resize); } static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3]) diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index 497443edffd..8d64e17bb8a 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -933,7 +933,7 @@ static void gp_stroke_to_bonechain (bGPDlayer *gpl, bGPDstroke *gps, bArmature * /* add new bone - note: sync with editarmature.c::add_editbone() */ { BLI_strncpy(ebo->name, "Stroke", 32); - unique_editbone_name(bones, ebo->name); + unique_editbone_name(bones, ebo->name, NULL); BLI_addtail(bones, ebo); From 5443d2d86b153160201d1ef5c7c2d09bfc2f956e Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 10 Nov 2008 19:43:11 +0000 Subject: [PATCH 043/252] Dual Links for control bones: Control bones that start and end on specific joints will do the same after retarget. Template Renaming: Fix renaming to handle contraints properly Template Renaming with Action constraints video available online: http://vimeo.com/2206779 and http://blenderartists.org/~theeth/bf/etch-a-ton/retarget_fingers_action.ogv --- source/blender/include/BIF_editarmature.h | 4 +- source/blender/include/BIF_retarget.h | 8 ++ source/blender/src/editarmature.c | 11 +- source/blender/src/editarmature_retarget.c | 131 ++++++++++++++++++--- 4 files changed, 131 insertions(+), 23 deletions(-) diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 6acb998e1da..1fb2343ff9d 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -72,13 +72,13 @@ EditBone *addEditBone(char *name, struct ListBase *ebones, struct bArmature *arm /* duplicate method */ void preEditBoneDuplicate(struct ListBase *editbones); -EditBone *duplicateEditBone(EditBone *curBone, struct ListBase *editbones, struct Object *ob); +EditBone *duplicateEditBone(EditBone *curBone, char *name, struct ListBase *editbones, struct Object *ob); void updateDuplicateSubtarget(EditBone *dupBone, struct ListBase *editbones, struct Object *ob); /* duplicate method (cross objects */ /* editbones is the target list */ -EditBone *duplicateEditBoneObjects(EditBone *curBone, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob); +EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob); /* editbones is the source list */ void updateDuplicateSubtargetObjects(EditBone *dupBone, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob); diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h index 7d1b3e8bc51..60e180f214e 100644 --- a/source/blender/include/BIF_retarget.h +++ b/source/blender/include/BIF_retarget.h @@ -121,6 +121,12 @@ typedef struct RigEdge { #define RIG_CTRL_DONE (RIG_CTRL_HEAD_DONE|RIG_CTRL_TAIL_DONE) +/* Control tail flags */ +typedef enum { + TL_NONE = 0, + TL_TAIL, + TL_HEAD +} LinkTailMode; typedef struct RigControl { struct RigControl *next, *prev; @@ -130,7 +136,9 @@ typedef struct RigControl { EditBone *link_tail; float up_axis[3]; float offset[3]; + float qrot[4]; /* for dual linked bones, store the rotation of the linked bone for the finalization */ int flag; + LinkTailMode tail_mode; } RigControl; void BIF_retargetArc(ReebArc *earc); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 4ba516259e2..9559059e44c 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -2288,7 +2288,7 @@ void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob } -EditBone *duplicateEditBoneObjects(EditBone *curBone, ListBase *editbones, Object *src_ob, Object *dst_ob) +EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *editbones, Object *src_ob, Object *dst_ob) { EditBone *eBone = MEM_callocN(sizeof(EditBone), "addup_editbone"); @@ -2297,6 +2297,11 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, ListBase *editbones, Objec curBone->temp = eBone; eBone->temp = curBone; + + if (name != NULL) + { + BLI_strncpy(eBone->name, name, 32); + } unique_editbone_name(editbones, eBone->name, NULL); BLI_addtail(editbones, eBone); @@ -2345,9 +2350,9 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, ListBase *editbones, Objec return eBone; } -EditBone *duplicateEditBone(EditBone *curBone, ListBase *editbones, Object *ob) +EditBone *duplicateEditBone(EditBone *curBone, char *name, ListBase *editbones, Object *ob) { - return duplicateEditBoneObjects(curBone, editbones, ob, ob); + return duplicateEditBoneObjects(curBone, name, editbones, ob, ob); } void adduplicate_armature(void) diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 7a72cc93f6c..fdc409dd85b 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -400,7 +400,7 @@ static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone) } /************************************** CLONING TEMPLATES **********************************************/ -static void renameTemplateBone(EditBone *bone, char *template_name, ListBase *editbones) +static void renameTemplateBone(char *name, char *template_name, ListBase *editbones) { char *side_string = G.scene->toolsettings->skgen_side_string; char *num_string = G.scene->toolsettings->skgen_num_string; @@ -412,35 +412,36 @@ static void renameTemplateBone(EditBone *bone, char *template_name, ListBase *ed { if (template_name[i+1] == 'S') { - j += sprintf(bone->name + j, side_string); + j += sprintf(name + j, side_string); i++; } else if (template_name[i+1] == 'N') { - j += sprintf(bone->name + j, num_string); + j += sprintf(name + j, num_string); i++; } else { - bone->name[j] = template_name[i]; + name[j] = template_name[i]; j++; } } else { - bone->name[j] = template_name[i]; + name[j] = template_name[i]; j++; } } - bone->name[j] = '\0'; + name[j] = '\0'; - unique_editbone_name(editbones, bone->name, bone); + unique_editbone_name(editbones, name, NULL); } static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash) { RigControl *ctrl; + char name[32]; ctrl = newRigControl(rg); @@ -449,14 +450,16 @@ static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ VECCOPY(ctrl->up_axis, src_ctrl->up_axis); VECCOPY(ctrl->offset, src_ctrl->offset); + ctrl->tail_mode = src_ctrl->tail_mode; ctrl->flag = src_ctrl->flag; - ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, rg->editbones, src_rg->ob, rg->ob); - renameTemplateBone(ctrl->bone, src_ctrl->bone->name, rg->editbones); + renameTemplateBone(name, src_ctrl->bone->name, rg->editbones); + ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, name, rg->editbones, src_rg->ob, rg->ob); ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone); ctrl->link = src_ctrl->link; + ctrl->link_tail = src_ctrl->link_tail; return ctrl; } @@ -493,8 +496,9 @@ static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash * if (src_edge->bone != NULL) { - edge->bone = duplicateEditBoneObjects(src_edge->bone, rg->editbones, src_rg->ob, rg->ob); - renameTemplateBone(edge->bone, src_edge->bone->name, rg->editbones); + char name[32]; + renameTemplateBone(name, src_edge->bone->name, rg->editbones); + edge->bone = duplicateEditBoneObjects(src_edge->bone, name, rg->editbones, src_rg->ob, rg->ob); edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone); } @@ -581,6 +585,7 @@ static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob) } ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link); + ctrl->link_tail = BLI_ghash_lookup(ptr_hash, ctrl->link_tail); } BLI_ghash_free(ptr_hash, NULL, NULL); @@ -613,6 +618,7 @@ static void RIG_addControlBone(RigGraph *rg, EditBone *bone) VECCOPY(ctrl->head, bone->head); VECCOPY(ctrl->tail, bone->tail); getEditBoneRollUpAxis(bone, bone->roll, ctrl->up_axis); + ctrl->tail_mode = TL_NONE; BLI_ghash_insert(rg->controls_map, bone->name, ctrl); } @@ -900,8 +906,54 @@ static void RIG_reconnectControlBones(RigGraph *rg) } } } - } + + /* third pass, link control tails */ + for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) + { + /* fit bone already means full match, so skip those */ + if ((ctrl->flag & RIG_CTRL_FIT_BONE) == 0) + { + GHashIterator ghi; + + /* look on deform bones first */ + BLI_ghashIterator_init(&ghi, rg->bones_map); + + for( ; !BLI_ghashIterator_isDone(&ghi); BLI_ghashIterator_step(&ghi)) + { + EditBone *bone = (EditBone*)BLI_ghashIterator_getValue(&ghi); + + /* don't link with parent */ + if (bone->parent != ctrl->bone) + { + if (VecLenf(ctrl->bone->tail, bone->head) < 0.01) + { + printf("%s -> %s: TL_HEAD\n", ctrl->bone->name, bone->name); + ctrl->tail_mode = TL_HEAD; + ctrl->link_tail = bone; + break; + } + else if (VecLenf(ctrl->bone->tail, bone->tail) < 0.01) + { + printf("%s -> %s: TL_TAIL\n", ctrl->bone->name, bone->name); + ctrl->tail_mode = TL_TAIL; + ctrl->link_tail = bone; + break; + } + } + } + + /* if we haven't found one yet, look in control bones */ + if (ctrl->tail_mode == TL_NONE) + { + } + } + else + { + printf("%s FIT\n", ctrl->bone->name); + } + } + } /*******************************************************************************************************/ @@ -1666,31 +1718,68 @@ void generateMissingArcs(RigGraph *rigg) static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize); +static void repositionTailControl(RigGraph *rigg, RigControl *ctrl); -static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float qrot[4], float resize) +static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize) { if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE) { RigControl *ctrl_child; - ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, qrot); + /* if there was a tail link: apply link, recalc resize factor and qrot */ + if (ctrl->tail_mode != TL_NONE) + { + float *tail_vec = NULL; + float v1[3], v2[3], qtail[4]; + + if (ctrl->tail_mode == TL_TAIL) + { + tail_vec = ctrl->link_tail->tail; + } + else if (ctrl->tail_mode == TL_HEAD) + { + tail_vec = ctrl->link_tail->head; + } + + VecSubf(v1, ctrl->bone->tail, ctrl->bone->head); + VecSubf(v2, tail_vec, ctrl->bone->head); + + VECCOPY(ctrl->bone->tail, tail_vec); + + RotationBetweenVectorsToQuat(qtail, v1, v2); + QuatMul(ctrl->qrot, qtail, ctrl->qrot); + + resize = VecLength(v2) / VecLenf(ctrl->head, ctrl->tail); + } + + ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, ctrl->qrot); /* Cascade to connected control bones */ for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next) { if (ctrl_child->link == ctrl->bone) { - repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, qrot, resize); + repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, ctrl->qrot, resize); + } + if (ctrl_child->link_tail == ctrl->bone) + { + repositionTailControl(rigg, ctrl_child); } } } } +static void repositionTailControl(RigGraph *rigg, RigControl *ctrl) +{ + ctrl->flag |= RIG_CTRL_TAIL_DONE; + + finalizeControl(rigg, ctrl, 1); /* resize will be recalculated anyway so we don't need it */ +} + static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize) { float parent_offset[3], tail_offset[3]; - VECCOPY(parent_offset, ctrl->offset); VecMulf(parent_offset, resize); QuatMulVecf(qrot, parent_offset); @@ -1699,7 +1788,9 @@ static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], f ctrl->flag |= RIG_CTRL_HEAD_DONE; - if (ctrl->link_tail == NULL) + QUATCOPY(ctrl->qrot, qrot); + + if (ctrl->tail_mode == TL_NONE) { VecSubf(tail_offset, ctrl->tail, ctrl->head); VecMulf(tail_offset, resize); @@ -1710,7 +1801,7 @@ static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], f ctrl->flag |= RIG_CTRL_TAIL_DONE; } - finalizeControl(rigg, ctrl, qrot, resize); + finalizeControl(rigg, ctrl, resize); } static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3]) @@ -1755,6 +1846,10 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v { repositionControl(rigg, ctrl, vec0, vec1, qrot, resize); } + if (ctrl->link_tail == bone) + { + repositionTailControl(rigg, ctrl); + } } } From 913fd3c730be5a38751e7c1f6bca6e298cf8b1a8 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 12 Nov 2008 19:16:46 +0000 Subject: [PATCH 044/252] Sensible defaults with do_version Auto names for name templating. When turned on, N will be incremented everytime (after a stroke has been converted) and S will be set to "l" or "r" (or "L or "R" if it already contains a capital L or R) depending on which side of the X axis the stroke started on. Experimental, there might be some bugs left. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenloader/intern/readfile.c | 74 ++++++++++----------- source/blender/makesdna/DNA_scene_types.h | 2 +- source/blender/src/drawview.c | 8 ++- source/blender/src/editarmature_sketch.c | 56 ++++++++++++++++ 5 files changed, 97 insertions(+), 45 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f392d57521c..a6334e665d1 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 248 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 2 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 5a12342bb1b..c3937dce041 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7372,47 +7372,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ima->flag |= IMA_DO_PREMUL; } } - - if (main->versionfile < 245 || main->subversionfile < 12) - { - /* initialize skeleton generation toolsettings */ - for(sce=main->scene.first; sce; sce = sce->id.next) - { - sce->toolsettings->skgen_resolution = 50; - sce->toolsettings->skgen_threshold_internal = 0.01f; - sce->toolsettings->skgen_threshold_external = 0.01f; - sce->toolsettings->skgen_angle_limit = 45.0f; - sce->toolsettings->skgen_length_ratio = 1.3f; - sce->toolsettings->skgen_length_limit = 1.5f; - sce->toolsettings->skgen_correlation_limit = 0.98f; - sce->toolsettings->skgen_symmetry_limit = 0.1f; - sce->toolsettings->skgen_postpro = SKGEN_SMOOTH; - sce->toolsettings->skgen_postpro_passes = 1; - sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_SUB_CORRELATION; - sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION; - sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH; - sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE; - } - } } - - /* sanity check for skgen - * */ - { - Scene *sce; - for(sce=main->scene.first; sce; sce = sce->id.next) - { - if (sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[1] || - sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[2] || - sce->toolsettings->skgen_subdivisions[1] == sce->toolsettings->skgen_subdivisions[2]) - { - sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION; - sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH; - sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE; - } - } - } - if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) { Image *ima; @@ -7993,6 +7953,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 248 || main->subversionfile < 2) + { + Scene *sce; + + /* initialize skeleton generation toolsettings */ + for(sce=main->scene.first; sce; sce = sce->id.next) + { + sce->toolsettings->skgen_resolution = 250; + sce->toolsettings->skgen_threshold_internal = 0.1f; + sce->toolsettings->skgen_threshold_external = 0.1f; + sce->toolsettings->skgen_angle_limit = 30.0f; + sce->toolsettings->skgen_length_ratio = 1.3f; + sce->toolsettings->skgen_length_limit = 1.5f; + sce->toolsettings->skgen_correlation_limit = 0.98f; + sce->toolsettings->skgen_symmetry_limit = 0.1f; + sce->toolsettings->skgen_postpro = SKGEN_SMOOTH; + sce->toolsettings->skgen_postpro_passes = 3; + sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_FILTER_SMART|SKGEN_SUB_CORRELATION|SKGEN_HARMONIC; + sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION; + sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH; + sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE; + + + sce->toolsettings->skgen_retarget_angle_weight = 1.0f; + sce->toolsettings->skgen_retarget_length_weight = 1.0f; + sce->toolsettings->skgen_retarget_distance_weight = 1.0f; + + /* Skeleton Sketching */ + sce->toolsettings->bone_sketching = 0; + sce->toolsettings->skgen_retarget_options |= SK_RETARGET_ROLL; + } + } + + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 27696e49615..7c99ea57b76 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -865,7 +865,6 @@ typedef struct Scene { #define SKGEN_DISP_ORIG (1 << 12) #define SKGEN_DISP_EMBED (1 << 13) #define SKGEN_DISP_INDEX (1 << 14) -#define SKGEN_CUT_FIXED 64 #define SKGEN_SUB_LENGTH 0 #define SKGEN_SUB_ANGLE 1 @@ -889,6 +888,7 @@ typedef struct Scene { /* toolsettings->skgen_retarget_options */ #define SK_RETARGET_ROLL 1 +#define SK_RETARGET_AUTONAME 2 #ifdef __cplusplus diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 45cf79ca390..0f321504723 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2354,7 +2354,6 @@ static void view3d_panel_bonesketch_spaces(short cntrl) but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(), 10,yco,150,19, &template_index, 0, 0, 0, 0, "Template"); uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL); - //uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_DIFF, "OB:", 10, yco, 150, 19, &G.scene->toolsettings->skgen_template, "Template Object"); yco -= 20; uiDefButF(block, NUM, B_DIFF, "Ang:", 10, yco, 50,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); @@ -2362,8 +2361,11 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiDefButF(block, NUM, B_DIFF, "Dist:", 110,yco, 50,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); yco -= 20; - uiDefBut(block, TEX,0,"S:", 10, yco, 75, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace %S with"); - uiDefBut(block, TEX,0,"N:", 85, yco, 75, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace %N with"); + uiDefBut(block, TEX,0,"S:", 10, yco, 65, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace %S with"); + uiDefBut(block, TEX,0,"N:", 75, yco, 65, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace %N with"); + uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,140,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming"); + + /* auto renaming magic */ uiBlockEndAlign(block); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 99c274c6628..a0ba3223d9d 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -178,6 +178,11 @@ char *BIF_listTemplates() char menu_header[] = "Template%t|None%x0|"; char *p; + if (TEMPLATES_MENU != NULL) + { + MEM_freeN(TEMPLATES_MENU); + } + TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu"); p = TEMPLATES_MENU; @@ -472,6 +477,53 @@ int peelObjects(ListBase *depth_peels, short mval[2]) } /*********************** CONVERSION ***************************/ +void sk_autoname(ReebArc *arc) +{ + if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_AUTONAME) + { + if (arc == NULL) + { + char *num = G.scene->toolsettings->skgen_num_string; + int i = atoi(num); + i++; + BLI_snprintf(num, 8, "%i", i); + } + else + { + char *side = G.scene->toolsettings->skgen_side_string; + int valid = 0; + int caps = 0; + + if (BLI_streq(side, "")) + { + valid = 1; + } + else if (BLI_streq(side, "R") || BLI_streq(side, "L")) + { + valid = 1; + caps = 1; + } + else if (BLI_streq(side, "r") || BLI_streq(side, "l")) + { + valid = 1; + caps = 0; + } + + if (valid) + { + if (arc->head->p[0] < 0) + { + BLI_snprintf(side, 8, caps?"R":"r"); + } + else + { + BLI_snprintf(side, 8, caps?"L":"l"); + } + } + } + } +} + ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3]) { ReebNode *node; @@ -529,8 +581,12 @@ void sk_retargetStroke(SK_Stroke *stk) arc = sk_strokeToArc(stk, imat, tmat); + sk_autoname(arc); + BIF_retargetArc(arc); + sk_autoname(NULL); + MEM_freeN(arc->head); MEM_freeN(arc->tail); REEB_freeArc((BArc*)arc); From 3d6be3536f9b67438fab197147327d7d50580e06 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 13 Nov 2008 18:57:10 +0000 Subject: [PATCH 045/252] Fix saving and loading of the template variable (it incorrectedly counted as a user). --- source/blender/blenkernel/intern/object.c | 1 + source/blender/blenloader/intern/readfile.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index a25afeafaef..0b153c3c065 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -521,6 +521,7 @@ void unlink_object(Object *ob) while(sce) { if(sce->id.lib==NULL) { if(sce->camera==ob) sce->camera= NULL; + if(sce->toolsettings->skgen_template==ob) sce->toolsettings->skgen_template = NULL; } sce= sce->id.next; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c3937dce041..ea8db51a300 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3460,7 +3460,7 @@ static void lib_link_scene(FileData *fd, Main *main) newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.brush); - sce->toolsettings->skgen_template = newlibadr_us(fd, sce->id.lib, sce->toolsettings->skgen_template); + sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template); /* Sculptdata textures */ for(a=0; a Date: Fri, 14 Nov 2008 03:52:04 +0000 Subject: [PATCH 046/252] Stroke conversion wasn't quite ok with unaligned armatures. Last bugfix before sleep I swear. --- source/blender/src/editarmature_sketch.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index a0ba3223d9d..0d622431fd3 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1688,13 +1688,16 @@ EditBone * subdivideStrokeBy(SK_Stroke *stk, int start, int end, float invmat[][ while (index != -1) { setBoneRollFromPoint(parent, &stk->points[index], invmat, tmat); - Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */ child = addEditBone("Bone", &G.edbo, arm); VECCOPY(child->head, parent->tail); child->parent = parent; child->flag |= BONE_CONNECTED; + /* going to next bone, fix parent */ + Mat4MulVecfl(invmat, parent->tail); + Mat4MulVecfl(invmat, parent->head); + parent = child; // new child is next parent bone_start = index; // start next bone from current index @@ -1705,8 +1708,9 @@ EditBone * subdivideStrokeBy(SK_Stroke *stk, int start, int end, float invmat[][ setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); - Mat4MulVecfl(invmat, parent->head); + /* fix last bone */ Mat4MulVecfl(invmat, parent->tail); + Mat4MulVecfl(invmat, parent->head); lastBone = parent; return lastBone; From 59ac45dd12ca5a177318815f9396cd6b97cea766 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 14 Nov 2008 15:46:51 +0000 Subject: [PATCH 047/252] Reset max cost to FLT_MAX (this fixes a bug with early culling) Optimization when number of buckets == number of joints --- source/blender/src/editarmature_retarget.c | 68 +++++++++++++--------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index fdc409dd85b..2ac62d89143 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -1936,7 +1936,7 @@ static void printPositions(int *positions, int nb_positions) } #endif -#define MAX_COST 100 /* FIX ME */ +#define MAX_COST FLT_MAX /* FIX ME */ static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i0, int i1) { @@ -2174,10 +2174,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino ReebArc *earc = iarc->link_mesh; float min_cost = FLT_MAX; float *vec0, *vec1, *vec2; - float **vec_cache; - float *cost_cache; int *best_positions; - int *positions; int nb_edges = BLI_countlist(&iarc->edges); int nb_joints = nb_edges - 1; RetargetMethod method = METHOD_MEMOIZE; @@ -2189,10 +2186,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino return; } - positions = MEM_callocN(sizeof(int) * nb_joints, "Aggresive positions"); - best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best Aggresive positions"); - cost_cache = MEM_callocN(sizeof(float) * nb_edges, "Cost cache"); - vec_cache = MEM_callocN(sizeof(float*) * (nb_edges + 1), "Vec cache"); + best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best positions"); if (testFlipArc(iarc, inode_start)) { @@ -2204,23 +2198,18 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino node_start = earc->head; node_end = earc->tail; } - - /* init with first values */ - for (i = 0; i < nb_joints; i++) - { - positions[i] = i + 1; - //positions[i] = (earc->bcount / nb_edges) * (i + 1); - } - - /* init cost cache */ - for (i = 0; i < nb_edges; i++) - { - cost_cache[i] = 0; - } - - vec_cache[0] = node_start->p; - vec_cache[nb_edges] = node_end->p; + /* equal number of joints and potential position, just fill them in */ + if (nb_joints == earc->bcount) + { + int i; + + /* init with first values */ + for (i = 0; i < nb_joints; i++) + { + best_positions[i] = i + 1; + } + } if (method == METHOD_MEMOIZE) { int nb_positions = earc->bcount; @@ -2252,10 +2241,32 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino /* BRUTE FORCE */ else if (method == METHOD_BRUTE_FORCE) { + float **vec_cache; + float *cost_cache; + int *positions; int last_index = 0; int first_pass = 1; int must_move = nb_joints - 1; + positions = MEM_callocN(sizeof(int) * nb_joints, "Aggresive positions"); + cost_cache = MEM_callocN(sizeof(float) * nb_edges, "Cost cache"); + vec_cache = MEM_callocN(sizeof(float*) * (nb_edges + 1), "Vec cache"); + + /* init with first values */ + for (i = 0; i < nb_joints; i++) + { + positions[i] = i + 1; + } + + /* init cost cache */ + for (i = 0; i < nb_edges; i++) + { + cost_cache[i] = 0; + } + + vec_cache[0] = node_start->p; + vec_cache[nb_edges] = node_end->p; + while(1) { float cost = 0; @@ -2390,6 +2401,10 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino memcpy(best_positions, positions, sizeof(int) * nb_joints); } } + + MEM_freeN(positions); + MEM_freeN(cost_cache); + MEM_freeN(vec_cache); } vec0 = node_start->p; @@ -2427,11 +2442,8 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino vec0 = vec1; } - - MEM_freeN(positions); + MEM_freeN(best_positions); - MEM_freeN(cost_cache); - MEM_freeN(vec_cache); } static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_start) From d2023e070ca0bb179af999553493f70300fc9f07 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 14 Nov 2008 17:33:15 +0000 Subject: [PATCH 048/252] Pkey toggle sketching panel (it used to do select parent, but that's already done with [ and ] for children, no need for a second key). --- source/blender/src/editarmature_sketch.c | 5 +---- source/blender/src/space.c | 7 +++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 0d622431fd3..1e6ca59d802 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -209,7 +209,6 @@ int BIF_currentTemplate() if (TEMPLATES_CURRENT == 0 && G.scene->toolsettings->skgen_template != NULL) { GHashIterator ghi; - int index = 0; BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); while (!BLI_ghashIterator_isDone(&ghi)) @@ -217,11 +216,9 @@ int BIF_currentTemplate() Object *ob = BLI_ghashIterator_getValue(&ghi); int key = (int)BLI_ghashIterator_getKey(&ghi); - index++; - if (ob == G.scene->toolsettings->skgen_template) { - TEMPLATES_CURRENT = index; + TEMPLATES_CURRENT = key; break; } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index cbb4fe2624c..ede33374ac8 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -2516,8 +2516,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.qual==LR_ALTKEY && G.obedit->type==OB_ARMATURE) clear_bone_parent(); - else if((G.qual==0) && (G.obedit->type==OB_ARMATURE)) - armature_select_hierarchy(BONE_SELECT_PARENT, 1); // 1 = add to selection + else if((G.qual==0) && (G.obedit->type==OB_ARMATURE)) + { + toggle_blockhandler(curarea, VIEW3D_HANDLER_BONESKETCH, UI_PNL_TO_MOUSE); + allqueue(REDRAWVIEW3D, 0); + } else if((G.qual==(LR_CTRLKEY|LR_ALTKEY)) && (G.obedit->type==OB_ARMATURE)) separate_armature(); else if((G.qual==0) && G.obedit->type==OB_MESH) From 139f6bb1aac5c7dbf50e44134338b566755f0fc9 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 17 Nov 2008 20:38:04 +0000 Subject: [PATCH 049/252] New option for roll correction. Calculate new roll based on the angle to the normal of the joint (cross produce of the two bones). This works best in some cases but not in others, so it's an option for now. I'll have to see if I can iron the left over kinks, then it can be made the default (with Align to view an added option). --- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/include/BIF_retarget.h | 3 +- source/blender/makesdna/DNA_scene_types.h | 10 ++- source/blender/src/drawview.c | 38 ++++----- source/blender/src/editarmature_retarget.c | 88 +++++++++++++++++++-- source/blender/src/editarmature_sketch.c | 14 +--- 6 files changed, 115 insertions(+), 40 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9001e75b55b..18dff78c050 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7999,7 +7999,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* Skeleton Sketching */ sce->toolsettings->bone_sketching = 0; - sce->toolsettings->skgen_retarget_options |= SK_RETARGET_ROLL; + sce->toolsettings->skgen_retarget_roll = SK_RETARGET_ROLL_VIEW; } } diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h index 60e180f214e..26c673d7c30 100644 --- a/source/blender/include/BIF_retarget.h +++ b/source/blender/include/BIF_retarget.h @@ -107,7 +107,8 @@ typedef struct RigEdge { struct RigEdge *next, *prev; float head[3], tail[3]; float length; - float angle; + float angle; /* angle to next edge */ + float up_angle; /* angle between up_axis and the joint normal (defined as Previous edge CrossProduct Current edge */ EditBone *bone; float up_axis[3]; } RigEdge; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 7c99ea57b76..10e8c534ab2 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -448,12 +448,13 @@ typedef struct ToolSettings { char bone_sketching_convert; char skgen_subdivision_number; char skgen_retarget_options; + char skgen_retarget_roll; char skgen_side_string[8]; char skgen_num_string[8]; /* Alt+RMB option */ char edge_mode; - char pad3[3]; + char pad3[2]; } ToolSettings; /* Used by all brushes to store their properties, which can be directly set @@ -887,8 +888,11 @@ typedef struct Scene { #define SK_CONVERT_RETARGET 4 /* toolsettings->skgen_retarget_options */ -#define SK_RETARGET_ROLL 1 -#define SK_RETARGET_AUTONAME 2 +#define SK_RETARGET_AUTONAME 1 + +/* toolsettings->skgen_retarget_roll */ +#define SK_RETARGET_ROLL_VIEW 1 +#define SK_RETARGET_ROLL_JOINT 2 #ifdef __cplusplus diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 0f321504723..2d0cf01d4a8 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2310,15 +2310,14 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockBeginAlign(block); /* use real flag instead of 1 */ - uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 130, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); - uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 140, yco, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end"); + uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 180, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 190, yco, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end"); yco -= 20; - but = uiDefBut(block, BUT, B_REDR, "Convert", 10,yco,150,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); + but = uiDefBut(block, BUT, B_REDR, "Convert", 10,yco,100,20, 0, 0, 0, 0, 0, "Convert sketch to armature"); uiButSetFunc(but, convert_sketch_armature, NULL, NULL); - yco -= 20; - but = uiDefBut(block, BUT, B_REDR, "Delete", 10,yco,150,20, 0, 0, 0, 0, 0, "Delete sketch"); + but = uiDefBut(block, BUT, B_REDR, "Delete", 110,yco,100,20, 0, 0, 0, 0, 0, "Delete sketch"); uiButSetFunc(but, delete_sketch_armature, NULL, NULL); yco -= 20; @@ -2327,20 +2326,21 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockBeginAlign(block); uiDefButC(block, ROW, B_REDR, "Length", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_LENGTH, 0, 0, "Subdivide arcs in bones of equal length"); - uiDefButF(block, NUM, B_REDR, "L:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the subdivided bones"); + uiDefButF(block, NUM, B_REDR, "Lim:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the subdivided bones"); yco -= 20; uiDefButC(block, ROW, B_REDR, "Correlation", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_CORRELATION, 0, 0, "Subdivide arcs based on correlation"); - uiDefButF(block, NUM, B_REDR, "T:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Correlation threshold for subdivision"); + uiDefButF(block, NUM, B_REDR, "Thres:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Correlation threshold for subdivision"); yco -= 20; uiDefButC(block, ROW, B_REDR, "Fixed", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_FIXED, 0, 0, "Subdivide arcs based on a fixed number of bones"); - uiDefButC(block, NUM, B_REDR, "N:", 70, yco, 90, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Number of subdivided bones"); + uiDefButC(block, NUM, B_REDR, "Num:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Number of subdivided bones"); yco -= 20; - uiDefButC(block, ROW, B_REDR, "Retarget", 10, yco,80, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_RETARGET, 0, 0, "Retarget selected bones to stroke"); - uiDefButBitC(block, TOG, SK_RETARGET_ROLL, B_DIFF, "Roll", 90, yco, 70,19, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Roll bones perpendicular to view"); - /* button here to select what to do (copy or not), template, ...*/ + uiDefButC(block, ROW, B_REDR, "Retarget", 10, yco,80, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_RETARGET, 0, 0, "Retarget selected bones to stroke"); + uiDefButC(block, ROW, B_DIFF, "No", 90, yco, 40,19, &G.scene->toolsettings->skgen_retarget_roll, 0, 0, 0, 0, "No special roll treatment"); + uiDefButC(block, ROW, B_DIFF, "View", 130, yco, 40,19, &G.scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_VIEW, 0, 0, "Roll bones perpendicular to view"); + uiDefButC(block, ROW, B_DIFF, "Joint", 170, yco, 40,19, &G.scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_JOINT, 0, 0, "Roll bones relative to joint bend"); yco -= 20; uiBlockEndAlign(block); @@ -2348,22 +2348,24 @@ static void view3d_panel_bonesketch_spaces(short cntrl) yco -= 10; uiBlockBeginAlign(block); + /* button here to select what to do (copy or not), template, ...*/ + BIF_makeListTemplates(); template_index = BIF_currentTemplate(); - but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(), 10,yco,150,19, &template_index, 0, 0, 0, 0, "Template"); + but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(), 10,yco,200,19, &template_index, 0, 0, 0, 0, "Template"); uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL); yco -= 20; - uiDefButF(block, NUM, B_DIFF, "Ang:", 10, yco, 50,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); - uiDefButF(block, NUM, B_DIFF, "Len:", 60, yco, 50,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); - uiDefButF(block, NUM, B_DIFF, "Dist:", 110,yco, 50,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); + uiDefButF(block, NUM, B_DIFF, "A:", 10, yco, 66,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); + uiDefButF(block, NUM, B_DIFF, "L:", 76, yco, 67,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); + uiDefButF(block, NUM, B_DIFF, "D:", 143,yco, 67,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); yco -= 20; - uiDefBut(block, TEX,0,"S:", 10, yco, 65, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace %S with"); - uiDefBut(block, TEX,0,"N:", 75, yco, 65, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace %N with"); - uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,140,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming"); + uiDefBut(block, TEX,0,"S:", 10, yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace %S with"); + uiDefBut(block, TEX,0,"N:", 100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace %N with"); + uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,190,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming"); /* auto renaming magic */ diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 2ac62d89143..23b0ba1d964 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -110,7 +110,8 @@ RigGraph *GLOBAL_RIGG = NULL; void *exec_retargetArctoArc(void *param); -static void RIG_calculateEdgeAngle(RigEdge *edge_first, RigEdge *edge_second); +static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second); +float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]); /* two levels */ #define SHAPE_LEVELS (SHAPE_RADIX * SHAPE_RADIX) @@ -200,12 +201,63 @@ float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], } } -float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float quat[4]) +float rollBoneByQuatJoint(RigEdge *edge, RigEdge *previous, float qrot[4], float qroll[4]) +{ + if (previous == NULL) + { + QuatOne(qroll); + return rollBoneByQuat(edge->bone, edge->up_axis, qrot); + } + else + { + float new_up_axis[3]; + float vec_first[3], vec_second[3], normal[3]; + + if (previous->bone) + { + VecSubf(vec_first, previous->bone->tail, previous->bone->head); + } + else if (previous->prev->bone) + { + VecSubf(vec_first, edge->bone->head, previous->prev->bone->tail); + } + else + { + /* SHOULDN'T BE HERE */ + QuatOne(qroll); + return rollBoneByQuat(edge->bone, edge->up_axis, qrot); + } + + VecSubf(vec_second, edge->bone->tail, edge->bone->head); + + Normalize(vec_first); + Normalize(vec_second); + + Crossf(normal, vec_first, vec_second); + Normalize(normal); + + AxisAngleToQuat(qroll, vec_second, edge->up_angle); + + QuatMulVecf(qroll, normal); + + VECCOPY(new_up_axis, edge->up_axis); + QuatMulVecf(qrot, new_up_axis); + + Normalize(new_up_axis); + + /* real qroll between normal and up_axis */ + RotationBetweenVectorsToQuat(qroll, new_up_axis, normal); + + return rollBoneToVector(edge->bone, normal); + } +} + +float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]) { float new_up_axis[3]; VECCOPY(new_up_axis, old_up_axis); - QuatMulVecf(quat, new_up_axis); + QuatMulVecf(qrot, new_up_axis); Normalize(new_up_axis); @@ -372,7 +424,7 @@ static void RIG_appendEdgeToArc(RigArc *arc, RigEdge *edge) { RigEdge *last_edge = edge->prev; VECCOPY(edge->head, last_edge->tail); - RIG_calculateEdgeAngle(last_edge, edge); + RIG_calculateEdgeAngles(last_edge, edge); } edge->length = VecLenf(edge->head, edge->tail); @@ -493,6 +545,7 @@ static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash * edge->length = src_edge->length; edge->angle = src_edge->angle; + edge->up_angle = src_edge->up_angle; if (src_edge->bone != NULL) { @@ -596,7 +649,7 @@ static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob) /*******************************************************************************************************/ -static void RIG_calculateEdgeAngle(RigEdge *edge_first, RigEdge *edge_second) +static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second) { float vec_first[3], vec_second[3]; @@ -606,7 +659,17 @@ static void RIG_calculateEdgeAngle(RigEdge *edge_first, RigEdge *edge_second) Normalize(vec_first); Normalize(vec_second); - edge_first->angle = saacos(Inpf(vec_first, vec_second)); + edge_first->angle = NormalizedVecAngle2(vec_first, vec_second); + + if (edge_second->bone != NULL) + { + float normal[3]; + + Crossf(normal, vec_first, vec_second); + Normalize(normal); + + edge_second->up_angle = NormalizedVecAngle2(normal, edge_second->up_axis); + } } /************************************ CONTROL BONES ****************************************************/ @@ -1831,7 +1894,18 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v { float qroll[4]; - bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis); + if (G.scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_VIEW) + { + bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis); + } + else if (G.scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_JOINT) + { + bone->roll = rollBoneByQuatJoint(edge, edge->next, qrot, qroll); + } + else + { + QuatOne(qroll); + } QuatMul(qrot, qroll, qrot); } diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 1e6ca59d802..03676d39088 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -529,11 +529,8 @@ ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3]) VECCOPY(node->p, pt->p); Mat4MulVecfl(imat, node->p); - if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_ROLL) - { - VECCOPY(node->no, pt->no); - Mat3MulVecfl(tmat, node->no); - } + VECCOPY(node->no, pt->no); + Mat3MulVecfl(tmat, node->no); return node; } @@ -555,11 +552,8 @@ ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3]) VECCOPY(arc->buckets[i].p, stk->points[i + 1].p); Mat4MulVecfl(imat, arc->buckets[i].p); - if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_ROLL) - { - VECCOPY(arc->buckets[i].no, stk->points[i + 1].no); - Mat3MulVecfl(tmat, arc->buckets[i].no); - } + VECCOPY(arc->buckets[i].no, stk->points[i + 1].no); + Mat3MulVecfl(tmat, arc->buckets[i].no); } return arc; From 497c9b4ce7301b5b5b589359704b418acbeb594a Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 17 Nov 2008 21:03:41 +0000 Subject: [PATCH 050/252] Use grease pencil manhattan distance threshold for strokes. --- source/blender/src/editarmature_sketch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 03676d39088..45a9238cddc 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -31,6 +31,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_armature_types.h" +#include "DNA_userdef_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -1450,7 +1451,7 @@ void sk_updateNextPoint(SK_Sketch *sketch) int sk_stroke_filtermval(SK_DrawData *dd) { int retval = 0; - if (dd->mval[0] != dd->previous_mval[0] || dd->mval[1] != dd->previous_mval[1]) + if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist) { retval = 1; } From 2d0a005aaa6f14bc80a6c9a0c34f853920d1bac8 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 17 Nov 2008 21:11:12 +0000 Subject: [PATCH 051/252] Template retarget now works with normal conversion (not in Quick mode that is). --- source/blender/src/editarmature_retarget.c | 2 -- source/blender/src/editarmature_sketch.c | 12 ++++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 23b0ba1d964..c2a64ef017b 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -3082,8 +3082,6 @@ void BIF_retargetArc(ReebArc *earc) RIG_freeRigGraph((BGraph*)template_rigg); RIG_freeRigGraph((BGraph*)rigg); - - BIF_undo_push("Retarget Arc"); allqueue(REDRAWVIEW3D, 0); } diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 45a9238cddc..c221cb53e65 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1802,7 +1802,15 @@ void sk_convert(SK_Sketch *sketch) { if (stk->selected == 1) { - sk_convertStroke(stk); + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET) + { + sk_retargetStroke(stk); + } + else + { + sk_convertStroke(stk); + } + allqueue(REDRAWBUTSEDIT, 0); } } } @@ -2519,8 +2527,8 @@ int sk_paint(SK_Sketch *sketch, short mbut) else { sk_convertStroke(stk); - BIF_undo_push("Convert Sketch"); } + BIF_undo_push("Convert Sketch"); sk_removeStroke(sketch, stk); allqueue(REDRAWBUTSEDIT, 0); } From 9ba822c4d76bd84699e3980d1f12e58a200c006f Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 17 Nov 2008 23:02:53 +0000 Subject: [PATCH 052/252] Fix leak on exit (it's not a real fix, still uses silly global mem) --- source/blender/include/BIF_editarmature.h | 6 +++++- source/blender/src/editarmature_sketch.c | 9 +++++++++ source/blender/src/usiblender.c | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index ad3623cad60..19d64f853e8 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -169,11 +169,15 @@ void align_selected_bones(void); #define BONESEL_NOSEL 0x80000000 /* Indicates a negative number */ -/* from autoarmature */ +/* from editarmature_retarget */ void BIF_retargetArmature(); void BIF_adjustRetarget(); void BIF_freeRetarget(); +/* from editarmature_sketch */ +void BIF_freeSketch(); +void BIF_freeTemplates(); + struct ReebArc; float calcVariance(struct ReebArc *arc, int start, int end, float v0[3], float n[3]); float calcDistance(struct ReebArc *arc, int start, int end, float head[3], float tail[3]); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index c221cb53e65..2debb63c13d 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -2745,3 +2745,12 @@ int BIF_fullSketchMode() return 0; } } + +void BIF_freeSketch() +{ + if (GLOBAL_sketch != NULL) + { + sk_freeSketch(GLOBAL_sketch); + GLOBAL_sketch = NULL; + } +} diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 7ebdc3a11cd..e3f153a64b6 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -1104,6 +1104,7 @@ void exit_usiblender(void) BIF_GlobalReebFree(); BIF_freeRetarget(); BIF_freeTemplates(); + BIF_freeSketch(); tf= G.ttfdata.first; while(tf) From 9bb9859753a18d9a72ac0cb482a765c4e40f4676 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 19 Nov 2008 20:01:13 +0000 Subject: [PATCH 053/252] draft for arc iterators to unify code. Just moving code to work home, nothing to see here. --- source/blender/blenlib/BLI_graph.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source/blender/blenlib/BLI_graph.h b/source/blender/blenlib/BLI_graph.h index 160c2e04cf5..12ca87577d5 100644 --- a/source/blender/blenlib/BLI_graph.h +++ b/source/blender/blenlib/BLI_graph.h @@ -60,6 +60,24 @@ typedef struct BArc { int symmetry_flag; } BArc; +struct BArcIterator; + +typedef float* (*PeekPointFct)(struct BArcIterator* iter, int n); +typedef float* (*NextPointFct)(struct BArcIterator* iter); +typedef float* (*CurrentPointFct)(struct BArcIterator* iter); +typedef float* (*PreviousPointFct)(struct BArcIterator* iter); +typedef int (*StoppedFct)(struct BArcIterator* iter); + +typedef struct BArcIterator { + PeekPointFct peek; + NextPointFct next; + CurrentPointFct current; + PreviousPointFct previous; + StoppedFct stopped; + + int length; +} BArcIterator; + /* Helper structure for radial symmetry */ typedef struct RadialArc { From c6ff0ec49d7781ba3b320299c34789fedae0e7ba Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 20 Nov 2008 22:23:01 +0000 Subject: [PATCH 054/252] Change name templating to &S and &N (less potential bugs). It now also accepts lower case versions (&s and &n). --- source/blender/src/drawview.c | 4 ++-- source/blender/src/editarmature_retarget.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 2d0cf01d4a8..6a9530e27cb 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2363,8 +2363,8 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiDefButF(block, NUM, B_DIFF, "D:", 143,yco, 67,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); yco -= 20; - uiDefBut(block, TEX,0,"S:", 10, yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace %S with"); - uiDefBut(block, TEX,0,"N:", 100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace %N with"); + uiDefBut(block, TEX,0,"S:", 10, yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with"); + uiDefBut(block, TEX,0,"N:", 100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with"); uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,190,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming"); /* auto renaming magic */ diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index c2a64ef017b..019d91d9bff 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -460,14 +460,14 @@ static void renameTemplateBone(char *name, char *template_name, ListBase *editbo for (i = 0, j = 0; template_name[i] != '\0' && i < 31 && j < 31; i++) { - if (template_name[i] == '%') + if (template_name[i] == '&') { - if (template_name[i+1] == 'S') + if (template_name[i+1] == 'S' || template_name[i+1] == 's') { j += sprintf(name + j, side_string); i++; } - else if (template_name[i+1] == 'N') + else if (template_name[i+1] == 'N' || template_name[i+1] == 'n') { j += sprintf(name + j, num_string); i++; From 6ae70999b948c00669a0e4f73f5007e5e2d1589d Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sat, 22 Nov 2008 17:58:49 +0000 Subject: [PATCH 055/252] Cache the armature template graph while in editmode. Display the number of joints in the selected template in the sketch panel When using selected bones as template, turn off Connected if bone has a parent that is not copied. --- source/blender/include/BIF_retarget.h | 18 ++++-- source/blender/include/BIF_sketch.h | 3 +- source/blender/src/drawview.c | 17 ++++- source/blender/src/editarmature.c | 2 + source/blender/src/editarmature_retarget.c | 73 ++++++++++++++++------ source/blender/src/editarmature_sketch.c | 62 +++++++++++++++++- 6 files changed, 146 insertions(+), 29 deletions(-) diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h index 26c673d7c30..9400b69e483 100644 --- a/source/blender/include/BIF_retarget.h +++ b/source/blender/include/BIF_retarget.h @@ -31,6 +31,9 @@ #include "reeb.h" +struct Object; +struct bArmature; + struct EditBone; struct RigJoint; @@ -65,7 +68,7 @@ typedef struct RigGraph { GHash *bones_map; /* map of editbones by name */ GHash *controls_map; /* map of rigcontrols by bone pointer */ - Object *ob; + struct Object *ob; } RigGraph; typedef struct RigNode { @@ -109,7 +112,7 @@ typedef struct RigEdge { float length; float angle; /* angle to next edge */ float up_angle; /* angle between up_axis and the joint normal (defined as Previous edge CrossProduct Current edge */ - EditBone *bone; + struct EditBone *bone; float up_axis[3]; } RigEdge; @@ -132,9 +135,9 @@ typedef enum { typedef struct RigControl { struct RigControl *next, *prev; float head[3], tail[3]; - EditBone *bone; - EditBone *link; - EditBone *link_tail; + struct EditBone *bone; + struct EditBone *link; + struct EditBone *link_tail; float up_axis[3]; float offset[3]; float qrot[4]; /* for dual linked bones, store the rotation of the linked bone for the finalization */ @@ -142,6 +145,9 @@ typedef struct RigControl { LinkTailMode tail_mode; } RigControl; -void BIF_retargetArc(ReebArc *earc); +void BIF_retargetArc(ReebArc *earc, RigGraph *template_rigg); +RigGraph *RIG_graphFromArmature(struct Object *ob, struct bArmature *arm); +int RIG_nbJoints(RigGraph *rg); +void RIG_freeRigGraph(BGraph *rg); #endif /* BIF_RETARGET_H */ diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h index 6295ce41788..28b975487de 100644 --- a/source/blender/include/BIF_sketch.h +++ b/source/blender/include/BIF_sketch.h @@ -36,6 +36,7 @@ void BIF_makeListTemplates(); char *BIF_listTemplates(); int BIF_currentTemplate(); void BIF_freeTemplates(); -void BIF_setTemplate(int); +void BIF_setTemplate(int); +int BIF_nbJointsTemplate(); #endif /* BIF_SKETCH_H */ diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 6a9530e27cb..542afc321d6 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2291,10 +2291,11 @@ static void assign_template_sketch_armature(void *arg1, void *arg2) static void view3d_panel_bonesketch_spaces(short cntrl) { static int template_index; + static char joint_label[32]; uiBlock *block; uiBut *but; int yco = 70, height = 140; -// int index; + int nb_joints; /* replace with check call to sketching lib */ if (G.obedit && G.obedit->type == OB_ARMATURE) @@ -2366,10 +2367,22 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiDefBut(block, TEX,0,"S:", 10, yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with"); uiDefBut(block, TEX,0,"N:", 100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with"); uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,190,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming"); + yco -= 20; /* auto renaming magic */ - uiBlockEndAlign(block); + + nb_joints = BIF_nbJointsTemplate(); + + if (nb_joints == -1) + { + nb_joints = G.totvertsel; + } + + BLI_snprintf(joint_label, 32, "%i joints", nb_joints); + + uiDefBut(block, LABEL, 1, joint_label, 10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, ""); + if(yco < 0) uiNewPanelHeight(block, height-yco); } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 9559059e44c..42053ee168b 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -1740,6 +1740,8 @@ void make_editArmature(void) if (!arm) return; make_boneList(&G.edbo, &arm->bonebase,NULL); + + BIF_freeTemplates(); /* force template update when entering editmode */ } /* put EditMode back in Object */ diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 019d91d9bff..062ca95031f 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -613,12 +613,22 @@ static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob) EditBone *bone; updateDuplicateSubtargetObjects(edge->bone, src->editbones, src->ob, rg->ob); - - bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent); - - if (bone != NULL) - { - edge->bone->parent = bone; + + if (edge->bone->parent) + { + bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent); + + if (bone != NULL) + { + edge->bone->parent = bone; + } + else + { + /* disconnect since parent isn't cloned + * this will only happen when cloning from selected bones + * */ + edge->bone->flag &= ~BONE_CONNECTED; + } } } } @@ -630,11 +640,21 @@ static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob) updateDuplicateSubtargetObjects(ctrl->bone, src->editbones, src->ob, rg->ob); - bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent); - - if (bone != NULL) + if (ctrl->bone->parent) { - ctrl->bone->parent = bone; + bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent); + + if (bone != NULL) + { + ctrl->bone->parent = bone; + } + else + { + /* disconnect since parent isn't cloned + * this will only happen when cloning from selected bones + * */ + ctrl->bone->flag &= ~BONE_CONNECTED; + } } ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link); @@ -1507,7 +1527,7 @@ void RIG_printGraph(RigGraph *rg) /*******************************************************************************************************/ -RigGraph *armatureToGraph(Object *ob, bArmature *arm) +RigGraph *RIG_graphFromArmature(Object *ob, bArmature *arm) { EditBone *ebone; RigGraph *rg; @@ -2958,6 +2978,20 @@ static void retargetGraphs(RigGraph *rigg) editbones_to_armature(rigg->editbones, rigg->ob); } +int RIG_nbJoints(RigGraph *rg) +{ + RigArc *arc; + int total = 0; + + total += BLI_countlist(&rg->nodes); + + for (arc = rg->arcs.first; arc; arc = arc->next) + { + total += BLI_countlist(&arc->edges) - 1; /* -1 because end nodes are already counted */ + } + + return total; +} void BIF_retargetArmature() { @@ -2995,7 +3029,7 @@ void BIF_retargetArmature() start_time = PIL_check_seconds_timer(); - rigg = armatureToGraph(ob, arm); + rigg = RIG_graphFromArmature(ob, arm); end_time = PIL_check_seconds_timer(); rig_time = end_time - start_time; @@ -3040,20 +3074,17 @@ void BIF_retargetArmature() allqueue(REDRAWVIEW3D, 0); } -void BIF_retargetArc(ReebArc *earc) +void BIF_retargetArc(ReebArc *earc, RigGraph *template_rigg) { Object *ob; - RigGraph *template_rigg; RigGraph *rigg; RigArc *iarc; bArmature *arm; - if (G.scene->toolsettings->skgen_template && - G.scene->toolsettings->skgen_template->type == OB_ARMATURE) + if (template_rigg) { - ob = G.scene->toolsettings->skgen_template; + ob = template_rigg->ob; arm = ob->data; - template_rigg = armatureToGraph(ob, arm); } else { @@ -3080,7 +3111,11 @@ void BIF_retargetArc(ReebArc *earc) finishRetarget(rigg); - RIG_freeRigGraph((BGraph*)template_rigg); + /* free template if it comes from the edit armature */ + if (ob == G.obedit) + { + RIG_freeRigGraph((BGraph*)template_rigg); + } RIG_freeRigGraph((BGraph*)rigg); allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 2debb63c13d..d558445dec6 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -142,6 +142,7 @@ int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3] char *TEMPLATES_MENU = NULL; int TEMPLATES_CURRENT = 0; GHash *TEMPLATES_HASH = NULL; +RigGraph *TEMPLATE_RIGG = NULL; void BIF_makeListTemplates() { @@ -230,16 +231,66 @@ int BIF_currentTemplate() return TEMPLATES_CURRENT; } +RigGraph* sk_makeTemplateGraph(Object *ob) +{ + if (ob == G.obedit) + { + return NULL; + } + + if (ob != NULL) + { + if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob) + { + RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG); + TEMPLATE_RIGG = NULL; + } + + if (TEMPLATE_RIGG == NULL) + { + bArmature *arm; + + arm = ob->data; + + TEMPLATE_RIGG = RIG_graphFromArmature(ob, arm); + } + } + + return TEMPLATE_RIGG; +} + +int BIF_nbJointsTemplate() +{ + RigGraph *rg = sk_makeTemplateGraph(G.scene->toolsettings->skgen_template); + + if (rg) + { + return RIG_nbJoints(rg); + } + else + { + return -1; + } +} + void BIF_freeTemplates() { if (TEMPLATES_MENU != NULL) { MEM_freeN(TEMPLATES_MENU); + TEMPLATES_MENU = NULL; } if (TEMPLATES_HASH != NULL) { BLI_ghash_free(TEMPLATES_HASH, NULL, NULL); + TEMPLATES_HASH = NULL; + } + + if (TEMPLATE_RIGG != NULL) + { + RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG); + TEMPLATE_RIGG = NULL; } } @@ -252,6 +303,12 @@ void BIF_setTemplate(int index) else { G.scene->toolsettings->skgen_template = NULL; + + if (TEMPLATE_RIGG != NULL) + { + RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG); + } + TEMPLATE_RIGG = NULL; } } @@ -565,6 +622,7 @@ void sk_retargetStroke(SK_Stroke *stk) float imat[4][4]; float tmat[3][3]; ReebArc *arc; + RigGraph *rg; Mat4Invert(imat, G.obedit->obmat); @@ -574,8 +632,10 @@ void sk_retargetStroke(SK_Stroke *stk) arc = sk_strokeToArc(stk, imat, tmat); sk_autoname(arc); + + rg = sk_makeTemplateGraph(G.scene->toolsettings->skgen_template); - BIF_retargetArc(arc); + BIF_retargetArc(arc, rg); sk_autoname(NULL); From 8a4a2d96d0fb38548366a73a44440deba43571e7 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sat, 22 Nov 2008 22:22:38 +0000 Subject: [PATCH 056/252] Fix bug with name templating text buttons (wrong event). --- source/blender/src/drawview.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 542afc321d6..e652ea989d1 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2364,8 +2364,8 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiDefButF(block, NUM, B_DIFF, "D:", 143,yco, 67,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); yco -= 20; - uiDefBut(block, TEX,0,"S:", 10, yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with"); - uiDefBut(block, TEX,0,"N:", 100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with"); + uiDefBut(block, TEX,B_DIFF,"S:", 10, yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with"); + uiDefBut(block, TEX,B_DIFF,"N:", 100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with"); uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,190,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming"); yco -= 20; From 933ac8db12729327ccd313dea0575ad2eb631fa0 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 24 Nov 2008 17:48:40 +0000 Subject: [PATCH 057/252] Link pole controls to the parent of the bone with the IK constraint. Presumably, this should give better result, but tests where not conclusive. --- source/blender/src/editarmature_retarget.c | 30 +++++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 062ca95031f..00cfafad0f5 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -805,15 +805,26 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* constraint targets */ if (cti && cti->get_constraint_targets) { + int target_index; + cti->get_constraint_targets(con, &targets); - for (ct= targets.first; ct; ct= ct->next) + for (target_index = 0, ct= targets.first; ct; target_index++, ct= ct->next) { if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0) { /* SET bone link to bone corresponding to pchan */ EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name); + /* for pole targets, link to parent bone instead, if possible */ + if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1) + { + if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name)) + { + link = link->parent; + } + } + found = RIG_parentControl(ctrl, link); } } @@ -1011,14 +1022,12 @@ static void RIG_reconnectControlBones(RigGraph *rg) { if (VecLenf(ctrl->bone->tail, bone->head) < 0.01) { - printf("%s -> %s: TL_HEAD\n", ctrl->bone->name, bone->name); ctrl->tail_mode = TL_HEAD; ctrl->link_tail = bone; break; } else if (VecLenf(ctrl->bone->tail, bone->tail) < 0.01) { - printf("%s -> %s: TL_TAIL\n", ctrl->bone->name, bone->name); ctrl->tail_mode = TL_TAIL; ctrl->link_tail = bone; break; @@ -1031,10 +1040,6 @@ static void RIG_reconnectControlBones(RigGraph *rg) { } } - else - { - printf("%s FIT\n", ctrl->bone->name); - } } } @@ -1808,6 +1813,17 @@ static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize) if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE) { RigControl *ctrl_child; + +#if 0 + printf("CTRL: %s LINK: %s", ctrl->bone->name, ctrl->link->name); + + if (ctrl->link_tail) + { + printf(" TAIL: %s", ctrl->link_tail->name); + } + + printf("\n"); +#endif /* if there was a tail link: apply link, recalc resize factor and qrot */ if (ctrl->tail_mode != TL_NONE) From d467158158b92ac9e92482db00ee51b2c16597f3 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 24 Nov 2008 19:24:49 +0000 Subject: [PATCH 058/252] Second step out of three for merging sketching subdivision methods with graph subdivision methods. Graph subdivision uses graph arc iterators. --- source/blender/blenlib/BLI_graph.h | 23 +-- source/blender/include/reeb.h | 23 +-- source/blender/src/editarmature.c | 72 +++++---- source/blender/src/editarmature_retarget.c | 20 +-- source/blender/src/reeb.c | 162 +++++++++++++-------- 5 files changed, 169 insertions(+), 131 deletions(-) diff --git a/source/blender/blenlib/BLI_graph.h b/source/blender/blenlib/BLI_graph.h index 12ca87577d5..7629dbf6ba8 100644 --- a/source/blender/blenlib/BLI_graph.h +++ b/source/blender/blenlib/BLI_graph.h @@ -62,20 +62,23 @@ typedef struct BArc { struct BArcIterator; -typedef float* (*PeekPointFct)(struct BArcIterator* iter, int n); -typedef float* (*NextPointFct)(struct BArcIterator* iter); -typedef float* (*CurrentPointFct)(struct BArcIterator* iter); -typedef float* (*PreviousPointFct)(struct BArcIterator* iter); -typedef int (*StoppedFct)(struct BArcIterator* iter); +typedef void* (*PeekFct)(void* iter, int n); +typedef void* (*NextFct)(void* iter); +typedef void* (*NextNFct)(void* iter, int n); +typedef void* (*PreviousFct)(void* iter); +typedef int (*StoppedFct)(void* iter); typedef struct BArcIterator { - PeekPointFct peek; - NextPointFct next; - CurrentPointFct current; - PreviousPointFct previous; - StoppedFct stopped; + PeekFct peek; + NextFct next; + NextNFct nextN; + PreviousFct previous; + StoppedFct stopped; + + float *p, *no; int length; + int index; } BArcIterator; /* Helper structure for radial symmetry */ diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index 927eded62d4..21c57495fb0 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -28,7 +28,7 @@ #ifndef REEB_H_ #define REEB_H_ -//#define WITH_BF_REEB +#define WITH_BF_REEB #include "DNA_listBase.h" @@ -120,12 +120,21 @@ typedef struct ReebArc { } ReebArc; typedef struct ReebArcIterator { - struct ReebArc *arc; + PeekFct peek; + NextFct next; + NextNFct nextN; + PreviousFct previous; + StoppedFct stopped; + + float *p, *no; + + int length; int index; + /*********************************/ + struct ReebArc *arc; int start; int end; - int stride; - int length; + int stride; } ReebArcIterator; struct EditMesh; @@ -145,12 +154,6 @@ ReebGraph * newReebGraph(); void initArcIterator(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head); void initArcIterator2(struct ReebArcIterator *iter, struct ReebArc *arc, int start, int end); void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start); -struct EmbedBucket * nextBucket(struct ReebArcIterator *iter); -struct EmbedBucket * nextNBucket(ReebArcIterator *iter, int n); -struct EmbedBucket * peekBucket(ReebArcIterator *iter, int n); -struct EmbedBucket * currentBucket(struct ReebArcIterator *iter); -struct EmbedBucket * previousBucket(struct ReebArcIterator *iter); -int iteratorStopped(struct ReebArcIterator *iter); /* Filtering */ void filterNullReebGraph(ReebGraph *rg); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 42053ee168b..bae6fc5a0af 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -4656,8 +4656,7 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) if (G.scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE) { ReebArcIterator iter; - EmbedBucket *current = NULL; - EmbedBucket *previous = NULL; + float *previous = NULL, *current = NULL; EditBone *child = NULL; EditBone *parent = NULL; EditBone *root = NULL; @@ -4669,22 +4668,28 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) root = parent; - for (initArcIterator(&iter, arc, head), previous = nextBucket(&iter), current = nextBucket(&iter); - current; - previous = current, current = nextBucket(&iter)) + initArcIterator(&iter, arc, head); + iter.next(&iter); + previous = iter.p; + + for (iter.next(&iter); + iter.stopped(&iter) == 0; + previous = iter.p, iter.next(&iter)) { float vec1[3], vec2[3]; float len1, len2; + + current = iter.p; - VecSubf(vec1, previous->p, parent->head); - VecSubf(vec2, current->p, previous->p); + VecSubf(vec1, previous, parent->head); + VecSubf(vec2, current, previous); len1 = Normalize(vec1); len2 = Normalize(vec2); if (len1 > 0.0f && len2 > 0.0f && Inpf(vec1, vec2) < angleLimit) { - VECCOPY(parent->tail, previous->p); + VECCOPY(parent->tail, previous); child = add_editbone("Bone"); VECCOPY(child->head, parent->tail); @@ -4718,19 +4723,18 @@ float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3]) if (len > 2) { ReebArcIterator iter; - EmbedBucket *bucket = NULL; float avg_t = 0.0f; float s_t = 0.0f; float s_xyz = 0.0f; /* First pass, calculate average */ - for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter); - bucket; - bucket = nextBucket(&iter)) + for (initArcIterator2(&iter, arc, start, end), iter.next(&iter); + iter.stopped(&iter) == 0; + iter.next(&iter)) { float v[3]; - VecSubf(v, bucket->p, v0); + VecSubf(v, iter.p, v0); avg_t += Inpf(v, n); } @@ -4739,14 +4743,14 @@ float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3]) avg_t /= len; /* Second pass, calculate s_xyz and s_t */ - for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter); - bucket; - bucket = nextBucket(&iter)) + for (initArcIterator2(&iter, arc, start, end), iter.next(&iter); + iter.stopped(&iter) == 0; + iter.next(&iter)) { float v[3], d[3]; float dt; - VecSubf(v, bucket->p, v0); + VecSubf(v, iter.p, v0); Projf(d, v, n); VecSubf(v, v, d); @@ -4770,19 +4774,18 @@ float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3]) float calcDistance(ReebArc *arc, int start, int end, float head[3], float tail[3]) { ReebArcIterator iter; - EmbedBucket *bucket = NULL; float max_dist = 0; /* calculate maximum distance */ - for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter); - bucket; - bucket = nextBucket(&iter)) + for (initArcIterator2(&iter, arc, start, end), iter.next(&iter); + iter.stopped(&iter) == 0; + iter.next(&iter)) { float v1[3], v2[3], c[3]; float dist; VecSubf(v1, head, tail); - VecSubf(v2, bucket->p, tail); + VecSubf(v2, iter.p, tail); Crossf(c, v1, v2); @@ -4810,8 +4813,6 @@ EditBone * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail) if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) { - EmbedBucket *bucket = NULL; - EmbedBucket *previous = NULL; EditBone *child = NULL; EditBone *parent = NULL; float normal[3] = {0, 0, 0}; @@ -4823,23 +4824,21 @@ EditBone * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail) parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; VECCOPY(parent->head, head->p); - for (previous = nextBucket(&iter), bucket = nextBucket(&iter); - bucket; - previous = bucket, bucket = nextBucket(&iter)) + while(iter.next(&iter)) { float btail[3]; float value = 0; if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING) { - VECCOPY(btail, bucket->p); + VECCOPY(btail, iter.p); } else { float length; /* Calculate normal */ - VecSubf(n, bucket->p, parent->head); + VecSubf(n, iter.p, parent->head); length = Normalize(n); total += 1; @@ -4923,8 +4922,7 @@ EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio) { ReebArcIterator iter; - EmbedBucket *bucket = NULL; - EmbedBucket *previous = NULL; + float *previous = NULL; EditBone *child = NULL; EditBone *parent = NULL; float lengthLimit = G.scene->toolsettings->skgen_length_limit; @@ -4936,12 +4934,12 @@ EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) initArcIterator(&iter, arc, head); - bucket = nextBucket(&iter); + iter.next(&iter); - while (bucket != NULL) + while (iter.stopped(&iter) == 0) { float *vec0 = NULL; - float *vec1 = bucket->p; + float *vec1 = iter.p; /* first bucket. Previous is head */ if (previous == NULL) @@ -4951,7 +4949,7 @@ EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) /* Previous is a valid bucket */ else { - vec0 = previous->p; + vec0 = previous; } /* If lengthLimit hits the current segment */ @@ -5009,8 +5007,8 @@ EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) } else { - previous = bucket; - bucket = nextBucket(&iter); + previous = iter.p; + iter.next(&iter); same = 0; // Reset same } } diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 00cfafad0f5..280292abaf0 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -1683,9 +1683,9 @@ EditBone * generateBonesForArc(RigGraph *rigg, ReebArc *arc, ReebNode *head, Ree parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; VECCOPY(parent->head, head->p); - for (previous = nextBucket(&iter), bucket = nextBucket(&iter); + for (previous = iter.next(&iter), bucket = iter.next(&iter); bucket; - previous = bucket, bucket = nextBucket(&iter)) + previous = bucket, bucket = iter.next(&iter)) { float btail[3]; float value = 0; @@ -2068,7 +2068,7 @@ static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i { float dist; - bucket = peekBucket(iter, j); + bucket = iter->peek(iter, j); VecSubf(v2, bucket->p, vec1); @@ -2336,7 +2336,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino for (i = 1; i <= nb_positions; i++) { - EmbedBucket *bucket = peekBucket(&iter, i); + EmbedBucket *bucket = iter.peek(&iter, i); positions_cache[i] = bucket->p; } @@ -2443,7 +2443,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino if (i < nb_joints) { i2 = positions[i]; - bucket = peekBucket(&iter, positions[i]); + bucket = iter.peek(&iter, positions[i]); vec2 = bucket->p; vec_cache[i + 1] = vec2; /* update cache for updated position */ } @@ -2535,7 +2535,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino float *no = NULL; if (i < nb_joints) { - bucket = peekBucket(&iter, best_positions[i]); + bucket = iter.peek(&iter, best_positions[i]); vec1 = bucket->p; no = bucket->no; } @@ -2582,7 +2582,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ initArcIterator(&iter, earc, node_start); - bucket = nextBucket(&iter); + bucket = iter.next(&iter); vec0 = node_start->p; @@ -2593,7 +2593,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ embedding_length += VecLenf(vec0, vec1); vec0 = vec1; - bucket = nextBucket(&iter); + bucket = iter.next(&iter); } embedding_length += VecLenf(node_end->p, vec1); @@ -2601,7 +2601,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ /* fit bones */ initArcIterator(&iter, earc, node_start); - bucket = nextBucket(&iter); + bucket = iter.next(&iter); vec0 = node_start->p; previous_vec = vec0; @@ -2616,7 +2616,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ while (bucket && new_bone_length > length) { length += VecLenf(previous_vec, vec1); - bucket = nextBucket(&iter); + bucket = iter.next(&iter); previous_vec = vec1; vec1 = bucket->p; no = bucket->no; diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index b37087064cb..bb53269bf12 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -851,7 +851,8 @@ void fillArcEmptyBuckets(ReebArc *arc) static void ExtendArcBuckets(ReebArc *arc) { ReebArcIterator iter; - EmbedBucket *previous, *bucket, *last_bucket, *first_bucket; + EmbedBucket *last_bucket, *first_bucket; + float *previous = NULL; float average_length = 0, length; int padding_head = 0, padding_tail = 0; @@ -861,13 +862,15 @@ static void ExtendArcBuckets(ReebArc *arc) } initArcIterator(&iter, arc, arc->head); + iter.next(&iter); + previous = iter.p; - for ( previous = nextBucket(&iter), bucket = nextBucket(&iter); - bucket; - previous = bucket, bucket = nextBucket(&iter) + for ( iter.next(&iter); + iter.stopped(&iter) == 0; + previous = iter.p, iter.next(&iter) ) { - average_length += VecLenf(previous->p, bucket->p); + average_length += VecLenf(previous, iter.p); } average_length /= (arc->bcount - 1); @@ -925,26 +928,22 @@ void extendGraphBuckets(ReebGraph *rg) void calculateArcLength(ReebArc *arc) { ReebArcIterator iter; - EmbedBucket *bucket = NULL; float *vec0, *vec1; arc->length = 0; initArcIterator(&iter, arc, arc->head); - bucket = nextBucket(&iter); - vec0 = arc->head->p; vec1 = arc->head->p; /* in case there's no embedding */ - - while (bucket != NULL) + + while (iter.next(&iter)) { - vec1 = bucket->p; + vec1 = iter.p; arc->length += VecLenf(vec0, vec1); vec0 = vec1; - bucket = nextBucket(&iter); } arc->length += VecLenf(arc->tail->p, vec1); @@ -1003,22 +1002,22 @@ void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count) initArcIterator(&iter1, arc1, (ReebNode*)root_node); initArcIterator(&iter2, arc2, (ReebNode*)root_node); - bucket1 = nextBucket(&iter1); - bucket2 = nextBucket(&iter2); + bucket1 = iter1.next(&iter1); + bucket2 = iter2.next(&iter2); /* Make sure they both start at the same value */ - while(bucket1 && bucket1->val < bucket2->val) + while(bucket1 && bucket2 && bucket1->val < bucket2->val) { - bucket1 = nextBucket(&iter1); + bucket1 = iter1.next(&iter1); } - while(bucket2 && bucket2->val < bucket1->val) + while(bucket1 && bucket2 && bucket2->val < bucket1->val) { - bucket2 = nextBucket(&iter2); + bucket2 = iter2.next(&iter2); } - for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = iter1.next(&iter1), bucket2 = iter2.next(&iter2)) { bucket2->nv += bucket1->nv; /* add counts */ @@ -1063,22 +1062,22 @@ void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count) initArcIterator(&iter1, arc1, node); initArcIterator(&iter2, arc2, node); - bucket1 = nextBucket(&iter1); - bucket2 = nextBucket(&iter2); + bucket1 = iter1.next(&iter1); + bucket2 = iter2.next(&iter2); /* Make sure they both start at the same value */ while(bucket1 && bucket1->val < bucket2->val) { - bucket1 = nextBucket(&iter1); + bucket1 = iter1.next(&iter1); } while(bucket2 && bucket2->val < bucket1->val) { - bucket2 = nextBucket(&iter2); + bucket2 = iter2.next(&iter2); } - for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = iter1.next(&iter1), bucket2 = iter1.next(&iter2)) { /* copy and mirror back to bucket2 */ bucket2->nv = bucket1->nv; @@ -1122,22 +1121,22 @@ void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BAr initArcIterator(&iter1, arc1, (ReebNode*)root_node); initArcIterator(&iter2, arc2, (ReebNode*)root_node); - bucket1 = nextBucket(&iter1); - bucket2 = nextBucket(&iter2); + bucket1 = iter1.next(&iter1); + bucket2 = iter2.next(&iter2); /* Make sure they both start at the same value */ while(bucket1 && bucket1->val < bucket2->val) { - bucket1 = nextBucket(&iter1); + bucket1 = iter1.next(&iter1); } while(bucket2 && bucket2->val < bucket1->val) { - bucket2 = nextBucket(&iter2); + bucket2 = iter1.next(&iter2); } - for ( ;bucket1 && bucket2; bucket1 = nextBucket(&iter1), bucket2 = nextBucket(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = iter2.next(&iter1), bucket2 = iter2.next(&iter2)) { bucket1->nv += bucket2->nv; /* add counts */ @@ -3297,8 +3296,38 @@ void arcToVCol(ReebGraph *rg, EditMesh *em, int index) /****************************************** BUCKET ITERATOR **************************************************/ +void* nextBucket(void *arg); +void* nextNBucket(void *arg, int n); +void* peekBucket(void *arg, int n); +void* previousBucket(void *arg); +int iteratorStopped(void *arg); + +void initIteratorFct(ReebArcIterator *iter) +{ + iter->peek = peekBucket; + iter->next = nextBucket; + iter->nextN = nextNBucket; + iter->previous = previousBucket; + iter->stopped = iteratorStopped; +} + +void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) +{ + if (bucket) + { + iter->p = bucket->p; + iter->no = bucket->no; + } + else + { + iter->p = NULL; + iter->no = NULL; + } +} + void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head) { + initIteratorFct(iter); iter->arc = arc; if (head == arc->head) @@ -3321,6 +3350,7 @@ void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head) void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start) { + initIteratorFct(iter); iter->arc = arc; if (head == arc->head) @@ -3348,6 +3378,7 @@ void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, str void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end) { + initIteratorFct(iter); iter->arc = arc; iter->start = start; @@ -3367,8 +3398,9 @@ void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end) iter->length = abs(iter->end - iter->start) + 1; } -EmbedBucket * nextBucket(ReebArcIterator *iter) +void* nextBucket(void *arg) { + ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; if (iter->index != iter->end) @@ -3377,13 +3409,15 @@ EmbedBucket * nextBucket(ReebArcIterator *iter) result = &(iter->arc->buckets[iter->index]); } + setIteratorValues(iter, result); return result; } -EmbedBucket * nextNBucket(ReebArcIterator *iter, int n) +void* nextNBucket(void *arg, int n) { + ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - + iter->index += n * iter->stride; /* check if passed end */ @@ -3398,11 +3432,13 @@ EmbedBucket * nextNBucket(ReebArcIterator *iter, int n) iter->index = iter->end; } + setIteratorValues(iter, result); return result; } -EmbedBucket * peekBucket(ReebArcIterator *iter, int n) +void* peekBucket(void *arg, int n) { + ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; int index = iter->index + n * iter->stride; @@ -3412,12 +3448,14 @@ EmbedBucket * peekBucket(ReebArcIterator *iter, int n) { result = &(iter->arc->buckets[index]); } - + + setIteratorValues(iter, result); return result; } -EmbedBucket * previousBucket(struct ReebArcIterator *iter) +void* previousBucket(void *arg) { + ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; if (iter->index != iter->start) @@ -3425,12 +3463,15 @@ EmbedBucket * previousBucket(struct ReebArcIterator *iter) iter->index -= iter->stride; result = &(iter->arc->buckets[iter->index]); } - + + setIteratorValues(iter, result); return result; } -int iteratorStopped(struct ReebArcIterator *iter) +int iteratorStopped(void *arg) { + ReebArcIterator *iter = (ReebArcIterator*)arg; + if (iter->index == iter->end) { return 1; @@ -3441,18 +3482,6 @@ int iteratorStopped(struct ReebArcIterator *iter) } } -struct EmbedBucket * currentBucket(struct ReebArcIterator *iter) -{ - EmbedBucket *result = NULL; - - if (iter->index != iter->end) - { - result = &(iter->arc->buckets[iter->index]); - } - - return result; -} - /************************ PUBLIC FUNCTIONS *********************************************/ ReebGraph *BIF_ReebGraphMultiFromEditMesh(void) @@ -3597,26 +3626,32 @@ ReebGraph *BIF_ReebGraphFromEditMesh(void) rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution); - REEB_exportGraph(rg, -1); - - printf("GENERATED\n"); - printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph*)rg)); /* Remove arcs without embedding */ filterNullReebGraph(rg); - BLI_freeAdjacencyList((BGraph*)rg); + /* smart filter and loop filter on basic level */ + filterGraph(rg, SKGEN_FILTER_SMART, 0, 0); - printf("NULL FILTERED\n"); - printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph*)rg)); + repositionNodes(rg); + /* Filtering might have created degree 2 nodes, so remove them */ + removeNormalNodes(rg); + + joinSubgraphs(rg, 1.0); + + BLI_buildAdjacencyList((BGraph*)rg); + + /* calc length before copy, so we have same length on all levels */ + BLI_calcGraphLength((BGraph*)rg); + filterGraph(rg, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external); finalizeGraph(rg, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro); +#ifdef DEBUG_REEB REEB_exportGraph(rg, -1); -#ifdef DEBUG_REEB arcToVCol(rg, em, 0); //angleToVCol(em, 1); #endif @@ -3677,7 +3712,6 @@ void REEB_draw() for (arc = rg->arcs.first; arc; arc = arc->next, i++) { ReebArcIterator iter; - EmbedBucket *bucket; float vec[3]; char text[128]; char *s = text; @@ -3690,9 +3724,9 @@ void REEB_draw() if (arc->bcount) { initArcIterator(&iter, arc, arc->head); - for (bucket = nextBucket(&iter); bucket; bucket = nextBucket(&iter)) + for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) { - glVertex3fv(bucket->p); + glVertex3fv(iter.p); } } @@ -3723,9 +3757,9 @@ void REEB_draw() if (arc->bcount) { initArcIterator(&iter, arc, arc->head); - for (bucket = nextBucket(&iter); bucket; bucket = nextBucket(&iter)) + for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) { - glVertex3fv(bucket->p); + glVertex3fv(iter.p); } } @@ -3744,9 +3778,9 @@ void REEB_draw() if (arc->bcount) { initArcIterator(&iter, arc, arc->head); - for (bucket = nextBucket(&iter); bucket; bucket = nextBucket(&iter)) + for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) { - glVertex3fv(bucket->p); + glVertex3fv(iter.p); } } glEnd(); From e2fb12ea18b4be8159fa14252af537d7dc01f585 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sat, 29 Nov 2008 20:37:10 +0000 Subject: [PATCH 059/252] Step 3/3, merging subdivision/bone creation methods using iterators This also adds a special Embedding option called "Peel Objects". This option makes the embedding snap consider objects as whole, taking the first and last hit of each of them to calculate the embedding point (instead of peeling with first/second, third/fourth and so on). This option is useful if you have mecanical pieces with lots of details (as single objects) and want to put bones in the middle (think of adding bones to a mecha, for example). --- source/blender/blenlib/BLI_graph.h | 14 +- source/blender/blenlib/intern/graph.c | 55 ++- source/blender/include/BIF_generate.h | 44 +++ source/blender/include/reeb.h | 10 +- source/blender/makesdna/DNA_scene_types.h | 1 + source/blender/src/drawview.c | 4 +- source/blender/src/editarmature.c | 303 ++------------ source/blender/src/editarmature_generate.c | 327 +++++++++++++++ source/blender/src/editarmature_retarget.c | 142 ++----- source/blender/src/editarmature_sketch.c | 437 ++++++++++----------- source/blender/src/reeb.c | 226 +++++++---- 11 files changed, 859 insertions(+), 704 deletions(-) create mode 100644 source/blender/include/BIF_generate.h create mode 100644 source/blender/src/editarmature_generate.c diff --git a/source/blender/blenlib/BLI_graph.h b/source/blender/blenlib/BLI_graph.h index 7629dbf6ba8..f4fccfcbb2c 100644 --- a/source/blender/blenlib/BLI_graph.h +++ b/source/blender/blenlib/BLI_graph.h @@ -62,13 +62,25 @@ typedef struct BArc { struct BArcIterator; +void* IT_head(void* iter); +void* IT_tail(void* iter); +void* IT_peek(void* iter, int n); +void* IT_next(void* iter); +void* IT_nextN(void* iter, int n); +void* IT_previous(void* iter); +int IT_stopped(void* iter); + +typedef void* (*HeadFct)(void* iter); +typedef void* (*TailFct)(void* iter); typedef void* (*PeekFct)(void* iter, int n); typedef void* (*NextFct)(void* iter); typedef void* (*NextNFct)(void* iter, int n); typedef void* (*PreviousFct)(void* iter); -typedef int (*StoppedFct)(void* iter); +typedef int (*StoppedFct)(void* iter); typedef struct BArcIterator { + HeadFct head; + TailFct tail; PeekFct peek; NextFct next; NextNFct nextN; diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c index e2ed8f11ee2..ca82fcac844 100644 --- a/source/blender/blenlib/intern/graph.c +++ b/source/blender/blenlib/intern/graph.c @@ -465,8 +465,6 @@ int subtreeShape(BNode *node, BArc *rootArc, int include_root) int BLI_subtreeShape(BGraph *graph, BNode *node, BArc *rootArc, int include_root) { - BNode *test_node; - BLI_flagNodes(graph, 0); return subtreeShape(node, rootArc, include_root); } @@ -1090,3 +1088,56 @@ void BLI_markdownSymmetry(BGraph *graph, BNode *root_node, float limit) } } +void* IT_head(void* arg) +{ + BArcIterator *iter = (BArcIterator*)arg; + return iter->head(iter); +} + +void* IT_tail(void* arg) +{ + BArcIterator *iter = (BArcIterator*)arg; + return iter->tail(iter); +} + +void* IT_peek(void* arg, int n) +{ + BArcIterator *iter = (BArcIterator*)arg; + + if (iter->index + n < 0) + { + return iter->head(iter); + } + else if (iter->index + n >= iter->length) + { + return iter->tail(iter); + } + else + { + return iter->peek(iter, n); + } +} + +void* IT_next(void* arg) +{ + BArcIterator *iter = (BArcIterator*)arg; + return iter->next(iter); +} + +void* IT_nextN(void* arg, int n) +{ + BArcIterator *iter = (BArcIterator*)arg; + return iter->nextN(iter, n); +} + +void* IT_previous(void* arg) +{ + BArcIterator *iter = (BArcIterator*)arg; + return iter->previous(iter); +} + +int IT_stopped(void* arg) +{ + BArcIterator *iter = (BArcIterator*)arg; + return iter->stopped(iter); +} diff --git a/source/blender/include/BIF_generate.h b/source/blender/include/BIF_generate.h new file mode 100644 index 00000000000..32d89d32f78 --- /dev/null +++ b/source/blender/include/BIF_generate.h @@ -0,0 +1,44 @@ +/** + * $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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BIF_GENERATE_H +#define BIF_GENERATE_H + +struct EditBone; +struct BArcIterator; +struct bArmature; +struct ListBase; + +typedef int(NextSubdivisionFunc)(struct BArcIterator*, int, int, float[3], float[3]); + +float calcArcCorrelation(struct BArcIterator *iter, int start, int end, float v0[3], float n[3]); + +int nextFixedSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); +int nextLengthSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); +int nextCorrelationSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); + +struct EditBone * subdivideArcBy(struct bArmature *arm, ListBase *editbones, struct BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion); + +void setBoneRollFromNormal(struct EditBone *bone, float *no, float invmat[][4], float tmat[][3]); + + +#endif /* BIF_GENERATE_H */ diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index 21c57495fb0..2f463d6194b 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -28,7 +28,7 @@ #ifndef REEB_H_ #define REEB_H_ -#define WITH_BF_REEB +//#define WITH_BF_REEB #include "DNA_listBase.h" @@ -120,6 +120,8 @@ typedef struct ReebArc { } ReebArc; typedef struct ReebArcIterator { + HeadFct head; + TailFct tail; PeekFct peek; NextFct next; NextNFct nextN; @@ -151,9 +153,9 @@ void renormalizeWeight(struct EditMesh *em, float newmax); ReebGraph * generateReebGraph(struct EditMesh *me, int subdivisions); ReebGraph * newReebGraph(); -void initArcIterator(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head); -void initArcIterator2(struct ReebArcIterator *iter, struct ReebArc *arc, int start, int end); -void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start); +void initArcIterator(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head); +void initArcIterator2(BArcIterator *iter, struct ReebArc *arc, int start, int end); +void initArcIteratorStart(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start); /* Filtering */ void filterNullReebGraph(ReebGraph *rg); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 10e8c534ab2..a5491578115 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -728,6 +728,7 @@ typedef struct Scene { /* scene->snap_flag */ #define SCE_SNAP 1 #define SCE_SNAP_ROTATE 2 +#define SCE_SNAP_PEEL_OBJECT 4 /* scene->snap_target */ #define SCE_SNAP_TARGET_CLOSEST 0 #define SCE_SNAP_TARGET_CENTER 1 diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index e652ea989d1..3dfec925474 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2294,7 +2294,7 @@ static void view3d_panel_bonesketch_spaces(short cntrl) static char joint_label[32]; uiBlock *block; uiBut *but; - int yco = 70, height = 140; + int yco = 130, height = 140; int nb_joints; /* replace with check call to sketching lib */ @@ -2382,7 +2382,9 @@ static void view3d_panel_bonesketch_spaces(short cntrl) BLI_snprintf(joint_label, 32, "%i joints", nb_joints); uiDefBut(block, LABEL, 1, joint_label, 10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, ""); + yco -= 20; + uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_DIFF, "Peel Objects", 10, yco, 200, 20, &G.scene->snap_flag, 0, 0, 0, 0, "Peel whole objects as one"); if(yco < 0) uiNewPanelHeight(block, height-yco); } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index bae6fc5a0af..4521c9a8312 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -93,6 +93,7 @@ #include "BIF_space.h" #include "BIF_toolbox.h" #include "BIF_transform.h" +#include "BIF_generate.h" #include "BDR_editobject.h" #include "BDR_drawobject.h" @@ -4655,7 +4656,8 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) EditBone *lastBone = NULL; if (G.scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; float *previous = NULL, *current = NULL; EditBone *child = NULL; EditBone *parent = NULL; @@ -4668,18 +4670,18 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) root = parent; - initArcIterator(&iter, arc, head); - iter.next(&iter); - previous = iter.p; + initArcIterator(iter, arc, head); + IT_next(iter); + previous = iter->p; - for (iter.next(&iter); - iter.stopped(&iter) == 0; - previous = iter.p, iter.next(&iter)) + for (IT_next(iter); + IT_stopped(iter) == 0; + previous = iter->p, IT_next(iter)) { float vec1[3], vec2[3]; float len1, len2; - current = iter.p; + current = iter->p; VecSubf(vec1, previous, parent->head); VecSubf(vec2, current, previous); @@ -4716,173 +4718,26 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail) return lastBone; } -float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3]) +EditBone * test_subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail) { - int len = 2 + abs(end - start); - - if (len > 2) - { - ReebArcIterator iter; - float avg_t = 0.0f; - float s_t = 0.0f; - float s_xyz = 0.0f; - - /* First pass, calculate average */ - for (initArcIterator2(&iter, arc, start, end), iter.next(&iter); - iter.stopped(&iter) == 0; - iter.next(&iter)) - { - float v[3]; - - VecSubf(v, iter.p, v0); - avg_t += Inpf(v, n); - } - - avg_t /= Inpf(n, n); - avg_t += 1.0f; /* adding start (0) and end (1) values */ - avg_t /= len; - - /* Second pass, calculate s_xyz and s_t */ - for (initArcIterator2(&iter, arc, start, end), iter.next(&iter); - iter.stopped(&iter) == 0; - iter.next(&iter)) - { - float v[3], d[3]; - float dt; - - VecSubf(v, iter.p, v0); - Projf(d, v, n); - VecSubf(v, v, d); - - dt = VecLength(d) - avg_t; - - s_t += dt * dt; - s_xyz += Inpf(v, v); - } - - /* adding start(0) and end(1) values to s_t */ - s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t); - - return s_xyz / s_t; - } - else - { - return 0; - } -} - -float calcDistance(ReebArc *arc, int start, int end, float head[3], float tail[3]) -{ - ReebArcIterator iter; - float max_dist = 0; - - /* calculate maximum distance */ - for (initArcIterator2(&iter, arc, start, end), iter.next(&iter); - iter.stopped(&iter) == 0; - iter.next(&iter)) - { - float v1[3], v2[3], c[3]; - float dist; - - VecSubf(v1, head, tail); - VecSubf(v2, iter.p, tail); - - Crossf(c, v1, v2); - - dist = Inpf(c, c) / Inpf(v1, v1); - - max_dist = dist > max_dist ? dist : max_dist; - } - - - return max_dist; -} - -EditBone * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail) -{ - ReebArcIterator iter; - float n[3]; - float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit; EditBone *lastBone = NULL; - - /* init iterator to get start and end from head */ - initArcIterator(&iter, arc, head); - - /* Calculate overall */ - VecSubf(n, arc->buckets[iter.end].p, head->p); - + if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) { - EditBone *child = NULL; - EditBone *parent = NULL; - float normal[3] = {0, 0, 0}; - float avg_normal[3]; - int total = 0; - int boneStart = iter.start; + float invmat[4][4] = { {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}}; + float tmat[3][3] = { {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}}; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; + bArmature *arm= G.obedit->data; - parent = add_editbone("Bone"); - parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - VECCOPY(parent->head, head->p); + initArcIterator(iter, arc, head); - while(iter.next(&iter)) - { - float btail[3]; - float value = 0; - - if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING) - { - VECCOPY(btail, iter.p); - } - else - { - float length; - - /* Calculate normal */ - VecSubf(n, iter.p, parent->head); - length = Normalize(n); - - total += 1; - VecAddf(normal, normal, n); - VECCOPY(avg_normal, normal); - VecMulf(avg_normal, 1.0f / total); - - VECCOPY(btail, avg_normal); - VecMulf(btail, length); - VecAddf(btail, btail, parent->head); - } - - if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE) - { - value = calcDistance(arc, boneStart, iter.index, parent->head, btail); - } - else - { - float n[3]; - - VecSubf(n, btail, parent->head); - value = calcVariance(arc, boneStart, iter.index, parent->head, n); - } - - if (value > ADAPTIVE_THRESHOLD) - { - VECCOPY(parent->tail, btail); - - child = add_editbone("Bone"); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - - parent = child; // new child is next parent - boneStart = iter.index; // start from end - - normal[0] = normal[1] = normal[2] = 0; - total = 0; - } - } - - VECCOPY(parent->tail, tail->p); - - lastBone = parent; /* set last bone in the chain */ + lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextCorrelationSubdivision); } return lastBone; @@ -4915,106 +4770,26 @@ float arcLengthRatio(ReebArc *arc) return embedLength / arcLength; } -EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) +EditBone * test_subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail) { EditBone *lastBone = NULL; if ((G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) && arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio) { - ReebArcIterator iter; - float *previous = NULL; - EditBone *child = NULL; - EditBone *parent = NULL; - float lengthLimit = G.scene->toolsettings->skgen_length_limit; - int same = 0; + float invmat[4][4] = { {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}}; + float tmat[3][3] = { {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}}; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; + bArmature *arm= G.obedit->data; - parent = add_editbone("Bone"); - parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - VECCOPY(parent->head, head->p); - - initArcIterator(&iter, arc, head); - - iter.next(&iter); + initArcIterator(iter, arc, head); - while (iter.stopped(&iter) == 0) - { - float *vec0 = NULL; - float *vec1 = iter.p; - - /* first bucket. Previous is head */ - if (previous == NULL) - { - vec0 = head->p; - } - /* Previous is a valid bucket */ - else - { - vec0 = previous; - } - - /* If lengthLimit hits the current segment */ - if (VecLenf(vec1, parent->head) > lengthLimit) - { - if (same == 0) - { - float dv[3], off[3]; - float a, b, c, f; - - /* Solve quadratic distance equation */ - VecSubf(dv, vec1, vec0); - a = Inpf(dv, dv); - - VecSubf(off, vec0, parent->head); - b = 2 * Inpf(dv, off); - - c = Inpf(off, off) - (lengthLimit * lengthLimit); - - f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a); - - //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); - - if (isnan(f) == 0 && f < 1.0f) - { - VECCOPY(parent->tail, dv); - VecMulf(parent->tail, f); - VecAddf(parent->tail, parent->tail, vec0); - } - else - { - VECCOPY(parent->tail, vec1); - } - } - else - { - float dv[3]; - - VecSubf(dv, vec1, vec0); - Normalize(dv); - - VECCOPY(parent->tail, dv); - VecMulf(parent->tail, lengthLimit); - VecAddf(parent->tail, parent->tail, parent->head); - } - - child = add_editbone("Bone"); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - - parent = child; // new child is next parent - - same = 1; // mark as same - } - else - { - previous = iter.p; - iter.next(&iter); - same = 0; // Reset same - } - } - VECCOPY(parent->tail, tail->p); - - lastBone = parent; /* set last bone in the chain */ + lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextLengthSubdivision); } return lastBone; @@ -5107,13 +4882,13 @@ void generateSkeletonFromReebGraph(ReebGraph *rg) switch(G.scene->toolsettings->skgen_subdivisions[i]) { case SKGEN_SUB_LENGTH: - lastBone = subdivideByLength(arc, head, tail); + lastBone = test_subdivideByLength(arc, head, tail); break; case SKGEN_SUB_ANGLE: lastBone = subdivideByAngle(arc, head, tail); break; case SKGEN_SUB_CORRELATION: - lastBone = subdivideByCorrelation(arc, head, tail); + lastBone = test_subdivideByCorrelation(arc, head, tail); break; } } diff --git a/source/blender/src/editarmature_generate.c b/source/blender/src/editarmature_generate.c new file mode 100644 index 00000000000..c6e77488212 --- /dev/null +++ b/source/blender/src/editarmature_generate.c @@ -0,0 +1,327 @@ +/** + * $Id: editarmature_generate.c $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 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 ***** + * editarmature.c: Interface for creating and posing armature objects + */ + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" +#include "DNA_scene_types.h" +#include "DNA_armature_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_graph.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" + +#include "BIF_editarmature.h" +#include "BIF_generate.h" + +void setBoneRollFromNormal(EditBone *bone, float *no, float invmat[][4], float tmat[][3]) +{ + if (no != NULL && !VecIsNull(no)) + { + float tangent[3], cotangent[3], normal[3]; + + VECCOPY(normal, no); + Mat3MulVecfl(tmat, normal); + + VecSubf(tangent, bone->tail, bone->head); + Crossf(cotangent, tangent, normal); + Crossf(normal, cotangent, tangent); + + Normalize(normal); + + bone->roll = rollBoneToVector(bone, normal); + } +} + +float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3]) +{ + int len = 2 + abs(end - start); + + if (len > 2) + { + float avg_t = 0.0f; + float s_t = 0.0f; + float s_xyz = 0.0f; + int i; + + /* First pass, calculate average */ + for (i = start; i <= end; i++) + { + float v[3]; + + IT_peek(iter, i); + VecSubf(v, iter->p, v0); + avg_t += Inpf(v, n); + } + + avg_t /= Inpf(n, n); + avg_t += 1.0f; /* adding start (0) and end (1) values */ + avg_t /= len; + + /* Second pass, calculate s_xyz and s_t */ + for (i = start; i <= end; i++) + { + float v[3], d[3]; + float dt; + + IT_peek(iter, i); + VecSubf(v, iter->p, v0); + Projf(d, v, n); + VecSubf(v, v, d); + + dt = VecLength(d) - avg_t; + + s_t += dt * dt; + s_xyz += Inpf(v, v); + } + + /* adding start(0) and end(1) values to s_t */ + s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t); + + return 1.0f - s_xyz / s_t; + } + else + { + return 1.0f; + } +} + +int nextFixedSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3]) +{ + static float stroke_length = 0; + static float current_length; + static char n; + float *v1, *v2; + float length_threshold; + int i; + + if (stroke_length == 0) + { + current_length = 0; + + IT_peek(iter, start); + v1 = iter->p; + + for (i = start + 1; i <= end; i++) + { + IT_peek(iter, i); + v2 = iter->p; + + stroke_length += VecLenf(v1, v2); + + v1 = v2; + } + + n = 0; + current_length = 0; + } + + n++; + + length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number; + + IT_peek(iter, start); + v1 = iter->p; + + /* < and not <= because we don't care about end, it is P_EXACT anyway */ + for (i = start + 1; i < end; i++) + { + IT_peek(iter, i); + v2 = iter->p; + + current_length += VecLenf(v1, v2); + + if (current_length >= length_threshold) + { + VECCOPY(p, v2); + return i; + } + + v1 = v2; + } + + stroke_length = 0; + + return -1; +} +int nextCorrelationSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3]) +{ + float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit; + float *start_p; + float n[3]; + int i; + + IT_peek(iter, start); + start_p = iter->p; + + for (i = start + 2; i <= end; i++) + { + /* Calculate normal */ + IT_peek(iter, i); + VecSubf(n, iter->p, head); + + if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold) + { + IT_peek(iter, i - 1); + VECCOPY(p, iter->p); + return i - 1; + } + } + + return -1; +} + +int nextLengthSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3]) +{ + float lengthLimit = G.scene->toolsettings->skgen_length_limit; + int same = 1; + int i; + + i = start + 1; + while (i <= end) + { + float *vec0; + float *vec1; + + IT_peek(iter, i - 1); + vec0 = iter->p; + + IT_peek(iter, i); + vec1 = iter->p; + + /* If lengthLimit hits the current segment */ + if (VecLenf(vec1, head) > lengthLimit) + { + if (same == 0) + { + float dv[3], off[3]; + float a, b, c, f; + + /* Solve quadratic distance equation */ + VecSubf(dv, vec1, vec0); + a = Inpf(dv, dv); + + VecSubf(off, vec0, head); + b = 2 * Inpf(dv, off); + + c = Inpf(off, off) - (lengthLimit * lengthLimit); + + f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a); + + //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); + + if (isnan(f) == 0 && f < 1.0f) + { + VECCOPY(p, dv); + VecMulf(p, f); + VecAddf(p, p, vec0); + } + else + { + VECCOPY(p, vec1); + } + } + else + { + float dv[3]; + + VecSubf(dv, vec1, vec0); + Normalize(dv); + + VECCOPY(p, dv); + VecMulf(p, lengthLimit); + VecAddf(p, p, head); + } + + return i - 1; /* restart at lower bound */ + } + else + { + i++; + same = 0; // Reset same + } + } + + return -1; +} + +EditBone * subdivideArcBy(bArmature *arm, ListBase *editbones, BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion) +{ + EditBone *lastBone = NULL; + EditBone *child = NULL; + EditBone *parent = NULL; + int bone_start = 0; + int end = iter->length; + int index; + + IT_head(iter); + + parent = addEditBone("Bone", editbones, arm); + VECCOPY(parent->head, iter->p); + + index = next_subdividion(iter, bone_start, end, parent->head, parent->tail); + while (index != -1) + { + IT_peek(iter, index); + + child = addEditBone("Bone", editbones, arm); + VECCOPY(child->head, parent->tail); + child->parent = parent; + child->flag |= BONE_CONNECTED; + + /* going to next bone, fix parent */ + Mat4MulVecfl(invmat, parent->tail); + Mat4MulVecfl(invmat, parent->head); + setBoneRollFromNormal(parent, iter->no, invmat, tmat); + + parent = child; // new child is next parent + bone_start = index; // start next bone from current index + + index = next_subdividion(iter, bone_start, end, parent->head, parent->tail); + } + + iter->tail(iter); + + VECCOPY(parent->tail, iter->p); + + /* fix last bone */ + Mat4MulVecfl(invmat, parent->tail); + Mat4MulVecfl(invmat, parent->head); + setBoneRollFromNormal(parent, iter->no, invmat, tmat); + lastBone = parent; + + return lastBone; +} diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 280292abaf0..bb0fc08905c 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -1655,100 +1655,6 @@ static EditBone *add_editbonetolist(char *name, ListBase *list) return bone; } -EditBone * generateBonesForArc(RigGraph *rigg, ReebArc *arc, ReebNode *head, ReebNode *tail) -{ - ReebArcIterator iter; - float n[3]; - float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit; - EditBone *lastBone = NULL; - - /* init iterator to get start and end from head */ - initArcIterator(&iter, arc, head); - - /* Calculate overall */ - VecSubf(n, arc->buckets[iter.end].p, head->p); - - if (1 /* G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION */ ) - { - EmbedBucket *bucket = NULL; - EmbedBucket *previous = NULL; - EditBone *child = NULL; - EditBone *parent = NULL; - float normal[3] = {0, 0, 0}; - float avg_normal[3]; - int total = 0; - int boneStart = iter.start; - - parent = add_editbonetolist("Bone", rigg->editbones); - parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - VECCOPY(parent->head, head->p); - - for (previous = iter.next(&iter), bucket = iter.next(&iter); - bucket; - previous = bucket, bucket = iter.next(&iter)) - { - float btail[3]; - float value = 0; - - if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING) - { - VECCOPY(btail, bucket->p); - } - else - { - float length; - - /* Calculate normal */ - VecSubf(n, bucket->p, parent->head); - length = Normalize(n); - - total += 1; - VecAddf(normal, normal, n); - VECCOPY(avg_normal, normal); - VecMulf(avg_normal, 1.0f / total); - - VECCOPY(btail, avg_normal); - VecMulf(btail, length); - VecAddf(btail, btail, parent->head); - } - - if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE) - { - value = calcDistance(arc, boneStart, iter.index, parent->head, btail); - } - else - { - float n[3]; - - VecSubf(n, btail, parent->head); - value = calcVariance(arc, boneStart, iter.index, parent->head, n); - } - - if (value > ADAPTIVE_THRESHOLD) - { - VECCOPY(parent->tail, btail); - - child = add_editbonetolist("Bone", rigg->editbones); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; - - parent = child; // new child is next parent - boneStart = iter.index; // start from end - - normal[0] = normal[1] = normal[2] = 0; - total = 0; - } - } - - VECCOPY(parent->tail, tail->p); - - lastBone = parent; /* set last bone in the chain */ - } - - return lastBone; -} - void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit) { while (node->multi_level > multi_level_limit && node->link_up) @@ -1775,7 +1681,7 @@ void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level earc->flag = ARC_USED; - generateBonesForArc(rigg, earc, node, other); + //generateBonesForArc(rigg, earc, node, other); generateMissingArcsFromNode(rigg, other, multi_level_limit); } } @@ -2048,7 +1954,7 @@ static void printPositions(int *positions, int nb_positions) #define MAX_COST FLT_MAX /* FIX ME */ -static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i0, int i1) +static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1) { EmbedBucket *bucket = NULL; float max_dist = 0; @@ -2068,7 +1974,7 @@ static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i { float dist; - bucket = iter->peek(iter, j); + bucket = IT_peek(iter, j); VecSubf(v2, bucket->p, vec1); @@ -2128,7 +2034,7 @@ static float costLength(float original_length, float current_length) } } -static float calcCostLengthDistance(ReebArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2) +static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2) { float vec[3]; float length; @@ -2139,7 +2045,7 @@ static float calcCostLengthDistance(ReebArcIterator *iter, float **vec_cache, Ri return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2); } -static float calcCostAngleLengthDistance(ReebArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2) +static float calcCostAngleLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2) { float vec_second[3], vec_first[3]; float length2; @@ -2189,7 +2095,7 @@ static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions, } } -static MemoNode * solveJoints(MemoNode *table, ReebArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left) +static MemoNode * solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left) { MemoNode *node; int index = indexMemoNode(nb_positions, previous, current, joints_left); @@ -2277,7 +2183,8 @@ static int testFlipArc(RigArc *iarc, RigNode *inode_start) static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *inode_start) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; RigEdge *edge; EmbedBucket *bucket = NULL; ReebNode *node_start, *node_end; @@ -2332,15 +2239,15 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino positions_cache[0] = node_start->p; positions_cache[nb_positions + 1] = node_end->p; - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); for (i = 1; i <= nb_positions; i++) { - EmbedBucket *bucket = iter.peek(&iter, i); + EmbedBucket *bucket = IT_peek(iter, i); positions_cache[i] = bucket->p; } - result = solveJoints(table, &iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints); + result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints); min_cost = result->weight; copyMemoPositions(best_positions, table, earc->bcount, nb_joints); @@ -2422,7 +2329,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino } /* calculating cost */ - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); vec0 = NULL; vec1 = node_start->p; @@ -2443,13 +2350,13 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino if (i < nb_joints) { i2 = positions[i]; - bucket = iter.peek(&iter, positions[i]); + bucket = IT_peek(iter, positions[i]); vec2 = bucket->p; vec_cache[i + 1] = vec2; /* update cache for updated position */ } else { - i2 = iter.length; + i2 = iter->length; vec2 = node_end->p; } @@ -2485,7 +2392,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino new_cost += costLength(edge->length, length2); /* Distance Cost */ - new_cost += costDistance(&iter, vec1, vec2, i1, i2); + new_cost += costDistance(iter, vec1, vec2, i1, i2); cost_cache[i] = new_cost; } @@ -2518,7 +2425,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino } vec0 = node_start->p; - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); #ifndef USE_THREADS printPositions(best_positions, nb_joints); @@ -2535,7 +2442,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino float *no = NULL; if (i < nb_joints) { - bucket = iter.peek(&iter, best_positions[i]); + bucket = IT_peek(iter, best_positions[i]); vec1 = bucket->p; no = bucket->no; } @@ -2558,7 +2465,8 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_start) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; ReebArc *earc = iarc->link_mesh; ReebNode *node_start, *node_end; RigEdge *edge; @@ -2580,9 +2488,9 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ node_end = (ReebNode*)earc->tail; } - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); - bucket = iter.next(&iter); + bucket = IT_next(iter); vec0 = node_start->p; @@ -2593,15 +2501,15 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ embedding_length += VecLenf(vec0, vec1); vec0 = vec1; - bucket = iter.next(&iter); + bucket = IT_next(iter); } embedding_length += VecLenf(node_end->p, vec1); /* fit bones */ - initArcIterator(&iter, earc, node_start); + initArcIterator(iter, earc, node_start); - bucket = iter.next(&iter); + bucket = IT_next(iter); vec0 = node_start->p; previous_vec = vec0; @@ -2616,7 +2524,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_ while (bucket && new_bone_length > length) { length += VecLenf(previous_vec, vec1); - bucket = iter.next(&iter); + bucket = IT_next(iter); previous_vec = vec1; vec1 = bucket->p; no = bucket->no; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index d558445dec6..78af0a726c2 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -54,6 +54,7 @@ #include "BIF_editarmature.h" #include "BIF_sketch.h" #include "BIF_retarget.h" +#include "BIF_generate.h" #include "blendef.h" #include "mydevice.h" @@ -117,6 +118,26 @@ typedef struct SK_Sketch SK_Point next_point; } SK_Sketch; +typedef struct SK_StrokeIterator { + HeadFct head; + TailFct tail; + PeekFct peek; + NextFct next; + NextNFct nextN; + PreviousFct previous; + StoppedFct stopped; + + float *p, *no; + + int length; + int index; + /*********************************/ + SK_Stroke *stroke; + int start; + int end; + int stride; +} SK_StrokeIterator; + SK_Sketch *GLOBAL_sketch = NULL; SK_Point boneSnap; @@ -124,7 +145,7 @@ SK_Point boneSnap; /******************** PROTOTYPES ******************************/ -typedef int(NextSubdivisionFunc)(SK_Stroke*, int, int, float[3], float[3]); +void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end); void sk_deleteSelectedStrokes(SK_Sketch *sketch); @@ -133,10 +154,6 @@ void sk_freeSketch(SK_Sketch *sketch); SK_Point *sk_lastStrokePoint(SK_Stroke *stk); -int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); -int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); -int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]); - /******************** TEMPLATES UTILS *************************/ char *TEMPLATES_MENU = NULL; @@ -990,18 +1007,20 @@ void sk_drawStroke(SK_Stroke *stk, int id, float color[3]) // glEnd(); } -void drawSubdividedStrokeBy(SK_Stroke *stk, int start, int end, NextSubdivisionFunc next_subdividion) +void drawSubdividedStrokeBy(BArcIterator *iter, NextSubdivisionFunc next_subdividion) { float head[3], tail[3]; - int bone_start = start; + int bone_start = 0; + int end = iter->length; int index; - VECCOPY(head, stk->points[start].p); + iter->head(iter); + VECCOPY(head, iter->p); glColor3f(0, 1, 1); glBegin(GL_POINTS); - index = next_subdividion(stk, bone_start, end, head, tail); + index = next_subdividion(iter, bone_start, end, head, tail); while (index != -1) { glVertex3fv(tail); @@ -1009,7 +1028,7 @@ void drawSubdividedStrokeBy(SK_Stroke *stk, int start, int end, NextSubdivisionF VECCOPY(head, tail); bone_start = index; // start next bone from current index - index = next_subdividion(stk, bone_start, end, head, tail); + index = next_subdividion(iter, bone_start, end, head, tail); } glEnd(); @@ -1040,17 +1059,22 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) { if (i - head_index > 1) { + SK_StrokeIterator sk_iter; + BArcIterator *iter = (BArcIterator*)&sk_iter; + + initStrokeIterator(iter, stk, head_index, i); + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) { - drawSubdividedStrokeBy(stk, head_index, i, nextCorrelationSubdivision); + drawSubdividedStrokeBy(iter, nextCorrelationSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { - drawSubdividedStrokeBy(stk, head_index, i, nextLengthSubdivision); + drawSubdividedStrokeBy(iter, nextLengthSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { - drawSubdividedStrokeBy(stk, head_index, i, nextFixedSubdivision); + drawSubdividedStrokeBy(iter, nextFixedSubdivision); } } @@ -1354,13 +1378,29 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D float vec[3]; float new_dist; - p1->flag = 0; - - for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + p1->flag = 1; + + /* if peeling objects, take the first and last from each object */ + if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT) { - /* nothing to do here */ + SK_DepthPeel *peel; + for (peel = p1->next; peel; peel = peel->next) + { + if (peel->ob == p1->ob) + { + peel->flag = 1; + p2 = peel; + } + } + } + /* otherwise, pair first with second and so on */ + else + { + for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + { + /* nothing to do here */ + } } - if (p2) { @@ -1528,250 +1568,175 @@ void sk_initDrawData(SK_DrawData *dd) } /********************************************/ -/* bone is assumed to be in GLOBAL space */ -void setBoneRollFromPoint(EditBone *bone, SK_Point *pt, float invmat[][4], float tmat[][3]) -{ - float tangent[3], cotangent[3], normal[3]; - - VecSubf(tangent, bone->tail, bone->head); - Crossf(cotangent, tangent, pt->no); - Crossf(normal, cotangent, tangent); - - Mat3MulVecfl(tmat, normal); - Normalize(normal); - - bone->roll = rollBoneToVector(bone, normal); +static void* headPoint(void *arg); +static void* tailPoint(void *arg); +static void* nextPoint(void *arg); +static void* nextNPoint(void *arg, int n); +static void* peekPoint(void *arg, int n); +static void* previousPoint(void *arg); +static int iteratorStopped(void *arg); +static void initIteratorFct(SK_StrokeIterator *iter) +{ + iter->head = headPoint; + iter->tail = tailPoint; + iter->peek = peekPoint; + iter->next = nextPoint; + iter->nextN = nextNPoint; + iter->previous = previousPoint; + iter->stopped = iteratorStopped; } -float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], float n[3]) +static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index) { - int len = 2 + abs(end - start); + SK_Point *pt = NULL; - if (len > 2) + if (index >= 0 && index < iter->length) { - float avg_t = 0.0f; - float s_t = 0.0f; - float s_xyz = 0.0f; - int i; - - /* First pass, calculate average */ - for (i = start; i <= end; i++) - { - float v[3]; - - VecSubf(v, stk->points[i].p, v0); - avg_t += Inpf(v, n); - } - - avg_t /= Inpf(n, n); - avg_t += 1.0f; /* adding start (0) and end (1) values */ - avg_t /= len; - - /* Second pass, calculate s_xyz and s_t */ - for (i = start; i <= end; i++) - { - float v[3], d[3]; - float dt; - - VecSubf(v, stk->points[i].p, v0); - Projf(d, v, n); - VecSubf(v, v, d); - - dt = VecLength(d) - avg_t; - - s_t += dt * dt; - s_xyz += Inpf(v, v); - } - - /* adding start(0) and end(1) values to s_t */ - s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t); - - return 1.0f - s_xyz / s_t; + pt = &(iter->stroke->points[iter->start + (iter->stride * index)]); + iter->p = pt->p; + iter->no = pt->no; } else { - return 1.0f; + iter->p = NULL; + iter->no = NULL; } + + return pt; } -int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) +void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end) { - static float stroke_length = 0; - static float current_length; - static char n; - float length_threshold; - int i; + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + + initIteratorFct(iter); + iter->stroke = stk; - if (stroke_length == 0) + if (start < end) { - current_length = 0; - for (i = start + 1; i <= end; i++) - { - stroke_length += VecLenf(stk->points[i].p, stk->points[i - 1].p); - } + iter->start = start + 1; + iter->end = end - 1; + iter->stride = 1; + } + else + { + iter->start = start - 1; + iter->end = end + 1; + iter->stride = -1; + } + + iter->length = iter->stride * (iter->end - iter->start + 1); + + iter->index = -1; +} + + +static void* headPoint(void *arg) +{ + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; + + result = &(iter->stroke->points[iter->start - iter->stride]); + iter->p = result->p; + iter->no = result->no; + + return result; +} + +static void* tailPoint(void *arg) +{ + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; + + result = &(iter->stroke->points[iter->end + iter->stride]); + iter->p = result->p; + iter->no = result->no; + + return result; +} + +static void* nextPoint(void *arg) +{ + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; + + if (iter->index < iter->length) + { + iter->index++; + result = setIteratorValues(iter, iter->index); + } + + return result; +} + +static void* nextNPoint(void *arg, int n) +{ + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; - n = 0; - current_length = 0; - } - - n++; - - length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number; - - /* < and not <= because we don't care about end, it is P_EXACT anyway */ - for (i = start + 1; i < end; i++) - { - current_length += VecLenf(stk->points[i].p, stk->points[i - 1].p); + iter->index += n; - if (current_length >= length_threshold) - { - VECCOPY(p, stk->points[i].p); - return i; - } + /* check if passed end */ + if (iter->index < iter->length) + { + result = setIteratorValues(iter, iter->index); } - - stroke_length = 0; - - return -1; + else + { + /* stop iterator if passed end */ + iter->index = iter->length; + } + + return result; } -int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) + +static void* peekPoint(void *arg, int n) { - float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit; - float n[3]; - int i; - - for (i = start + 2; i <= end; i++) - { - /* Calculate normal */ - VecSubf(n, stk->points[i].p, head); + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; + int index = iter->index + n; - if (calcStrokeCorrelation(stk, start, i, stk->points[start].p, n) < correlation_threshold) - { - VECCOPY(p, stk->points[i - 1].p); - return i - 1; - } + /* check if passed end */ + if (index < iter->length) + { + result = setIteratorValues(iter, index); } - - return -1; + + return result; } -int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]) +static void* previousPoint(void *arg) { - float lengthLimit = G.scene->toolsettings->skgen_length_limit; - int same = 1; - int i; + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + SK_Point *result = NULL; - i = start + 1; - while (i <= end) + if (iter->index > 0) { - float *vec0 = stk->points[i - 1].p; - float *vec1 = stk->points[i].p; - - /* If lengthLimit hits the current segment */ - if (VecLenf(vec1, head) > lengthLimit) - { - if (same == 0) - { - float dv[3], off[3]; - float a, b, c, f; - - /* Solve quadratic distance equation */ - VecSubf(dv, vec1, vec0); - a = Inpf(dv, dv); - - VecSubf(off, vec0, head); - b = 2 * Inpf(dv, off); - - c = Inpf(off, off) - (lengthLimit * lengthLimit); - - f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a); - - //printf("a %f, b %f, c %f, f %f\n", a, b, c, f); - - if (isnan(f) == 0 && f < 1.0f) - { - VECCOPY(p, dv); - VecMulf(p, f); - VecAddf(p, p, vec0); - } - else - { - VECCOPY(p, vec1); - } - } - else - { - float dv[3]; - - VecSubf(dv, vec1, vec0); - Normalize(dv); - - VECCOPY(p, dv); - VecMulf(p, lengthLimit); - VecAddf(p, p, head); - } - - return i - 1; /* restart at lower bound */ - } - else - { - i++; - same = 0; // Reset same - } + iter->index--; + result = setIteratorValues(iter, iter->index); } - - return -1; + + return result; } -EditBone * subdivideStrokeBy(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion) +static int iteratorStopped(void *arg) { - bArmature *arm = G.obedit->data; - EditBone *lastBone = NULL; - EditBone *child = NULL; - EditBone *parent = NULL; - int bone_start = start; - int index; - - parent = addEditBone("Bone", &G.edbo, arm); - VECCOPY(parent->head, stk->points[start].p); - - index = next_subdividion(stk, bone_start, end, parent->head, parent->tail); - while (index != -1) + SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; + + if (iter->index == iter->length) { - setBoneRollFromPoint(parent, &stk->points[index], invmat, tmat); - - child = addEditBone("Bone", &G.edbo, arm); - VECCOPY(child->head, parent->tail); - child->parent = parent; - child->flag |= BONE_CONNECTED; - - /* going to next bone, fix parent */ - Mat4MulVecfl(invmat, parent->tail); - Mat4MulVecfl(invmat, parent->head); - - parent = child; // new child is next parent - bone_start = index; // start next bone from current index - - index = next_subdividion(stk, bone_start, end, parent->head, parent->tail); + return 1; + } + else + { + return 0; } - - VECCOPY(parent->tail, stk->points[end].p); - - setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat); - - /* fix last bone */ - Mat4MulVecfl(invmat, parent->tail); - Mat4MulVecfl(invmat, parent->head); - lastBone = parent; - - return lastBone; } - void sk_convertStroke(SK_Stroke *stk) { - bArmature *arm= G.obedit->data; + bArmature *arm = G.obedit->data; SK_Point *head; EditBone *parent = NULL; float invmat[4][4]; /* move in caller function */ @@ -1804,17 +1769,22 @@ void sk_convertStroke(SK_Stroke *stk) if (i - head_index > 1) { + SK_StrokeIterator sk_iter; + BArcIterator *iter = (BArcIterator*)&sk_iter; + + initStrokeIterator(iter, stk, head_index, i); + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) { - bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextCorrelationSubdivision); + bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextCorrelationSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { - bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextLengthSubdivision); + bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextLengthSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { - bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextFixedSubdivision); + bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextFixedSubdivision); } } @@ -1824,10 +1794,10 @@ void sk_convertStroke(SK_Stroke *stk) VECCOPY(bone->head, head->p); VECCOPY(bone->tail, pt->p); - setBoneRollFromPoint(bone, pt, invmat, tmat); - + Mat4MulVecfl(invmat, bone->head); Mat4MulVecfl(invmat, bone->tail); + setBoneRollFromNormal(bone, pt->no, invmat, tmat); } new_parent = bone; @@ -1995,6 +1965,9 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) { + SK_StrokeIterator sk_iter; + BArcIterator *iter = (BArcIterator*)&sk_iter; + float CORRELATION_THRESHOLD = 0.99f; float *vec; int i, j; @@ -2002,6 +1975,8 @@ int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) sk_appendStrokePoint(segments, &gesture->points[0]); vec = segments->points[segments->nb_points - 1].p; + initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1); + for (i = 1, j = 0; i < gesture->nb_points; i++) { float n[3]; @@ -2009,7 +1984,7 @@ int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) /* Calculate normal */ VecSubf(n, gesture->points[i].p, vec); - if (calcStrokeCorrelation(gesture, j, i, vec, n) < CORRELATION_THRESHOLD) + if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD) { j = i - 1; sk_appendStrokePoint(segments, &gesture->points[j]); diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index bb53269bf12..553a758c9d5 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -850,7 +850,8 @@ void fillArcEmptyBuckets(ReebArc *arc) static void ExtendArcBuckets(ReebArc *arc) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; EmbedBucket *last_bucket, *first_bucket; float *previous = NULL; float average_length = 0, length; @@ -861,16 +862,16 @@ static void ExtendArcBuckets(ReebArc *arc) return; /* failsafe, shouldn't happen */ } - initArcIterator(&iter, arc, arc->head); - iter.next(&iter); - previous = iter.p; + initArcIterator(iter, arc, arc->head); + IT_next(iter); + previous = iter->p; - for ( iter.next(&iter); - iter.stopped(&iter) == 0; - previous = iter.p, iter.next(&iter) + for ( IT_next(iter); + IT_stopped(iter) == 0; + previous = iter->p, IT_next(iter) ) { - average_length += VecLenf(previous, iter.p); + average_length += VecLenf(previous, iter->p); } average_length /= (arc->bcount - 1); @@ -927,19 +928,20 @@ void extendGraphBuckets(ReebGraph *rg) void calculateArcLength(ReebArc *arc) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; float *vec0, *vec1; arc->length = 0; - initArcIterator(&iter, arc, arc->head); + initArcIterator(iter, arc, arc->head); vec0 = arc->head->p; vec1 = arc->head->p; /* in case there's no embedding */ - while (iter.next(&iter)) + while (IT_next(iter)) { - vec1 = iter.p; + vec1 = iter->p; arc->length += VecLenf(vec0, vec1); @@ -996,28 +998,30 @@ void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count) * */ if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator iter1, iter2; + ReebArcIterator arc_iter1, arc_iter2; + BArcIterator *iter1 = (BArcIterator*)&arc_iter1; + BArcIterator *iter2 = (BArcIterator*)&arc_iter2; EmbedBucket *bucket1 = NULL, *bucket2 = NULL; - initArcIterator(&iter1, arc1, (ReebNode*)root_node); - initArcIterator(&iter2, arc2, (ReebNode*)root_node); + initArcIterator(iter1, arc1, (ReebNode*)root_node); + initArcIterator(iter2, arc2, (ReebNode*)root_node); - bucket1 = iter1.next(&iter1); - bucket2 = iter2.next(&iter2); + bucket1 = IT_next(iter1); + bucket2 = IT_next(iter2); /* Make sure they both start at the same value */ while(bucket1 && bucket2 && bucket1->val < bucket2->val) { - bucket1 = iter1.next(&iter1); + bucket1 = IT_next(iter1); } while(bucket1 && bucket2 && bucket2->val < bucket1->val) { - bucket2 = iter2.next(&iter2); + bucket2 = IT_next(iter2); } - for ( ;bucket1 && bucket2; bucket1 = iter1.next(&iter1), bucket2 = iter2.next(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { bucket2->nv += bucket1->nv; /* add counts */ @@ -1056,28 +1060,30 @@ void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count) * */ if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator iter1, iter2; + ReebArcIterator arc_iter1, arc_iter2; + BArcIterator *iter1 = (BArcIterator*)&arc_iter1; + BArcIterator *iter2 = (BArcIterator*)&arc_iter2; EmbedBucket *bucket1 = NULL, *bucket2 = NULL; - initArcIterator(&iter1, arc1, node); - initArcIterator(&iter2, arc2, node); + initArcIterator(iter1, arc1, node); + initArcIterator(iter2, arc2, node); - bucket1 = iter1.next(&iter1); - bucket2 = iter2.next(&iter2); + bucket1 = IT_next(iter1); + bucket2 = IT_next(iter2); /* Make sure they both start at the same value */ while(bucket1 && bucket1->val < bucket2->val) { - bucket1 = iter1.next(&iter1); + bucket1 = IT_next(iter1); } while(bucket2 && bucket2->val < bucket1->val) { - bucket2 = iter2.next(&iter2); + bucket2 = IT_next(iter2); } - for ( ;bucket1 && bucket2; bucket1 = iter1.next(&iter1), bucket2 = iter1.next(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { /* copy and mirror back to bucket2 */ bucket2->nv = bucket1->nv; @@ -1115,28 +1121,30 @@ void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BAr * */ if (arc1->bcount > 0 && arc2->bcount > 0) { - ReebArcIterator iter1, iter2; + ReebArcIterator arc_iter1, arc_iter2; + BArcIterator *iter1 = (BArcIterator*)&arc_iter1; + BArcIterator *iter2 = (BArcIterator*)&arc_iter2; EmbedBucket *bucket1 = NULL, *bucket2 = NULL; - initArcIterator(&iter1, arc1, (ReebNode*)root_node); - initArcIterator(&iter2, arc2, (ReebNode*)root_node); + initArcIterator(iter1, arc1, (ReebNode*)root_node); + initArcIterator(iter2, arc2, (ReebNode*)root_node); - bucket1 = iter1.next(&iter1); - bucket2 = iter2.next(&iter2); + bucket1 = IT_next(iter1); + bucket2 = IT_next(iter2); /* Make sure they both start at the same value */ while(bucket1 && bucket1->val < bucket2->val) { - bucket1 = iter1.next(&iter1); + bucket1 = IT_next(iter1); } while(bucket2 && bucket2->val < bucket1->val) { - bucket2 = iter1.next(&iter2); + bucket2 = IT_next(iter2); } - for ( ;bucket1 && bucket2; bucket1 = iter2.next(&iter1), bucket2 = iter2.next(&iter2)) + for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { bucket1->nv += bucket2->nv; /* add counts */ @@ -1763,15 +1771,16 @@ int filterSmartReebGraph(ReebGraph *rg, float threshold) EditFace *efa = BLI_ghashIterator_getValue(&ghi); #if 0 - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; EmbedBucket *bucket = NULL; EmbedBucket *previous = NULL; float min_distance = -1; float angle = 0; - initArcIterator(&iter, arc, arc->head); + initArcIterator(iter, arc, arc->head); - bucket = nextBucket(&iter); + bucket = nextBucket(iter); while (bucket != NULL) { @@ -1806,7 +1815,7 @@ int filterSmartReebGraph(ReebGraph *rg, float threshold) } previous = bucket; - bucket = nextBucket(&iter); + bucket = nextBucket(iter); } avg_angle += saacos(fabs(angle)); @@ -3296,14 +3305,18 @@ void arcToVCol(ReebGraph *rg, EditMesh *em, int index) /****************************************** BUCKET ITERATOR **************************************************/ -void* nextBucket(void *arg); -void* nextNBucket(void *arg, int n); -void* peekBucket(void *arg, int n); -void* previousBucket(void *arg); -int iteratorStopped(void *arg); +static void* headNode(void *arg); +static void* tailNode(void *arg); +static void* nextBucket(void *arg); +static void* nextNBucket(void *arg, int n); +static void* peekBucket(void *arg, int n); +static void* previousBucket(void *arg); +static int iteratorStopped(void *arg); -void initIteratorFct(ReebArcIterator *iter) +static void initIteratorFct(ReebArcIterator *iter) { + iter->head = headNode; + iter->tail = tailNode; iter->peek = peekBucket; iter->next = nextBucket; iter->nextN = nextNBucket; @@ -3311,7 +3324,7 @@ void initIteratorFct(ReebArcIterator *iter) iter->stopped = iteratorStopped; } -void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) +static void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) { if (bucket) { @@ -3325,8 +3338,10 @@ void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) } } -void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head) +void initArcIterator(BArcIterator *arg, ReebArc *arc, ReebNode *head) { + ReebArcIterator *iter = (ReebArcIterator*)arg; + initIteratorFct(iter); iter->arc = arc; @@ -3345,11 +3360,13 @@ void initArcIterator(ReebArcIterator *iter, ReebArc *arc, ReebNode *head) iter->length = arc->bcount; - iter->index = iter->start - iter->stride; + iter->index = -1; } -void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start) +void initArcIteratorStart(BArcIterator *arg, struct ReebArc *arc, struct ReebNode *head, int start) { + ReebArcIterator *iter = (ReebArcIterator*)arg; + initIteratorFct(iter); iter->arc = arc; @@ -3366,7 +3383,7 @@ void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, str iter->stride = -1; } - iter->index = iter->start - iter->stride; + iter->index = -1; iter->length = arc->bcount - start; @@ -3376,8 +3393,10 @@ void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, str } } -void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end) +void initArcIterator2(BArcIterator *arg, ReebArc *arc, int start, int end) { + ReebArcIterator *iter = (ReebArcIterator*)arg; + initIteratorFct(iter); iter->arc = arc; @@ -3393,86 +3412,124 @@ void initArcIterator2(ReebArcIterator *iter, ReebArc *arc, int start, int end) iter->stride = -1; } - iter->index = iter->start - iter->stride; + iter->index = -1; iter->length = abs(iter->end - iter->start) + 1; } -void* nextBucket(void *arg) +static void* headNode(void *arg) +{ + ReebArcIterator *iter = (ReebArcIterator*)arg; + ReebNode *node; + + if (iter->start < iter->end) + { + node = iter->arc->head; + } + else + { + node = iter->arc->tail; + } + + iter->p = node->p; + iter->no = node->no; + + return node; +} + +static void* tailNode(void *arg) +{ + ReebArcIterator *iter = (ReebArcIterator*)arg; + ReebNode *node; + + if (iter->start < iter->end) + { + node = iter->arc->tail; + } + else + { + node = iter->arc->head; + } + + iter->p = node->p; + iter->no = node->no; + + return node; +} + +static void* nextBucket(void *arg) { ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - if (iter->index != iter->end) + if (iter->index < iter->length) { - iter->index += iter->stride; - result = &(iter->arc->buckets[iter->index]); + iter->index++; + result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); } setIteratorValues(iter, result); return result; } -void* nextNBucket(void *arg, int n) +static void* nextNBucket(void *arg, int n) { ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - iter->index += n * iter->stride; + iter->index += n; /* check if passed end */ - if ((iter->stride == 1 && iter->index <= iter->end) || - (iter->stride == -1 && iter->index >= iter->end)) + if (iter->index < iter->length) { - result = &(iter->arc->buckets[iter->index]); + result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); } else { /* stop iterator if passed end */ - iter->index = iter->end; + iter->index = iter->length; } setIteratorValues(iter, result); return result; } -void* peekBucket(void *arg, int n) +static void* peekBucket(void *arg, int n) { ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - int index = iter->index + n * iter->stride; + int index = iter->index + n; /* check if passed end */ - if ((iter->stride == 1 && index <= iter->end && index >= iter->start) || - (iter->stride == -1 && index >= iter->end && index <= iter->start)) + if (index < iter->length) { - result = &(iter->arc->buckets[index]); + result = &(iter->arc->buckets[iter->start + (iter->stride * index)]); } setIteratorValues(iter, result); return result; } -void* previousBucket(void *arg) +static void* previousBucket(void *arg) { ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; - if (iter->index != iter->start) + if (iter->index > 0) { - iter->index -= iter->stride; - result = &(iter->arc->buckets[iter->index]); + iter->index--; + result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); } setIteratorValues(iter, result); return result; } -int iteratorStopped(void *arg) +static int iteratorStopped(void *arg) { ReebArcIterator *iter = (ReebArcIterator*)arg; - if (iter->index == iter->end) + if (iter->index == iter->length) { return 1; } @@ -3711,7 +3768,8 @@ void REEB_draw() glDisable(GL_DEPTH_TEST); for (arc = rg->arcs.first; arc; arc = arc->next, i++) { - ReebArcIterator iter; + ReebArcIterator arc_iter; + BArcIterator *iter = (BArcIterator*)&arc_iter; float vec[3]; char text[128]; char *s = text; @@ -3723,10 +3781,10 @@ void REEB_draw() if (arc->bcount) { - initArcIterator(&iter, arc, arc->head); - for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) + initArcIterator(iter, arc, arc->head); + for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter)) { - glVertex3fv(iter.p); + glVertex3fv(iter->p); } } @@ -3756,10 +3814,10 @@ void REEB_draw() if (arc->bcount) { - initArcIterator(&iter, arc, arc->head); - for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) + initArcIterator(iter, arc, arc->head); + for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter)) { - glVertex3fv(iter.p); + glVertex3fv(iter->p); } } @@ -3777,10 +3835,10 @@ void REEB_draw() glColor3f(0.5f, 0.5f, 1); if (arc->bcount) { - initArcIterator(&iter, arc, arc->head); - for (iter.next(&iter); iter.stopped(&iter) == 0; iter.next(&iter)) + initArcIterator(iter, arc, arc->head); + for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter)) { - glVertex3fv(iter.p); + glVertex3fv(iter->p); } } glEnd(); From 28786f55e6daf24e82efea2996eba67bd03e7c9d Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 2 Dec 2008 21:29:31 +0000 Subject: [PATCH 060/252] Retarget bug: missing angle cost on last bone. --- source/blender/src/editarmature_retarget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index bb0fc08905c..0d83ee846a0 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -2108,10 +2108,11 @@ static MemoNode * solveJoints(MemoNode *table, BArcIterator *iter, float **vec_c } else if (joints_left == 0) { + float *vec0 = vec_cache[previous]; float *vec1 = vec_cache[current]; float *vec2 = vec_cache[nb_positions + 1]; - node->weight = calcCostLengthDistance(iter, vec_cache, edge, vec1, vec2, current, iter->length); + node->weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, iter->length); return node; } From 93efabc0d9450b21071265c6d05f106656345ee5 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 9 Dec 2008 00:46:05 +0000 Subject: [PATCH 061/252] Off by one error at the end of reeb and sketch iterators causing despair and dismay. --- source/blender/src/editarmature_sketch.c | 9 ++------- source/blender/src/reeb.c | 10 +++------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 78af0a726c2..7027d899ddf 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1661,9 +1661,9 @@ static void* nextPoint(void *arg) SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; SK_Point *result = NULL; + iter->index++; if (iter->index < iter->length) { - iter->index++; result = setIteratorValues(iter, iter->index); } @@ -1682,11 +1682,6 @@ static void* nextNPoint(void *arg, int n) { result = setIteratorValues(iter, iter->index); } - else - { - /* stop iterator if passed end */ - iter->index = iter->length; - } return result; } @@ -1724,7 +1719,7 @@ static int iteratorStopped(void *arg) { SK_StrokeIterator *iter = (SK_StrokeIterator*)arg; - if (iter->index == iter->length) + if (iter->index >= iter->length) { return 1; } diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index 553a758c9d5..51dfa9e2405 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -3462,9 +3462,10 @@ static void* nextBucket(void *arg) ReebArcIterator *iter = (ReebArcIterator*)arg; EmbedBucket *result = NULL; + iter->index++; + if (iter->index < iter->length) { - iter->index++; result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); } @@ -3484,11 +3485,6 @@ static void* nextNBucket(void *arg, int n) { result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]); } - else - { - /* stop iterator if passed end */ - iter->index = iter->length; - } setIteratorValues(iter, result); return result; @@ -3529,7 +3525,7 @@ static int iteratorStopped(void *arg) { ReebArcIterator *iter = (ReebArcIterator*)arg; - if (iter->index == iter->length) + if (iter->index >= iter->length) { return 1; } From 2b9a6251d173522b3bdb561edeb9aceb2178639f Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 9 Dec 2008 20:46:25 +0000 Subject: [PATCH 062/252] Reeb graph filtering Add exception to normal nodes preservation when that node is the root node. In that case, pruning the arc is A-OK and in fact needed. --- source/blender/src/reeb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/src/reeb.c b/source/blender/src/reeb.c index 51dfa9e2405..67cfce55907 100644 --- a/source/blender/src/reeb.c +++ b/source/blender/src/reeb.c @@ -1662,10 +1662,11 @@ int filterInternalExternalReebGraph(ReebGraph *rg, float threshold_internal, flo middleNode = arc->head; } - if (middleNode->degree == 2) + if (middleNode->degree == 2 && middleNode != rg->nodes.first) { #if 1 // If middle node is a normal node, it will be removed later + // Only if middle node is not the root node /* USE THIS IF YOU WANT TO PROLONG ARCS TO THEIR TERMINAL NODES * FOR HANDS, THIS IS NOT THE BEST RESULT * */ From 6651af413dc4c510b0e5dea4fceb276b332577ba Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 9 Dec 2008 21:25:30 +0000 Subject: [PATCH 063/252] When not using quick mode, automatically select the last drawn stroke. --- source/blender/src/editarmature_sketch.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 7027d899ddf..6d99e963183 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -2562,6 +2562,11 @@ int sk_paint(SK_Sketch *sketch, short mbut) sk_removeStroke(sketch, stk); allqueue(REDRAWBUTSEDIT, 0); } + else + { + sk_selectAllSketch(sketch, -1); + stk->selected = 1; + } allqueue(REDRAWVIEW3D, 0); } From c794e13ba33f0bbc0d985489fa33777d845bd3a8 Mon Sep 17 00:00:00 2001 From: Remigiusz Fiedler Date: Sun, 14 Dec 2008 18:39:58 +0000 Subject: [PATCH 064/252] bugfix in pickMeshRayFaceWeight() in bpymodules/BPyMesh.py --- release/scripts/bpymodules/BPyMesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/bpymodules/BPyMesh.py b/release/scripts/bpymodules/BPyMesh.py index 415c2a12c69..6bbfaa463d0 100644 --- a/release/scripts/bpymodules/BPyMesh.py +++ b/release/scripts/bpymodules/BPyMesh.py @@ -479,7 +479,7 @@ def pickMeshRayFaceWeight(me, orig, rdir): w0 = (l1+l2) w1 = (l0+l2) - w2 = (l1+l2) + w2 = (l1+l0) totw= w0 + w1 + w2 w0=w0/totw From e7c0666d9678b76e03ffe773bb9c2fc4b86f0a79 Mon Sep 17 00:00:00 2001 From: Remigiusz Fiedler Date: Sun, 14 Dec 2008 21:26:24 +0000 Subject: [PATCH 065/252] DXF exporter, dxf-library.py updated v1.28 - 2008.12.13 by Steeve/BlenderArtists - bugfix for EXTMIN/EXTMAX to suit Cycas-CAD --- release/scripts/bpymodules/dxfLibrary.py | 111 ++++++++++++----------- 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/release/scripts/bpymodules/dxfLibrary.py b/release/scripts/bpymodules/dxfLibrary.py index 5c63e7f5bf5..96caa50cc41 100644 --- a/release/scripts/bpymodules/dxfLibrary.py +++ b/release/scripts/bpymodules/dxfLibrary.py @@ -1,10 +1,10 @@ #dxfLibrary.py : provides functions for generating DXF files # -------------------------------------------------------------------------- -__version__ = "v1.27beta - 2008.10.05" -__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)" +__version__ = "v1.28beta - 2008.12.13" +__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)" __license__ = "GPL" -__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf" -__bpydoc__ ="""The script exports geometry data to DXF format r12 version. +__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf" +__bpydoc__ ="""The library to export geometry data to DXF format r12 version. Copyright %s Version %s @@ -12,15 +12,17 @@ License %s Homepage %s See the homepage for documentation. -url: +Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439 IDEAs: - - + TODO: -- +- add support for SPLINEs History +v1.28 - 2008.12.13 by Steeve/BlenderArtists +- bugfix for EXTMIN/EXTMAX to suit Cycas-CAD v1.27 - 2008.10.07 by migius - beautifying output code: keys whitespace prefix - refactoring DXF-strings format: NewLine moved to the end of @@ -154,56 +156,56 @@ BYBLOCK=0 BYLAYER=256 #---block-type flags (bit coded values, may be combined): -ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application +ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all) -XREF =4 # This block is an external reference (xref) -XREF_OVERLAY =8 # This block is an xref overlay -EXTERNAL =16 # This block is externally dependent -RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input) -REFERENCED =64 # This definition is a referenced external reference (ignored on input) +XREF =4 # This block is an external reference (xref) +XREF_OVERLAY =8 # This block is an xref overlay +EXTERNAL =16 # This block is externally dependent +RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input) +REFERENCED =64 # This definition is a referenced external reference (ignored on input) #---mtext flags #attachment point -TOP_LEFT = 1 -TOP_CENTER = 2 -TOP_RIGHT = 3 -MIDDLE_LEFT = 4 -MIDDLE_CENTER = 5 +TOP_LEFT = 1 +TOP_CENTER = 2 +TOP_RIGHT = 3 +MIDDLE_LEFT = 4 +MIDDLE_CENTER = 5 MIDDLE_RIGHT = 6 -BOTTOM_LEFT = 7 -BOTTOM_CENTER = 8 -BOTTOM_RIGHT = 9 +BOTTOM_LEFT = 7 +BOTTOM_CENTER = 8 +BOTTOM_RIGHT = 9 #drawing direction -LEFT_RIGHT = 1 -TOP_BOTTOM = 3 -BY_STYLE = 5 #the flow direction is inherited from the associated text style +LEFT_RIGHT = 1 +TOP_BOTTOM = 3 +BY_STYLE = 5 #the flow direction is inherited from the associated text style #line spacing style (optional): -AT_LEAST = 1 #taller characters will override -EXACT = 2 #taller characters will not override +AT_LEAST = 1 #taller characters will override +EXACT = 2 #taller characters will not override #---polyline flags -CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction) -CURVE_FIT =2 # Curve-fit vertices have been added -SPLINE_FIT =4 # Spline-fit vertices have been added -POLYLINE_3D =8 # This is a 3D polyline -POLYGON_MESH =16 # This is a 3D polygon mesh -CLOSED_N =32 # The polygon mesh is closed in the N direction -POLYFACE_MESH =64 # The polyline is a polyface mesh -CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline +CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction) +CURVE_FIT =2 # Curve-fit vertices have been added +SPLINE_FIT =4 # Spline-fit vertices have been added +POLYLINE_3D =8 # This is a 3D polyline +POLYGON_MESH =16 # This is a 3D polygon mesh +CLOSED_N =32 # The polygon mesh is closed in the N direction +POLYFACE_MESH =64 # The polyline is a polyface mesh +CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline #---text flags #horizontal -LEFT = 0 -CENTER = 1 -RIGHT = 2 -ALIGNED = 3 #if vertical alignment = 0 -MIDDLE = 4 #if vertical alignment = 0 -FIT = 5 #if vertical alignment = 0 +LEFT = 0 +CENTER = 1 +RIGHT = 2 +ALIGNED = 3 #if vertical alignment = 0 +MIDDLE = 4 #if vertical alignment = 0 +FIT = 5 #if vertical alignment = 0 #vertical -BASELINE = 0 -BOTTOM = 1 -MIDDLE = 2 -TOP = 3 +BASELINE = 0 +BOTTOM = 1 +MIDDLE = 2 +TOP = 3 ####3) Classes #---entitities ----------------------------------------------- @@ -239,7 +241,7 @@ class Face(_Entity): """3dface""" def __init__(self,points,**common): _Entity.__init__(self,**common) - if len(points)<4: #fix for r12 format + while len(points)<4: #fix for r12 format points.append(points[-1]) self.points=points @@ -336,10 +338,14 @@ class PolyLine(_Entity): #----------------------------------------------- class Point(_Entity): - """Colored solid fill.""" + """Point.""" def __init__(self,points=None,**common): _Entity.__init__(self,**common) self.points=points + def __str__(self): #TODO: + return ' 0\nPOINT\n%s%s\n' %(self._common(), + _points(self.points) + ) #----------------------------------------------- class Solid(_Entity): @@ -468,7 +474,7 @@ class Block(_Collection): self.name=name self.flag=0 self.base=base - def __str__(self): + def __str__(self): #TODO: e=''.join([str(x)for x in self.entities]) return ' 0\nBLOCK\n 8\n%s\n 2\n%s\n 70\n%s\n%s\n 3\n%s\n%s 0\nENDBLK\n'%\ (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e) @@ -552,11 +558,12 @@ def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options): #----------------------------------------------- class Drawing(_Collection): """Dxf drawing. Use append or any other list methods to add objects.""" - def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0),extmax=(0.0,0.0), + def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0), layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[], views=[],entities=None,fileName='test.dxf'): # TODO: replace list with None,arial - if not entities:entities=[] + if not entities: + entities=[] _Collection.__init__(self,entities) self.insbase=insbase self.extmin=extmin @@ -680,9 +687,9 @@ def test(): #Drawing d=Drawing() #tables - d.blocks.append(b) #table blocks - d.styles.append(Style()) #table styles - d.views.append(View('Normal')) #table view + d.blocks.append(b) #table blocks + d.styles.append(Style()) #table styles + d.views.append(View('Normal')) #table view d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem #entities From ba6972eb4db3f4b1cf5e2f6132efab90d9357a9b Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Mon, 15 Dec 2008 05:30:09 +0000 Subject: [PATCH 066/252] Python API ---------- Bugfix #18044: missing return statements in getter for displacement modifier caused incorrect values to be returned. --- source/blender/python/api2_2x/Modifier.c | 6 +++--- source/blender/python/api2_2x/doc/Modifier.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/python/api2_2x/Modifier.c b/source/blender/python/api2_2x/Modifier.c index 3bef0eead09..dde21b13722 100644 --- a/source/blender/python/api2_2x/Modifier.c +++ b/source/blender/python/api2_2x/Modifier.c @@ -909,18 +909,18 @@ static PyObject *displace_getter( BPy_Modifier * self, int type ) switch( type ) { case EXPP_MOD_TEXTURE: - if (md->texture) Texture_CreatePyObject( md->texture ); + if (md->texture) return Texture_CreatePyObject( md->texture ); else Py_RETURN_NONE; case EXPP_MOD_STRENGTH: return PyFloat_FromDouble( (double)md->strength ); case EXPP_MOD_DIRECTION: - PyInt_FromLong( md->direction ); + return PyInt_FromLong( md->direction ); case EXPP_MOD_VERTGROUP: return PyString_FromString( md->defgrp_name ) ; case EXPP_MOD_MID_LEVEL: return PyFloat_FromDouble( (double)md->midlevel ); case EXPP_MOD_MAPPING: - PyInt_FromLong( md->texmapping ); + return PyInt_FromLong( md->texmapping ); case EXPP_MOD_OBJECT: return Object_CreatePyObject( md->map_object ); case EXPP_MOD_UVLAYER: diff --git a/source/blender/python/api2_2x/doc/Modifier.py b/source/blender/python/api2_2x/doc/Modifier.py index 47f72e566b2..03b868d3605 100644 --- a/source/blender/python/api2_2x/doc/Modifier.py +++ b/source/blender/python/api2_2x/doc/Modifier.py @@ -129,7 +129,7 @@ Example:: - UVLAYER - Used for Displace only - MID_LEVEL - Used for Displace only (float [0.0, 1.0], default: 0.5) - STRENGTH - Used for Displace only (float [-1000.0, 1000.0, default: 1.0) - - TEXTURE - Used for Displace only (string) + - TEXTURE - Used for Displace only (Texture object) - MAPPING - Used for Displace only - DIRECTION - Used for Displace only From d99686a783ca65cb29792396c70182c3330813c3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 15 Dec 2008 08:29:31 +0000 Subject: [PATCH 067/252] Touch/NoOverwrite options were not disabled for video. --- .../blender/render/intern/source/pipeline.c | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 1dfcbc6e45d..9ef9c2f3859 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2616,17 +2616,20 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) else nfra+= tfra; - if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { - BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); - } - - if (scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { - printf("skipping existing frame \"%s\"\n", name); - continue; - } - if (scene->r.mode & R_TOUCH && !BLI_exist(name)) { - BLI_make_existing_file(name); /* makes the dir if its not there */ - BLI_touch(name); + /* Touch/NoOverwrite options are only valid for image's */ + if(BKE_imtype_is_movie(scene->r.imtype) == 0) { + if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); + } + + if (scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { + printf("skipping existing frame \"%s\"\n", name); + continue; + } + if (scene->r.mode & R_TOUCH && !BLI_exist(name)) { + BLI_make_existing_file(name); /* makes the dir if its not there */ + BLI_touch(name); + } } re->r.cfra= scene->r.cfra; /* weak.... */ @@ -2639,8 +2642,10 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) if(G.afbreek==1) { /* remove touched file */ - if (scene->r.mode & R_TOUCH && BLI_exist(name) && BLI_filepathsize(name) == 0) { - BLI_delete(name, 0, 0); + if(BKE_imtype_is_movie(scene->r.imtype) == 0) { + if (scene->r.mode & R_TOUCH && BLI_exist(name) && BLI_filepathsize(name) == 0) { + BLI_delete(name, 0, 0); + } } break; From 4d21036829e93481b4b65b6d716205dda07314a2 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 15 Dec 2008 08:37:39 +0000 Subject: [PATCH 068/252] bugfix #17989 Patch from Xavier Thomas. Compositor, filter node, had shifted output when used on single-value buffers. --- source/blender/nodes/intern/CMP_nodes/CMP_filter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_filter.c b/source/blender/nodes/intern/CMP_nodes/CMP_filter.c index 46a9d747ac1..6011ac3b58a 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_filter.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_filter.c @@ -78,6 +78,7 @@ static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac) QUATCOPY(fp, row2+4); } else if(pix==CB_VAL) { + fp+= pix; for(x=2; x Date: Mon, 15 Dec 2008 17:47:57 +0000 Subject: [PATCH 069/252] Make sure that WITH_OPENEXR is defined when sources are configured with OpenEXR in the CMake system. This is a compilation fix from Miguel A. Figueroa Villanueva for building Debug versions of Blender using OpenEXR (thanks!). --- source/blender/imbuf/intern/openexr/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/imbuf/intern/openexr/CMakeLists.txt b/source/blender/imbuf/intern/openexr/CMakeLists.txt index bb1dad087f3..21792086774 100644 --- a/source/blender/imbuf/intern/openexr/CMakeLists.txt +++ b/source/blender/imbuf/intern/openexr/CMakeLists.txt @@ -38,5 +38,9 @@ SET(INC ${OPENEXR_INC} ) +IF(WITH_OPENEXR) + ADD_DEFINITIONS(-DWITH_OPENEXR) +ENDIF(WITH_OPENEXR) + BLENDERLIB(bf_openexr "${SRC}" "${INC}") #env.BlenderLib ('bf_openexr', source_files, incs, defs, libtype=['core','player'], priority = [90, 200]) From 024b4b3dda2c6e4acb3fb111fdee4de82215d6ea Mon Sep 17 00:00:00 2001 From: Chris Want Date: Mon, 15 Dec 2008 20:53:45 +0000 Subject: [PATCH 070/252] B Linking of blenderplayer was failing with unresolved symbols (initVideoTexture) when building without FFMPEG. Needs testing with SCons and Makefiles. --- source/gameengine/GamePlayer/ghost/CMakeLists.txt | 4 ++++ source/gameengine/GamePlayer/ghost/GPG_Application.cpp | 3 ++- source/gameengine/GamePlayer/ghost/Makefile | 3 +++ source/gameengine/GamePlayer/ghost/SConscript | 2 ++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index 5e0ca93ac06..a3cd8296da3 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -70,5 +70,9 @@ SET(INC ${PYTHON_INC} ) +IF(WITH_FFMPEG) + ADD_DEFINITIONS(-DWITH_FFMPEG) +ENDIF(WITH_FFMPEG) + BLENDERLIB_NOLIST(gp_ghost "${SRC}" "${INC}") #env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index aa5e5835cdc..d0a2d0b05f2 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -686,8 +686,9 @@ bool GPG_Application::startEngine(void) initGameKeys(); initPythonConstraintBinding(); initMathutils(); +#ifdef WITH_FFMPEG initVideoTexture(); - +#endif // 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); diff --git a/source/gameengine/GamePlayer/ghost/Makefile b/source/gameengine/GamePlayer/ghost/Makefile index 52e219db8f2..5f90d804611 100644 --- a/source/gameengine/GamePlayer/ghost/Makefile +++ b/source/gameengine/GamePlayer/ghost/Makefile @@ -82,3 +82,6 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_GHOST)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +ifeq ($(WITH_FFMPEG), true) + CPPFLAGS += -DWITH_FFMPEG +endif diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 33cf07b6211..c1559f6e1fc 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -49,5 +49,7 @@ cflags = [] if env['OURPLATFORM']=='win32-vc': cflags = ['/GR'] +if env['WITH_BF_FFMPEG']: + defs += ' WITH_FFMPEG' env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags) From 4da3c4b9d5ede4369467165cb9f31eee4385a353 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 16 Dec 2008 11:26:55 +0000 Subject: [PATCH 071/252] fix for [bf-blender-Bug Tracker][18089] scons compiling bug and removed unused vars --- source/blender/python/api2_2x/Sys.c | 3 --- source/gameengine/GamePlayer/ghost/SConscript | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/source/blender/python/api2_2x/Sys.c b/source/blender/python/api2_2x/Sys.c index c438d2c6e54..936014d87ed 100644 --- a/source/blender/python/api2_2x/Sys.c +++ b/source/blender/python/api2_2x/Sys.c @@ -427,9 +427,6 @@ static PyObject *M_sys_relpath( PyObject * self, PyObject * args ) char *path; char relpath[FILE_MAXDIR + FILE_MAXFILE]; - char dir[FILE_MAXDIR]; - char file[FILE_MAXFILE]; - if( !PyArg_ParseTuple( args, "s|s:Blender.sys.relpath", &path, &base ) ) return NULL; diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index c1559f6e1fc..4f1324b3938 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -49,7 +49,8 @@ cflags = [] if env['OURPLATFORM']=='win32-vc': cflags = ['/GR'] +defs = '' if env['WITH_BF_FFMPEG']: defs += ' WITH_FFMPEG' -env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags) +env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = Split(defs), libtype='player',priority=0, compileflags=cflags) From 882d85a96827cb50d1fc4a2ac1d63b902aab8f86 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 16 Dec 2008 12:32:10 +0000 Subject: [PATCH 072/252] Patch from Banlu Kemiyatorn replace VecMulf(var,-1) with new VecNegf(var) function. --- source/blender/blenkernel/intern/collision.c | 2 +- source/blender/blenkernel/intern/constraint.c | 14 +++++++------- source/blender/blenkernel/intern/effect.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 8 ++++---- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 11 +++++++++-- source/blender/blenlib/intern/graph.c | 6 +++--- source/blender/gpu/intern/gpu_material.c | 2 +- .../blender/radiosity/intern/source/radfactors.c | 4 ++-- source/blender/radiosity/intern/source/radrender.c | 4 ++-- source/blender/render/intern/source/occlusion.c | 10 +++++----- source/blender/render/intern/source/rendercore.c | 4 ++-- source/blender/render/intern/source/shadeinput.c | 2 +- 13 files changed, 39 insertions(+), 31 deletions(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 775f1dee241..0b5465ea25d 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1236,7 +1236,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat if(out_normalVelocity < 0.0) { out_normalVelocity*= -1.0; - VecMulf(out_normal, -1.0); + VecNegf(out_normal); } */ /* Inelastic repulsion impulse. */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 5639f00ee39..b668a1f214d 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1044,7 +1044,7 @@ static void vectomat (float *vec, float *target_up, short axis, short upflag, sh n[2] = 1.0; } if (axis > 2) axis -= 3; - else VecMulf(n,-1); + else VecNegf(n); /* n specifies the transformation of the track axis */ if (flags & TARGET_Z_UP) { @@ -2182,7 +2182,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[0]); VecSubf(totmat[1], vec, vec2); Normalize(totmat[1]); - VecMulf(totmat[1],-1); + VecNegf(totmat[1]); /* the x axis is fixed */ totmat[0][0] = cob->matrix[0][0]; @@ -2200,7 +2200,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[0]); VecSubf(totmat[2], vec, vec2); Normalize(totmat[2]); - VecMulf(totmat[2],-1); + VecNegf(totmat[2]); /* the x axis is fixed */ totmat[0][0] = cob->matrix[0][0]; @@ -2265,7 +2265,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[1]); VecSubf(totmat[0], vec, vec2); Normalize(totmat[0]); - VecMulf(totmat[0],-1); + VecNegf(totmat[0]); /* the y axis is fixed */ totmat[1][0] = cob->matrix[1][0]; @@ -2283,7 +2283,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[1]); VecSubf(totmat[2], vec, vec2); Normalize(totmat[2]); - VecMulf(totmat[2],-1); + VecNegf(totmat[2]); /* the y axis is fixed */ totmat[1][0] = cob->matrix[1][0]; @@ -2348,7 +2348,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[2]); VecSubf(totmat[0], vec, vec2); Normalize(totmat[0]); - VecMulf(totmat[0],-1); + VecNegf(totmat[0]); /* the z axis is fixed */ totmat[2][0] = cob->matrix[2][0]; @@ -2366,7 +2366,7 @@ static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Projf(vec2, vec, cob->matrix[2]); VecSubf(totmat[1], vec, vec2); Normalize(totmat[1]); - VecMulf(totmat[1],-1); + VecNegf(totmat[1]); /* the z axis is fixed */ totmat[2][0] = cob->matrix[2][0]; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 122c6c71a6c..0338ec92414 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -251,7 +251,7 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir) return 0; VECCOPY(norm, dir); - VecMulf(norm, -1.0); + VecNegf(norm); len = Normalize(norm); // check all collision objects diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 39226faff1e..8a964c5b32e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -831,7 +831,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C VecCopyf(tan,seam->tan); VecSubf(temp2,co1,temp); if(Inpf(tan,temp2)<0.0f) - VecMulf(tan,-1.0f); + VecNegf(tan); } for(w=0; wnor); VECSUB(temp, co2, co1); if(Inpf(col->nor, temp) > 0.0f) - VecMulf(col->nor, -1.0f); + VecNegf(col->nor); VECCOPY(col->vel,vel); @@ -3802,7 +3802,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, VecRotToQuat(pa->state.vel,bank,q); VECCOPY(dvec,pa->state.vel); - VecMulf(dvec,-1.0f); + VecNegf(dvec); vectoquat(dvec, OB_POSX, OB_POSZ, q2); QuatMul(pa->state.rot,q,q2); diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index e4b983d9ba3..fd58aa318da 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -241,6 +241,7 @@ int VecLen(int *v1, int *v2); float VecLenf(float *v1, float *v2); float VecLength(float *v); void VecMulf(float *v1, float f); +void VecNegf(float *v1); int VecLenCompare(float *v1, float *v2, float limit); int VecCompare(float *v1, float *v2, float limit); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index e606092f72d..61cbf791bf1 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2183,6 +2183,13 @@ void VecMulf(float *v1, float f) v1[2]*= f; } +void VecNegf(float *v1) +{ + v1[0] = -v1[0]; + v1[1] = -v1[1]; + v1[2] = -v1[2]; +} + void VecOrthoBasisf(float *v, float *v1, float *v2) { float f = sqrt(v[0]*v[0] + v[1]*v[1]); @@ -3945,7 +3952,7 @@ int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, f Normalize(nor); /* flip normal */ - if(Inpf(nor,vel)>0.0f) VecMulf(nor,-1.0f); + if(Inpf(nor,vel)>0.0f) VecNegf(nor); a=Inpf(p1,nor)-Inpf(v0,nor); nordotv=Inpf(nor,vel); @@ -4616,7 +4623,7 @@ void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, /* check flip */ if ((ct[0]*n[0] + ct[1]*n[1] + ct[2]*n[2]) < 0.0f) - VecMulf(tang, -1.0f); + VecNegf(tang); } /* used for zoom values*/ diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c index 8f35b38379e..bcd8a2ce7cd 100644 --- a/source/blender/blenlib/intern/graph.c +++ b/source/blender/blenlib/intern/graph.c @@ -809,15 +809,15 @@ static void testAxialSymmetry(BGraph *graph, BNode* root_node, BNode* node1, BNo if (abs(nor[0]) > abs(nor[1]) && abs(nor[0]) > abs(nor[2]) && nor[0] < 0) { - VecMulf(nor, -1); + VecNegf(nor); } else if (abs(nor[1]) > abs(nor[0]) && abs(nor[1]) > abs(nor[2]) && nor[1] < 0) { - VecMulf(nor, -1); + VecNegf(nor); } else if (abs(nor[2]) > abs(nor[1]) && abs(nor[2]) > abs(nor[0]) && nor[2] < 0) { - VecMulf(nor, -1); + VecNegf(nor); } /* mirror node2 along axis */ diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 46df003cbbc..87703bc73bf 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -306,7 +306,7 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float v if(material->dynproperty & DYN_LAMP_VEC) { VECCOPY(lamp->dynvec, lamp->vec); Normalize(lamp->dynvec); - VecMulf(lamp->dynvec, -1.0f); + VecNegf(lamp->dynvec); Mat4Mul3Vecfl(viewmat, lamp->dynvec); } diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c index ba4dbf1b793..d5b7c1caef3 100644 --- a/source/blender/radiosity/intern/source/radfactors.c +++ b/source/blender/radiosity/intern/source/radfactors.c @@ -535,10 +535,10 @@ void progressiverad() if(shoot->first->f & RAD_TWOSIDED) { VECCOPY(unshot, shoot->unshot); - VecMulf(shoot->norm, -1.0); + VecNegf(shoot->norm); if(makeformfactors(shoot)) applyformfactors(shoot); - VecMulf(shoot->norm, -1.0); + VecNegf(shoot->norm); VECCOPY(shoot->unshot, unshot); } diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c index 68b5fa81f43..454a7d01688 100644 --- a/source/blender/radiosity/intern/source/radrender.c +++ b/source/blender/radiosity/intern/source/radrender.c @@ -299,10 +299,10 @@ static void progressiverad_rr(Render *re) /* ...unless it's two sided */ if(shootrf->flag & RAD_TWOSIDED) { VECCOPY(unshot, shootrf->unshot); - VecMulf(shootrf->norm, -1.0); + VecNegf(shootrf->norm); makeformfactors_rr(re, shoot, shootrf); applyformfactors_rr(re, shoot, shootrf); - VecMulf(shootrf->norm, -1.0); + VecNegf(shootrf->norm); VECCOPY(shootrf->unshot, unshot); } diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index d2d2cf3fb77..494feb96c18 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -181,8 +181,8 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, /* not a pretty solution, but fixes common cases */ if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { - VecMulf(shi->vn, -1.0f); - VecMulf(shi->vno, -1.0f); + VecNegf(shi->vn); + VecNegf(shi->vno); } /* init material vars */ @@ -1288,7 +1288,7 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass) for(pass=0; passtotface; i++) { occ_face(&tree->face[i], co, n, NULL); - VecMulf(n, -1.0f); + VecNegf(n); VECADDFAC(co, co, n, 1e-8f); occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL); @@ -1321,7 +1321,7 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f aocolor= WO_AOPLAIN; VECCOPY(nn, n); - VecMulf(nn, -1.0f); + VecNegf(nn); occ_lookup(tree, thread, exclude, co, nn, &occ, (aocolor)? bn: NULL); @@ -1525,7 +1525,7 @@ static void *exec_strandsurface_sample(void *data) CalcCent3f(co, co1, co2, co3); CalcNormFloat(co1, co2, co3, n); } - VecMulf(n, -1.0f); + VecNegf(n); sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, col); VECCOPY(othread->facecol[a], col); diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index c3b281f2a23..5dfb509939b 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1505,8 +1505,8 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRe /* not a pretty solution, but fixes common cases */ if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { - VecMulf(shi->vn, -1.0f); - VecMulf(shi->vno, -1.0f); + VecNegf(shi->vn); + VecNegf(shi->vno); } /* if nodetree, use the material that we are currently preprocessing diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 476330152ec..1cd8ec110f9 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -354,7 +354,7 @@ void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spo Normalize(shi->vn); if(INPR(shi->vn, shi->view) < 0.0f) - VecMulf(shi->vn, -1.0f); + VecNegf(shi->vn); } VECCOPY(shi->vno, shi->vn); From 0611154cfe0eacd7e46288966f60122c1cbd0175 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 16 Dec 2008 21:07:12 +0000 Subject: [PATCH 073/252] Flatten and Cut Out tools for correcting errors in strokes. Ogg Video: http://blenderartists.org/~theeth/bf/etch-a-ton/gesture_command.ogv Vimeo: http://vimeo.com/2546077 --- source/blender/src/editarmature_sketch.c | 145 +++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 6d99e963183..75cb91c8b85 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -55,6 +55,7 @@ #include "BIF_sketch.h" #include "BIF_retarget.h" #include "BIF_generate.h" +#include "BIF_interface.h" #include "blendef.h" #include "mydevice.h" @@ -108,6 +109,7 @@ typedef struct SK_Intersection int after; int gesture_index; float p[3]; + float lambda; /* used for sorting intersection points */ } SK_Intersection; typedef struct SK_Sketch @@ -801,6 +803,68 @@ void sk_trimStroke(SK_Stroke *stk, int start, int end) stk->nb_points = size; } +void sk_cutoutStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3]) +{ + int size = end - start + 1; + + if (size == 1) + { + int move_size = stk->nb_points - end; + + sk_growStrokeBuffer(stk); + + memmove(stk->points + end + 1, stk->points + end, move_size * sizeof(SK_Point)); + end++; + size++; + stk->nb_points++; + } + + stk->points[start].type = PT_EXACT; + VECCOPY(stk->points[start].p, p_start); + stk->points[end].type = PT_EXACT; + VECCOPY(stk->points[end].p, p_end); + + if (size > 2) + { + int move_size = stk->nb_points - end; + + memmove(stk->points + start + 1, stk->points + end, move_size * sizeof(SK_Point)); + + stk->nb_points = stk->nb_points - (size - 2); + } +} + +void sk_flattenStroke(SK_Stroke *stk, int start, int end) +{ + float normal[3], distance[3]; + float limit; + int i, total; + + total = end - start + 1; + + VECCOPY(normal, stk->points[start].no); + + VecSubf(distance, stk->points[end].p, stk->points[start].p); + Projf(normal, distance, normal); + limit = Normalize(normal); + + for (i = 1; i < total - 1; i++) + { + float d = limit * i / total; + float offset[3]; + float *p = stk->points[start + i].p; + + VecSubf(distance, p, stk->points[start].p); + Projf(distance, distance, normal); + + VECCOPY(offset, normal); + VecMulf(offset, d); + + VecSubf(p, p, distance); + VecAddf(p, p, offset); + } +} + void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk) { if (sketch->active_stroke == stk) @@ -1891,6 +1955,36 @@ int sk_getSelfIntersections(ListBase *list, SK_Stroke *gesture) return added; } +int cmpIntersections(void *i1, void *i2) +{ + SK_Intersection *isect1 = i1, *isect2 = i2; + + if (isect1->stroke == isect2->stroke) + { + if (isect1->before < isect2->before) + { + return -1; + } + else if (isect1->before > isect2->before) + { + return 1; + } + else + { + if (isect1->lambda < isect2->lambda) + { + return -1; + } + else if (isect1->lambda > isect2->lambda) + { + return 1; + } + } + } + + return 0; +} + /* returns the maximum number of intersections per stroke */ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) @@ -1932,6 +2026,7 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) isect->before = s_i; isect->after = s_i + 1; isect->stroke = stk; + isect->lambda = lambda; mval[0] = (short)(vi[0]); mval[1] = (short)(vi[1]); @@ -1954,6 +2049,7 @@ int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) added = MAX2(s_added, added); } + BLI_sortlist(list, cmpIntersections); return added; } @@ -2063,6 +2159,51 @@ void sk_applyTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, } } +int sk_detectCommandGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + return 1; +} + +void sk_applyCommandGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +{ + SK_Intersection *isect; + int command; + + command = pupmenu("Action %t|Flatten %x1|Cut Out %x2"); + if(command < 1) return; + + for (isect = list->first; isect; isect = isect->next) + { + SK_Intersection *i2, *i3; + + i2 = isect->next; + + if (i2 && i2->stroke == isect->stroke) + { + i3 = i2->next; + + if (i3 && i3->stroke == i2->stroke) + { + switch (command) + { + case 1: + sk_flattenStroke(isect->stroke, isect->before, i3->after); + break; + case 2: + sk_cutoutStroke(isect->stroke, isect->after, i3->before, isect->p, i3->p); + break; + } + + isect = i3; + } + else + { + isect = i2; + } + } + } +} + int sk_detectDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) { float s1[3], s2[3]; @@ -2269,6 +2410,10 @@ void sk_applyGesture(SK_Sketch *sketch) { sk_applyReverseGesture(sketch, sketch->gesture, &intersections, segments); } + else if (nb_segments > 2 && nb_intersections == 3 && nb_self_intersections == 1 && sk_detectCommandGesture(sketch, sketch->gesture, &intersections, segments)) + { + sk_applyCommandGesture(sketch, sketch->gesture, &intersections, segments); + } else if (nb_segments > 2 && nb_self_intersections == 1) { sk_convert(sketch); From 7714f17eca00b3b9038ad946d26a4869b16edaf7 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 16 Dec 2008 22:57:15 +0000 Subject: [PATCH 074/252] Applying scons compiling fix for windows/mingw (to get compiler warnings to show up). This has already been applied in other branches too --- SConstruct | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index 16e98e64f6b..b2eb0ffe26d 100644 --- a/SConstruct +++ b/SConstruct @@ -115,8 +115,9 @@ if toolset: env.Tool('mstoolkit', ['tools']) else: env = BlenderEnvironment(tools=[toolset], ENV = os.environ) - if env: - btools.SetupSpawn(env) + # xxx commented out, as was supressing warnings under mingw.. + #if env: + # btools.SetupSpawn(env) else: env = BlenderEnvironment(ENV = os.environ) From 9776749438661c0476618d81918c15bd41347fc9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 17 Dec 2008 00:41:07 +0000 Subject: [PATCH 075/252] Reverting revision 17417 which broke cloth collisions which check also in blenkernel/intern for WITH_BULLET --- source/blender/src/SConscript | 3 --- tools/Blender.py | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index 451afc9b244..dedb40485ef 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -65,9 +65,6 @@ if env['WITH_BF_ICONV']: incs += ' ' + env['BF_ICONV_INC'] defs.append('WITH_ICONV') -if env['WITH_BF_GAMEENGINE']: - defs.append('GAMEBLENDER=1') - if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') incs += ' ' + env['BF_FFMPEG_INC'] diff --git a/tools/Blender.py b/tools/Blender.py index 1c54e98f177..3bf6f01bc25 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -421,6 +421,10 @@ class BlenderEnvironment(SConsEnvironment): lenv = self.Clone() lenv.Append(CPPPATH=includes) lenv.Append(CPPDEFINES=defines) + if lenv['WITH_BF_GAMEENGINE']: + lenv.Append(CPPDEFINES=['GAMEBLENDER=1']) + if lenv['WITH_BF_BULLET']: + lenv.Append(CPPDEFINES=['WITH_BULLET=1']) if lenv['BF_DEBUG'] or (libname in quickdebug): lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS']) lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS']) From 3c886d7c384289206b02b1581ddc9366d607bd3f Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 17 Dec 2008 05:40:40 +0000 Subject: [PATCH 076/252] * commit r17900 by Genscher was wrong. - Instead of defining such defines for the entire codebase in Blender.py, add the right checks and definitions to the places where it matters. - Only check+set WITH_BULLET instead of also GAMEBLENDER=1 - NOTE: No global defines allowed in BlenderLib. --- source/blender/blenkernel/SConscript | 3 +++ source/blender/src/SConscript | 3 +++ tools/Blender.py | 4 ---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index ab122e40bfc..4ab7d4a6792 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -53,6 +53,9 @@ if env['WITH_BF_QUICKTIME']: defs += ' WITH_QUICKTIME' incs += ' ' + env['BF_QUICKTIME_INC'] +if env['WITH_BF_BULLET']: + defs += ' WITH_BULLET' + if env['BF_NO_ELBEEM']: defs += ' DISABLE_ELBEEM' diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index dedb40485ef..451afc9b244 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -65,6 +65,9 @@ if env['WITH_BF_ICONV']: incs += ' ' + env['BF_ICONV_INC'] defs.append('WITH_ICONV') +if env['WITH_BF_GAMEENGINE']: + defs.append('GAMEBLENDER=1') + if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') incs += ' ' + env['BF_FFMPEG_INC'] diff --git a/tools/Blender.py b/tools/Blender.py index 3bf6f01bc25..1c54e98f177 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -421,10 +421,6 @@ class BlenderEnvironment(SConsEnvironment): lenv = self.Clone() lenv.Append(CPPPATH=includes) lenv.Append(CPPDEFINES=defines) - if lenv['WITH_BF_GAMEENGINE']: - lenv.Append(CPPDEFINES=['GAMEBLENDER=1']) - if lenv['WITH_BF_BULLET']: - lenv.Append(CPPDEFINES=['WITH_BULLET=1']) if lenv['BF_DEBUG'] or (libname in quickdebug): lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS']) lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS']) From 04ef5be177b35c12378c85ef99b2e83aa7f27bd3 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 17 Dec 2008 20:52:39 +0000 Subject: [PATCH 077/252] FFmpeg upgrade to revision 12758 (avformat version 52.13): support libavdevice for video capture in VideoTexture module (BGE). Makefile, CMake, scons updated. FFmpeg binaries will have to be rebuilt for certain OS (irix), win32 binaries already up to date. You MUST do a clean rebuild after this patch. Scons users: pay attention that the config/-config.py files have changed, adapt your user-config.py in consequence --- CMakeLists.txt | 2 +- SConstruct | 9 +++++++-- config/darwin-config.py | 6 +++++- config/irix6-config.py | 2 +- config/linux2-config.py | 9 +++++++-- config/sunos5-config.py | 2 +- config/win32-mingw-config.py | 2 +- source/blender/imbuf/intern/util.c | 4 ++-- source/nan_definitions.mk | 14 +++++++------- 9 files changed, 32 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e01a37d3b3e..4b96ca585a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,7 +175,7 @@ IF(UNIX) SET(FFMPEG /usr) SET(FFMPEG_INC ${FFMPEG}/include) - SET(FFMPEG_LIB avformat avcodec avutil) + SET(FFMPEG_LIB avformat avcodec avutil avdevice swscale) SET(FFMPEG_LIBPATH ${FFMPEG}/lib) SET(JPEG_LIB jpeg) diff --git a/SConstruct b/SConstruct index b2eb0ffe26d..809166586e6 100644 --- a/SConstruct +++ b/SConstruct @@ -322,10 +322,15 @@ if not quickie and do_clean: print "remove file %s"%(B.root_build_dir+entry) os.remove(B.root_build_dir+entry) for confile in ['extern/ffmpeg/config.mak', 'extern/x264/config.mak', - 'extern/xvidcore/build/generic/platform.inc']: + 'extern/xvidcore/build/generic/platform.inc', 'extern/ffmpeg/include']: if os.path.exists(confile): print "clean file %s"%confile - os.remove(confile) + if os.path.isdir(confile): + for root, dirs, files in os.walk(confile): + for name in files: + os.remove(os.path.join(root, name)) + else: + os.remove(confile) print B.bc.OKGREEN+'...done'+B.bc.ENDC else: print B.bc.HEADER+'Already Clean, nothing to do.'+B.bc.ENDC diff --git a/config/darwin-config.py b/config/darwin-config.py index 3ef7b7132d9..cfd6a9395bb 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -40,7 +40,11 @@ else: # enable ffmpeg support WITH_BF_FFMPEG = True # -DWITH_FFMPEG BF_FFMPEG = "#extern/ffmpeg" -BF_FFMPEG_INC = '${BF_FFMPEG}/include' +# trick : The version of ffmpeg in extern/ffmpeg uses explicit libav.. directory in #include statements +# To keep Blender compatible with older versions, I add ${BF_FFMPEG} to the inc dir so that ffmpeg +# finds the files directly in extern/ffmpeg/libav... while blender finds them in +# extern/ffmpeg/include. +BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}' if USE_SDK==True: BF_FFMPEG_EXTRA = '-isysroot '+MACOSX_SDK+' -mmacosx-version-min='+MAC_MIN_VERS #BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' diff --git a/config/irix6-config.py b/config/irix6-config.py index b643affb0b3..2485c02e095 100644 --- a/config/irix6-config.py +++ b/config/irix6-config.py @@ -146,7 +146,7 @@ WITH_BF_BINRELOC = 'false' WITH_BF_FFMPEG = 'true' # -DWITH_FFMPEG # Uncomment the following two lines to use system's ffmpeg BF_FFMPEG = LCGDIR+'/ffmpeg' -BF_FFMPEG_LIB = 'avformat avcodec swscale avutil faad faac vorbis x264 ogg mp3lame z' +BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice faad faac vorbis x264 ogg mp3lame z' BF_FFMPEG_INC = '${BF_FFMPEG}/include' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' diff --git a/config/linux2-config.py b/config/linux2-config.py index 2984c06d2df..56132aaf1de 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -139,8 +139,13 @@ BF_FFMPEG = '#extern/ffmpeg' BF_FFMPEG_LIB = '' # Uncomment the following two lines to use system's ffmpeg # BF_FFMPEG = '/usr' -# BF_FFMPEG_LIB = 'avformat avcodec swscale avutil' -BF_FFMPEG_INC = '${BF_FFMPEG}/include' +# BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice' +# trick : The version of ffmpeg in extern/ffmpeg uses explicit libav.. directory in #include statements +# To keep Blender compatible with older version, I add ${BF_FFMPEG} to the inc dir so that ffmpeg +# finds the files directly in extern/ffmpeg/libav... while blender finds them in +# extern/ffmpeg/include. When using system ffmpeg, you don't need that, assuming the system library +# still use the flat directory model, otherwise will not compile anyway +BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' # enable ogg, vorbis and theora in ffmpeg diff --git a/config/sunos5-config.py b/config/sunos5-config.py index a44a9df7c75..dda7d0ff2f3 100644 --- a/config/sunos5-config.py +++ b/config/sunos5-config.py @@ -131,7 +131,7 @@ WITH_BF_FFMPEG = False # -DWITH_FFMPEG BF_FFMPEG = '/usr/local' BF_FFMPEG_INC = '${BF_FFMPEG}/include' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' -BF_FFMPEG_LIB = 'avformat avcodec avutil' +BF_FFMPEG_LIB = 'avformat avcodec avutil avdevice' # Mesa Libs should go here if your using them as well.... WITH_BF_STATICOPENGL = False diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py index 6278672ca3d..963f62a5f40 100644 --- a/config/win32-mingw-config.py +++ b/config/win32-mingw-config.py @@ -21,7 +21,7 @@ BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_FFMPEG = False -BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264' +BF_FFMPEG_LIB = 'avformat swscale avcodec avutil avdevice xvidcore x264' BF_FFMPEG_LIBPATH = LIBDIR + '/gcc/ffmpeg/lib' BF_FFMPEG_INC = LIBDIR + '/gcc/ffmpeg/include' diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index c86f9b017bf..cf8c0978c66 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -71,7 +71,7 @@ #ifdef WITH_FFMPEG #include #include -//#include +#include #include #if LIBAVFORMAT_VERSION_INT < (49 << 16) @@ -258,7 +258,7 @@ void do_init_ffmpeg() if (!ffmpeg_init) { ffmpeg_init = 1; av_register_all(); - //avdevice_register_all(); + avdevice_register_all(); if ((G.f & G_DEBUG) == 0) { diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 04a1d107931..3961e153cea 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -100,13 +100,13 @@ endif ifeq ($(FREE_WINDOWS), true) export NAN_FTGL ?= $(LCGDIR)/gcc/ftgl export NAN_FFMPEG ?= $(LCGDIR)/gcc/ffmpeg - export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavcodec.a - export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include + export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libavdevice.a + export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include -I$(NANBLENDERHOME)/extern/ffmpeg else export NAN_FTGL ?= $(LCGDIR)/ftgl export NAN_FFMPEG ?= $(LCGDIR)/ffmpeg - export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a - export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include + export NAN_FFMPEGLIBS ?= $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavdevice.a + export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include -I$(NANBLENDERHOME)/extern/ffmpeg endif ifeq ($(WITH_VERSE), true) @@ -357,8 +357,8 @@ endif export NAN_SDLLIBS ?= $(NAN_SDL)/lib/libSDL.a export NAN_SDLCFLAGS ?= -I$(NAN_SDL)/include/SDL export NAN_FFMPEG ?= $(LCGDIR)/ffmpeg - export NAN_FFMPEGLIBS = $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libogg.a $(NAN_FFMPEG)/lib/libfaad.a $(NAN_FFMPEG)/lib/libmp3lame.a $(NAN_FFMPEG)/lib/libvorbis.a $(NAN_FFMPEG)/lib/libx264.a $(NAN_FFMPEG)/lib/libfaac.a $(NAN_ZLIB)/lib/libz.a - export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include + export NAN_FFMPEGLIBS = $(NAN_FFMPEG)/lib/libavformat.a $(NAN_FFMPEG)/lib/libavcodec.a $(NAN_FFMPEG)/lib/libswscale.a $(NAN_FFMPEG)/lib/libavutil.a $(NAN_FFMPEG)/lib/libavdevice.a $(NAN_FFMPEG)/lib/libogg.a $(NAN_FFMPEG)/lib/libfaad.a $(NAN_FFMPEG)/lib/libmp3lame.a $(NAN_FFMPEG)/lib/libvorbis.a $(NAN_FFMPEG)/lib/libx264.a $(NAN_FFMPEG)/lib/libfaac.a $(NAN_ZLIB)/lib/libz.a + export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include -I$(NANBLENDERHOME)/extern/ffmpeg # Uncomment the following line to use Mozilla inplace of netscape # CPPFLAGS +=-DMOZ_NOT_NET @@ -407,7 +407,7 @@ endif ifneq ($(NAN_USE_FFMPEG_CONFIG), true) export NAN_FFMPEG ?= /usr - export NAN_FFMPEGLIBS ?= -L$(NAN_FFMPEG)/lib -lavformat -lavcodec -lavutil -lswscale -ldts -lz + export NAN_FFMPEGLIBS ?= -L$(NAN_FFMPEG)/lib -lavformat -lavcodec -lavutil -lswscale -lavdevice -ldts -lz export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include endif From a755342b1442ede048f7761b3d30cb546de23607 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 18 Dec 2008 22:08:57 +0000 Subject: [PATCH 078/252] Bugfix for crash with loading fluidsim files, reported by Gimble3d and nudelZ --- source/blender/blenloader/intern/readfile.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 91170563c11..6579d2cd4c1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3179,6 +3179,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) FluidsimModifierData *fluidmd = (FluidsimModifierData*) md; fluidmd->fss= newdataadr(fd, fluidmd->fss); + fluidmd->fss->meshSurfNormals = 0; } else if (md->type==eModifierType_Collision) { @@ -7856,6 +7857,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) fluidmd->fss->lastgoodframe = INT_MAX; fluidmd->fss->flag = 0; + fluidmd->fss->meshSurfNormals = 0; } } } From 3c9ae035fbe81f0b6397a27ec3489bbdb430b2ef Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 19 Dec 2008 03:26:41 +0000 Subject: [PATCH 079/252] Typo was making actuator.getExecutePriority() crash --- source/gameengine/GameLogic/SCA_ILogicBrick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index abd049e9d64..515b485061d 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -247,7 +247,7 @@ PyParentObject SCA_ILogicBrick::Parents[] = { PyMethodDef SCA_ILogicBrick::Methods[] = { {"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_NOARGS}, - {"getExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_NOARGS}, + {"getExecutePriority", (PyCFunction) SCA_ILogicBrick::sPyGetExecutePriority, METH_NOARGS}, {"setExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_VARARGS}, {NULL,NULL} //Sentinel }; From 4a3630751d386bdd9aec063503b579899fcd9037 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 19 Dec 2008 19:47:25 +0000 Subject: [PATCH 080/252] Cleaner code for gestures. Command gesture (for flatten and cutout) now needs to intersect a line in two points and end in a pig tail (loop and intersect itself). This is easier than the cross three times and self interesect once of before. --- source/blender/src/editarmature_sketch.c | 402 +++++++++++++---------- 1 file changed, 231 insertions(+), 171 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 75cb91c8b85..c63575c8b7a 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -140,6 +140,27 @@ typedef struct SK_StrokeIterator { int stride; } SK_StrokeIterator; +typedef struct SK_Gesture { + SK_Stroke *stk; + SK_Stroke *segments; + + ListBase intersections; + ListBase self_intersections; + + int nb_self_intersections; + int nb_intersections; + int nb_segments; +} SK_Gesture; + +typedef int (*GestureDetectFct)(SK_Gesture*, SK_Sketch *); +typedef void (*GestureApplyFct)(SK_Gesture*, SK_Sketch *); + +typedef struct SK_GestureAction { + char name[64]; + GestureDetectFct detect; + GestureApplyFct apply; +} SK_GestureAction; + SK_Sketch *GLOBAL_sketch = NULL; SK_Point boneSnap; @@ -156,6 +177,33 @@ void sk_freeSketch(SK_Sketch *sketch); SK_Point *sk_lastStrokePoint(SK_Stroke *stk); +int sk_detectCutGesture(SK_Gesture *gest, SK_Sketch *sketch); +void sk_applyCutGesture(SK_Gesture *gest, SK_Sketch *sketch); +int sk_detectTrimGesture(SK_Gesture *gest, SK_Sketch *sketch); +void sk_applyTrimGesture(SK_Gesture *gest, SK_Sketch *sketch); +int sk_detectCommandGesture(SK_Gesture *gest, SK_Sketch *sketch); +void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch); +int sk_detectDeleteGesture(SK_Gesture *gest, SK_Sketch *sketch); +void sk_applyDeleteGesture(SK_Gesture *gest, SK_Sketch *sketch); +int sk_detectMergeGesture(SK_Gesture *gest, SK_Sketch *sketch); +void sk_applyMergeGesture(SK_Gesture *gest, SK_Sketch *sketch); +int sk_detectReverseGesture(SK_Gesture *gest, SK_Sketch *sketch); +void sk_applyReverseGesture(SK_Gesture *gest, SK_Sketch *sketch); + + +/******************** GESTURE ACTIONS ******************************/ + +SK_GestureAction GESTURE_ACTIONS[] = + { + {"Cut", sk_detectCutGesture, sk_applyCutGesture}, + {"Trim", sk_detectTrimGesture, sk_applyTrimGesture}, + {"Command", sk_detectCommandGesture, sk_applyCommandGesture}, + {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture}, + {"Merge", sk_detectMergeGesture, sk_applyMergeGesture}, + {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture}, + {"", NULL, NULL} + }; + /******************** TEMPLATES UTILS *************************/ char *TEMPLATES_MENU = NULL; @@ -2089,11 +2137,21 @@ int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) return segments->nb_points - 1; } -void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +int sk_detectCutGesture(SK_Gesture *gest, SK_Sketch *sketch) +{ + if (gest->nb_segments == 1 && gest->nb_intersections == 1) + { + return 1; + } + + return 0; +} + +void sk_applyCutGesture(SK_Gesture *gest, SK_Sketch *sketch) { SK_Intersection *isect; - for (isect = list->first; isect; isect = isect->next) + for (isect = gest->intersections.first; isect; isect = isect->next) { SK_Point pt; @@ -2105,34 +2163,35 @@ void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, S } } -int sk_detectTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +int sk_detectTrimGesture(SK_Gesture *gest, SK_Sketch *sketch) { - float s1[3], s2[3]; - float angle; - - VecSubf(s1, segments->points[1].p, segments->points[0].p); - VecSubf(s2, segments->points[2].p, segments->points[1].p); - - angle = VecAngle2(s1, s2); - - if (angle > 60 && angle < 120) + if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0) { - return 1; - } - else - { - return 0; + float s1[3], s2[3]; + float angle; + + VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p); + VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p); + + angle = VecAngle2(s1, s2); + + if (angle > 60 && angle < 120) + { + return 1; + } } + + return 0; } -void sk_applyTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +void sk_applyTrimGesture(SK_Gesture *gest, SK_Sketch *sketch) { SK_Intersection *isect; float trim_dir[3]; - VecSubf(trim_dir, segments->points[2].p, segments->points[1].p); + VecSubf(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p); - for (isect = list->first; isect; isect = isect->next) + for (isect = gest->intersections.first; isect; isect = isect->next) { SK_Point pt; float stroke_dir[3]; @@ -2159,12 +2218,34 @@ void sk_applyTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, } } -int sk_detectCommandGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +int sk_detectCommandGesture(SK_Gesture *gest, SK_Sketch *sketch) { - return 1; + if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1) + { + SK_Intersection *isect, *self_isect; + + /* get the the last intersection of the first pair */ + for( isect = gest->intersections.first; isect; isect = isect->next ) + { + if (isect->stroke == isect->next->stroke) + { + isect = isect->next; + break; + } + } + + self_isect = gest->self_intersections.first; + + if (isect && isect->gesture_index < self_isect->gesture_index) + { + return 1; + } + } + + return 0; } -void sk_applyCommandGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch) { SK_Intersection *isect; int command; @@ -2172,63 +2253,55 @@ void sk_applyCommandGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *lis command = pupmenu("Action %t|Flatten %x1|Cut Out %x2"); if(command < 1) return; - for (isect = list->first; isect; isect = isect->next) + for (isect = gest->intersections.first; isect; isect = isect->next) { - SK_Intersection *i2, *i3; + SK_Intersection *i2; i2 = isect->next; if (i2 && i2->stroke == isect->stroke) { - i3 = i2->next; - - if (i3 && i3->stroke == i2->stroke) + switch (command) { - switch (command) - { - case 1: - sk_flattenStroke(isect->stroke, isect->before, i3->after); - break; - case 2: - sk_cutoutStroke(isect->stroke, isect->after, i3->before, isect->p, i3->p); - break; - } + case 1: + sk_flattenStroke(isect->stroke, isect->before, i2->after); + break; + case 2: + sk_cutoutStroke(isect->stroke, isect->after, i2->before, isect->p, i2->p); + break; + } - isect = i3; - } - else - { - isect = i2; - } + isect = i2; } } } -int sk_detectDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +int sk_detectDeleteGesture(SK_Gesture *gest, SK_Sketch *sketch) { - float s1[3], s2[3]; - float angle; - - VecSubf(s1, segments->points[1].p, segments->points[0].p); - VecSubf(s2, segments->points[2].p, segments->points[1].p); - - angle = VecAngle2(s1, s2); - - if (angle > 120) + if (gest->nb_segments == 2 && gest->nb_intersections == 2) { - return 1; - } - else - { - return 0; + float s1[3], s2[3]; + float angle; + + VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p); + VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p); + + angle = VecAngle2(s1, s2); + + if (angle > 120) + { + return 1; + } } + + return 0; } -void sk_applyDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +void sk_applyDeleteGesture(SK_Gesture *gest, SK_Sketch *sketch) { SK_Intersection *isect; - for (isect = list->first; isect; isect = isect->next) + for (isect = gest->intersections.first; isect; isect = isect->next) { /* only delete strokes that are crossed twice */ if (isect->next && isect->next->stroke == isect->stroke) @@ -2240,60 +2313,59 @@ void sk_applyDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list } } -int sk_detectMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +int sk_detectMergeGesture(SK_Gesture *gest, SK_Sketch *sketch) { - short start_val[2], end_val[2]; - short dist; - - project_short_noclip(gesture->points[0].p, start_val); - project_short_noclip(gesture->points[gesture->nb_points - 1].p, end_val); - - dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1])); - - /* if gesture is a circle */ - if ( dist <= 20 ) + if (gest->nb_segments > 2 && gest->nb_intersections == 2) { - SK_Intersection *isect; + short start_val[2], end_val[2]; + short dist; - /* check if it circled around an exact point */ - for (isect = list->first; isect; isect = isect->next) + project_short_noclip(gest->stk->points[0].p, start_val); + project_short_noclip(sk_lastStrokePoint(gest->stk)->p, end_val); + + dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1])); + + /* if gesture is a circle */ + if ( dist <= 20 ) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) + SK_Intersection *isect; + + /* check if it circled around an exact point */ + for (isect = gest->intersections.first; isect; isect = isect->next) { - int start_index, end_index; - int i; - - start_index = MIN2(isect->after, isect->next->after); - end_index = MAX2(isect->before, isect->next->before); - - for (i = start_index; i <= end_index; i++) + /* only delete strokes that are crossed twice */ + if (isect->next && isect->next->stroke == isect->stroke) { - if (isect->stroke->points[i].type == PT_EXACT) + int start_index, end_index; + int i; + + start_index = MIN2(isect->after, isect->next->after); + end_index = MAX2(isect->before, isect->next->before); + + for (i = start_index; i <= end_index; i++) { - return 1; /* at least one exact point found, stop detect here */ + if (isect->stroke->points[i].type == PT_EXACT) + { + return 1; /* at least one exact point found, stop detect here */ + } } + + /* skip next */ + isect = isect->next; } - - /* skip next */ - isect = isect->next; } } - - return 0; - } - else - { - return 0; } + + return 0; } -void sk_applyMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +void sk_applyMergeGesture(SK_Gesture *gest, SK_Sketch *sketch) { SK_Intersection *isect; /* check if it circled around an exact point */ - for (isect = list->first; isect; isect = isect->next) + for (isect = gest->intersections.first; isect; isect = isect->next) { /* only merge strokes that are crossed twice */ if (isect->next && isect->next->stroke == isect->stroke) @@ -2319,50 +2391,53 @@ void sk_applyMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, } } -int sk_detectReverseGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +int sk_detectReverseGesture(SK_Gesture *gest, SK_Sketch *sketch) { - SK_Intersection *isect; - - /* check if it circled around an exact point */ - for (isect = list->first; isect; isect = isect->next) + if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) + SK_Intersection *isect; + + /* check if it circled around an exact point */ + for (isect = gest->intersections.first; isect; isect = isect->next) { - float start_v[3], end_v[3]; - float angle; - - if (isect->gesture_index < isect->next->gesture_index) + /* only delete strokes that are crossed twice */ + if (isect->next && isect->next->stroke == isect->stroke) { - VecSubf(start_v, isect->p, gesture->points[0].p); - VecSubf(end_v, sk_lastStrokePoint(gesture)->p, isect->next->p); + float start_v[3], end_v[3]; + float angle; + + if (isect->gesture_index < isect->next->gesture_index) + { + VecSubf(start_v, isect->p, gest->stk->points[0].p); + VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p); + } + else + { + VecSubf(start_v, isect->next->p, gest->stk->points[0].p); + VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p); + } + + angle = VecAngle2(start_v, end_v); + + if (angle > 120) + { + return 1; + } + + /* skip next */ + isect = isect->next; } - else - { - VecSubf(start_v, isect->next->p, gesture->points[0].p); - VecSubf(end_v, sk_lastStrokePoint(gesture)->p, isect->p); - } - - angle = VecAngle2(start_v, end_v); - - if (angle > 120) - { - return 1; - } - - /* skip next */ - isect = isect->next; } } return 0; } -void sk_applyReverseGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments) +void sk_applyReverseGesture(SK_Gesture *gest, SK_Sketch *sketch) { SK_Intersection *isect; - for (isect = list->first; isect; isect = isect->next) + for (isect = gest->intersections.first; isect; isect = isect->next) { /* only reverse strokes that are crossed twice */ if (isect->next && isect->next->stroke == isect->stroke) @@ -2375,59 +2450,44 @@ void sk_applyReverseGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *lis } } +static void sk_initGesture(SK_Gesture *gest, SK_Sketch *sketch) +{ + gest->intersections.first = gest->intersections.last = NULL; + gest->self_intersections.first = gest->self_intersections.last = NULL; + + gest->segments = sk_createStroke(); + gest->stk = sketch->gesture; + + gest->nb_self_intersections = sk_getSelfIntersections(&gest->self_intersections, gest->stk); + gest->nb_intersections = sk_getIntersections(&gest->intersections, sketch, gest->stk); + gest->nb_segments = sk_getSegments(gest->segments, gest->stk); +} + +static void sk_freeGesture(SK_Gesture *gest) +{ + sk_freeStroke(gest->segments); + BLI_freelistN(&gest->intersections); + BLI_freelistN(&gest->self_intersections); +} + void sk_applyGesture(SK_Sketch *sketch) { - ListBase intersections; - ListBase self_intersections; - SK_Stroke *segments = sk_createStroke(); - int nb_self_intersections, nb_intersections, nb_segments; + SK_Gesture gest; + SK_GestureAction *act; - intersections.first = intersections.last = NULL; - self_intersections.first = self_intersections.last = NULL; - - nb_self_intersections = sk_getSelfIntersections(&self_intersections, sketch->gesture); - nb_intersections = sk_getIntersections(&intersections, sketch, sketch->gesture); - nb_segments = sk_getSegments(segments, sketch->gesture); + sk_initGesture(&gest, sketch); /* detect and apply */ - if (nb_segments == 1 && nb_intersections == 1) + for (act = GESTURE_ACTIONS; act->apply != NULL; act++) { - sk_applyCutGesture(sketch, sketch->gesture, &intersections, segments); - } - else if (nb_segments == 2 && nb_intersections == 1 && sk_detectTrimGesture(sketch, sketch->gesture, &intersections, segments)) - { - sk_applyTrimGesture(sketch, sketch->gesture, &intersections, segments); - } - else if (nb_segments == 2 && nb_intersections == 2 && sk_detectDeleteGesture(sketch, sketch->gesture, &intersections, segments)) - { - sk_applyDeleteGesture(sketch, sketch->gesture, &intersections, segments); - } - else if (nb_segments > 2 && nb_intersections == 2 && sk_detectMergeGesture(sketch, sketch->gesture, &intersections, segments)) - { - sk_applyMergeGesture(sketch, sketch->gesture, &intersections, segments); - } - else if (nb_segments > 2 && nb_intersections == 2 && sk_detectReverseGesture(sketch, sketch->gesture, &intersections, segments)) - { - sk_applyReverseGesture(sketch, sketch->gesture, &intersections, segments); - } - else if (nb_segments > 2 && nb_intersections == 3 && nb_self_intersections == 1 && sk_detectCommandGesture(sketch, sketch->gesture, &intersections, segments)) - { - sk_applyCommandGesture(sketch, sketch->gesture, &intersections, segments); - } - else if (nb_segments > 2 && nb_self_intersections == 1) - { - sk_convert(sketch); - BIF_undo_push("Convert Sketch"); - allqueue(REDRAWBUTSEDIT, 0); - } - else if (nb_segments > 2 && nb_self_intersections == 2) - { - sk_deleteSelectedStrokes(sketch); + if (act->detect(&gest, sketch)) + { + act->apply(&gest, sketch); + break; + } } - sk_freeStroke(segments); - BLI_freelistN(&intersections); - BLI_freelistN(&self_intersections); + sk_freeGesture(&gest); } /********************************************/ From 5881922bc5efbb0c542344c9e6f320ec9eb4235a Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Fri, 19 Dec 2008 20:35:53 +0000 Subject: [PATCH 081/252] Add G_FILE_IGNORE_DEPRECATION_WARNINGS option to G.fileflags in preparation of BGE python API cleanup --- source/blender/blenkernel/BKE_global.h | 1 + source/blender/src/header_info.c | 7 +++++++ source/blender/src/space.c | 3 +++ 3 files changed, 11 insertions(+) diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 3a2dca525b8..e8918bcdce6 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -227,6 +227,7 @@ typedef struct Global { #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) +#define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index b6bd00d2ad6..6e43b6073eb 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -1672,6 +1672,7 @@ static uiBlock *info_game_glslmenu(void *arg_unused) static void do_info_gamemenu(void *arg, int event) { switch (event) { + case G_FILE_IGNORE_DEPRECATION_WARNINGS: case G_FILE_ENABLE_ALL_FRAMES: case G_FILE_DISPLAY_LISTS: case G_FILE_SHOW_FRAMERATE: @@ -1750,6 +1751,12 @@ static uiBlock *info_gamemenu(void *arg_unused) 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, ""); } + if(G.fileflags & G_FILE_IGNORE_DEPRECATION_WARNINGS) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Ignore Deprecation Warnings", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_IGNORE_DEPRECATION_WARNINGS, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Ignore Deprecation Warnings", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_IGNORE_DEPRECATION_WARNINGS, ""); + } + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 1, 0, ""); if(!(G.fileflags & G_FILE_GAME_MAT)) { diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 4267159baee..bba58840566 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -424,6 +424,9 @@ void space_set_commmandline_options(void) { a= (G.fileflags & G_FILE_GAME_TO_IPO); SYS_WriteCommandLineInt(syshandle, "game2ipo", a); + a= (G.fileflags & G_FILE_IGNORE_DEPRECATION_WARNINGS); + SYS_WriteCommandLineInt(syshandle, "ignore_deprecation_warnings", a); + a=(G.fileflags & G_FILE_GAME_MAT); SYS_WriteCommandLineInt(syshandle, "blender_material", a); a=(G.fileflags & G_FILE_GAME_MAT_GLSL); From 630c16feb7c8c5e8f128e4e56507c3afceaf9c6f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 20 Dec 2008 07:12:38 +0000 Subject: [PATCH 082/252] patch [#18110] [patch] Update blenderplayer.exe -h text from Mitchell Stokes (moguri) --- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 0bf0317d8f2..70272d57357 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -162,11 +162,10 @@ void usage(const char* program) consoleoption = ""; #endif - printf("usage: %s [-w [-p l t w h]] %s[-g gamengineoptions] " + printf("usage: %s [-w l t w h] %s[-g gamengineoptions] " "[-s stereomode] filename.blend\n", program, consoleoption); printf(" -h: Prints this command summary\n"); printf(" -w: display in a window\n"); - printf(" -p: specify window position\n"); printf(" l = window left coordinate\n"); printf(" t = window top coordinate\n"); printf(" w = window width\n"); @@ -190,17 +189,18 @@ void usage(const char* program) 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"); - printf(" fixedtime 0 Do the same timestep each frame \"Enable all frames\"\n"); - printf(" nomipmap 0 Disable mipmaps\n"); - printf(" show_framerate 0 Show the frame rate\n"); - printf(" show_properties 0 Show debug properties\n"); - printf(" show_profile 0 Show profiling information\n"); - printf(" blender_material 0 Enable material settings\n"); + printf(" -g: game engine options:\n\n"); + printf(" Name Default Description\n"); + printf(" ------------------------------------------------------------------------\n"); + printf(" fixedtime 0 \"Enable all frames\"\n"); + printf(" nomipmap 0 Disable mipmaps\n"); + printf(" show_framerate 0 Show the frame rate\n"); + printf(" show_properties 0 Show debug properties\n"); + printf(" show_profile 0 Show profiling information\n"); + printf(" blender_material 0 Enable material settings\n"); + printf(" ignore_deprecation_warnings 0 Ignore deprecation warnings\n"); printf("\n"); - printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program); + printf("example: %s -w 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program); printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } From c67d26602f9d55be1a4a26ed0646541ca4651624 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 20 Dec 2008 08:41:46 +0000 Subject: [PATCH 083/252] id prop update function was receiving a tuple when it only needed a single arg --- source/blender/python/api2_2x/IDProp.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/source/blender/python/api2_2x/IDProp.c b/source/blender/python/api2_2x/IDProp.c index 07269e54c7c..6457cd07098 100644 --- a/source/blender/python/api2_2x/IDProp.c +++ b/source/blender/python/api2_2x/IDProp.c @@ -533,21 +533,16 @@ static PyObject *BPy_IDGroup_HasKey(BPy_IDProperty *self, PyObject *value) Py_RETURN_FALSE; } -static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *vars) +static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *value) { - PyObject *pyob, *pkey, *pval; + PyObject *pkey, *pval; Py_ssize_t i=0; - if (PySequence_Size(vars) != 1) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected an object derived from dict."); - - pyob = PyTuple_GET_ITEM(vars, 0); - if (!PyDict_Check(pyob)) + if (!PyDict_Check(value)) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected an object derived from dict."); - while (PyDict_Next(pyob, &i, &pkey, &pval)) { + while (PyDict_Next(value, &i, &pkey, &pval)) { BPy_IDGroup_Map_SetItem(self, pkey, pval); if (PyErr_Occurred()) return NULL; } @@ -571,7 +566,7 @@ static struct PyMethodDef BPy_IDGroup_methods[] = { "get the values associated with this group."}, {"has_key", (PyCFunction)BPy_IDGroup_HasKey, METH_O, "returns true if the group contains a key, false if not."}, - {"update", (PyCFunction)BPy_IDGroup_Update, METH_VARARGS, + {"update", (PyCFunction)BPy_IDGroup_Update, METH_O, "updates the values in the group with the values of another or a dict."}, {"convert_to_pyobject", (PyCFunction)BPy_IDGroup_ConvertToPy, METH_NOARGS, "return a purely python version of the group."}, From eb1d0e139f5dba57b487cc5d9149774175da16bd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 20 Dec 2008 17:09:45 +0000 Subject: [PATCH 084/252] Bugfix since rev 2, BLO_setversionnumber() was using sizeof(array), which gives the sizeof the pointer, not the array. On a 64bit system I assume this would set 8 chars of a 4 char array. Turns out this isnt such a problem since BLO_setversionnumber isn't used anymore but way as well commit. --- source/blender/readblenfile/intern/BLO_readblenfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c index ec71611b31d..aa853e13e48 100644 --- a/source/blender/readblenfile/intern/BLO_readblenfile.c +++ b/source/blender/readblenfile/intern/BLO_readblenfile.c @@ -67,7 +67,7 @@ char *headerMagic = "BLENDFI"; */ void BLO_setversionnumber(char array[4], int version) { - memset(array, 0, sizeof(array)); + memset(array, 0, sizeof(char)*4); array[1] = version / 100; array[2] = version % 100; From f288a43457a707f767282909747897616171fc94 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 21 Dec 2008 03:11:32 +0000 Subject: [PATCH 085/252] define WITH_CCGSUBSURF isnt used anymore --- source/blender/blenkernel/CMakeLists.txt | 2 -- source/blender/nodes/CMakeLists.txt | 2 -- source/blender/nodes/SConscript | 2 -- 3 files changed, 6 deletions(-) diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0ed4f38e457..04ca5c79a11 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -65,8 +65,6 @@ IF(WITH_PLAYER) SUBDIRS(bad_level_call_stubs) ENDIF(WITH_PLAYER) -ADD_DEFINITIONS(-DWITH_CCGSUBSURF) - BLENDERLIB(bf_blenkernel "${SRC}" "${INC}") IF(WITH_VERSE) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 22e732d046b..4e9e4c2f84f 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -55,8 +55,6 @@ IF(WITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) -ADD_DEFINITIONS(-DWITH_CCGSUBSURF) - BLENDERLIB(bf_nodes "${SRC}" "${INC}") IF(WITH_VERSE) diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index 91ca6cd8c81..881479387b5 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -46,6 +46,4 @@ if env['WITH_BF_QUICKTIME']: defs += ' WITH_QUICKTIME' incs += ' ' + env['BF_QUICKTIME_INC'] -defs += ' WITH_CCGSUBSURF ' - env.BlenderLib ( libname = 'nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core','player'], priority = [65, 20] ) From 601fb5e6fab8ab47863201654403851fb723f69b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 22 Dec 2008 10:52:17 +0000 Subject: [PATCH 086/252] Bugfix - Fixed crashes in Action Editor on Ctrl-L due to missing NULL checks. --- source/blender/src/edittime.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c index 2c37a0eb20f..bd45a528b8d 100644 --- a/source/blender/src/edittime.c +++ b/source/blender/src/edittime.c @@ -187,6 +187,9 @@ void transform_markers(int mode, int smode) // mode and smode unused here, for c } else markers= &G.scene->markers; + + if (markers == NULL) + return; for (marker= markers->first; marker; marker= marker->next) { if (marker->flag & SELECT) totmark++; @@ -442,6 +445,11 @@ void get_minmax_markers(short sel, float *first, float *last) int selcount = 0; markers= &(G.scene->markers); + if (markers == NULL) { + *first = 0.0f; + *last = 0.0f; + return; + } if (sel) for (marker= markers->first; marker; marker= marker->next) { @@ -494,6 +502,10 @@ TimeMarker *find_nearest_marker(ListBase *markers, int clip_y) getmouseco_areawin (mval); + /* sanity checks */ + if (markers == NULL) + return NULL; + /* first clip selection in Y */ if ((clip_y) && (mval[1] > 30)) return NULL; From 61587627975c4528f0d61e9f30f3d7589c6d6c35 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 22 Dec 2008 15:05:07 +0000 Subject: [PATCH 087/252] WIP - support for VRML PROTO's --- release/scripts/import_web3d.py | 569 +++++++++++++++++++++----------- 1 file changed, 371 insertions(+), 198 deletions(-) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index 06cde898ef2..a4b367b6df8 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -201,6 +201,7 @@ def vrmlFormat(data): NODE_NORMAL = 1 # {} NODE_ARRAY = 2 # [] NODE_REFERENCE = 3 # USE foobar +# NODE_PROTO = 4 # lines = [] @@ -211,6 +212,10 @@ def getNodePreText(i, words): if i>=len(lines): break + ''' + elif lines[i].startswith('PROTO'): + return NODE_PROTO, i+1 + ''' elif lines[i]=='{': # words.append(lines[i]) # no need # print "OK" @@ -239,11 +244,45 @@ def getNodePreText(i, words): # print "error value!!!", words return 0, -1 -def is_nodeline(i, words): +def is_protoline(i, words, proto_field_defs): + + node_type = NODE_NORMAL + # print "PRPTOTOOOO ---- test", i, lines[i] + if not lines[i].startswith('PROTO' ): + # print 'not a proto' + return node_type, -1 + + words[:] = lines[i].split() # TODO - maybe multiline proto's exist? + + i+=1 + if lines[i].startswith('['): # ']\n' + while not lines[i].startswith(']'): + proto_field_defs.append(lines[i].split()) + i+=1 + i+=1 # advance past the ']\n' + + if lines[i].startswith('{'): + node_type = NODE_NORMAL + i+=1 # advance past the '{\n' + + elif lines[i].startswith('['): # does this even exist??, add incase + node_type = NODE_ARRAY + i+=1 # advance past the '{\n' + + print "IS PROTO", i, node_type + return node_type, i + +def is_nodeline(i, words, proto_field_defs): if not lines[i][0].isalpha(): return 0, 0 + # Is this a prototype?? + proto_type, new_i = is_protoline(i, words, proto_field_defs) + if new_i != -1: + return proto_type, new_i + + # Simple "var [" type if lines[i+1] == '[': if lines[i].count('"') % 2 == 0: @@ -253,6 +292,7 @@ def is_nodeline(i, words): node_type, new_i = getNodePreText(i, words) if not node_type: + print "not node_type", lines[i] return 0, 0 # Ok, we have a { after some values @@ -311,10 +351,10 @@ def is_numline(i): return True except: return False - + class vrmlNode(object): - __slots__ = 'id', 'fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'FIELD_NAMESPACE', 'x3dNode' + __slots__ = 'id', 'fields', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode' def __init__(self, parent, node_type, lineno): self.id = None self.node_type = node_type @@ -333,7 +373,12 @@ class vrmlNode(object): # Store in the root node because each inline file needs its own root node and its own namespace self.DEF_NAMESPACE = None self.ROUTE_IPO_NAMESPACE = None + ''' self.FIELD_NAMESPACE = None + ''' + + + self.PROTO_NAMESPACE = None self.reference = None @@ -343,16 +388,25 @@ class vrmlNode(object): return self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict + self.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1" + self.proto_fields = [] # proto field usage "diffuseColor IS seatColor" self.children = [] self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types # Only available from the root node + ''' def getFieldDict(self): if self.FIELD_NAMESPACE != None: return self.FIELD_NAMESPACE else: return self.parent.getFieldDict() + ''' + def getProtoDict(self): + if self.PROTO_NAMESPACE != None: + return self.PROTO_NAMESPACE + else: + return self.parent.getProtoDict() def getDefDict(self): if self.DEF_NAMESPACE != None: @@ -368,9 +422,10 @@ class vrmlNode(object): def setRoot(self, filename): self.filename = filename - self.FIELD_NAMESPACE = {} + # self.FIELD_NAMESPACE = {} self.DEF_NAMESPACE = {} self.ROUTE_IPO_NAMESPACE = {} + self.PROTO_NAMESPACE = {} def isRoot(self): if self.filename == None: @@ -404,15 +459,17 @@ class vrmlNode(object): return self.id[0] return None - def getDefName(self): + def getSpecialTypeName(self, typename): self_real = self.getRealNode() - - if 'DEF' in self_real.id: - # print self_real.id - return self_real.id[ list(self_real.id).index('DEF')+1 ] - else: - return None - + try: return self_real.id[ list(self_real.id).index(typename)+1 ] + except: return None + + + def getDefName(self): + return self.getSpecialTypeName('DEF') + + def getProtoName(self): + return self.getSpecialTypeName('PROTO') def getChildrenBySpec(self, node_spec): # spec could be Transform, Shape, Appearance self_real = self.getRealNode() @@ -449,7 +506,21 @@ class vrmlNode(object): ancestry.append(self) for child in self.getRealNode().children: if child not in ancestry: - child.getSerialized(results, ancestry) + # We dont want to load proto's, they are only references + # We could enforce this elsewhere + + # Only add this in a very special case + # where the parent of this object is not the real parent + # - In this case we have added the proto as a child to a node instancing it. + # This is a bit arbitary, but its how Proto's are done with this importer. + if child.getProtoName() == None: + child.getSerialized(results, ancestry) + else: + print "\n\n\n\nTEST!!!!!!!!!!!!!" + print child.getProtoName(), self.getSpec() + if child.getProtoName()==self.getSpec(): + print "PROTO!!!!!!!!!!!!!!!!\n" + child.getSerialized(results, ancestry) return results @@ -462,7 +533,7 @@ class vrmlNode(object): child.searchNodeTypeID(node_spec, results) return results - def getFieldName(self, field): + def getFieldName(self, field, ancestry): self_real = self.getRealNode() # incase we're an instance for f in self_real.fields: @@ -470,14 +541,51 @@ class vrmlNode(object): if f and f[0] == field: # print '\tfound field', f - return f[1:] + if len(f)>=3 and f[1] == 'IS': # eg: 'diffuseColor IS legColor' + field_id = f[2] + + # print "\n\n\n\n\n\nFOND IS!!!" + f_proto_lookup = None + i = len(ancestry) + while i: + i -= 1 + node = ancestry[i] + + # Get the default value from the proto, this can be overwridden by the proto instace + # 'field SFColor legColor .8 .4 .7' + for f_def in node.proto_field_defs: + if len(f_def) >= 4: + if f_def[0]=='field' and f_def[2]==field_id: + f_proto_lookup = f_def[3:] + + # Node instance, Will be 1 up from the proto-node in the ancestry list. but NOT its parent. + # This is the setting as defined by the instance, including this setting is optional, + # and will override the default PROTO value + # eg: 'legColor 1 0 0' + for f_def in node.fields: + # print "\n\n\n\n\nASSSSSSSS", f_def + if len(f_def) >= 2: + if f_def[0]==field_id: + f_proto_lookup = f_def[1:] + # print "\n\n\n\nWOOOOHOOO", field, f_proto_lookup + + return f_proto_lookup + else: + # Not using a proto + return f[1:] # print '\tfield not found', field + + + # See if this is a proto name + + + return None - def getFieldAsInt(self, field, default): + def getFieldAsInt(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default if ',' in f: f = f[:f.index(',')] # strip after the comma @@ -491,10 +599,10 @@ class vrmlNode(object): print '\tvalue "%s" could not be used as an int for field "%s"' % (f[0], field) return default - def getFieldAsFloat(self, field, default): + def getFieldAsFloat(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default if ',' in f: f = f[:f.index(',')] # strip after the comma @@ -508,10 +616,10 @@ class vrmlNode(object): print '\tvalue "%s" could not be used as a float for field "%s"' % (f[0], field) return default - def getFieldAsFloatTuple(self, field, default): + def getFieldAsFloatTuple(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default # if ',' in f: f = f[:f.index(',')] # strip after the comma @@ -532,10 +640,10 @@ class vrmlNode(object): print '\tvalue "%s" could not be used as a float tuple for field "%s"' % (f, field) return default - def getFieldAsBool(self, field, default): + def getFieldAsBool(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default if ',' in f: f = f[:f.index(',')] # strip after the comma @@ -551,10 +659,10 @@ class vrmlNode(object): print '\t"%s" could not be used as a bool for field "%s"' % (f[1], field) return default - def getFieldAsString(self, field, default=None): + def getFieldAsString(self, field, default, ancestry): self_real = self.getRealNode() # incase we're an instance - f = self_real.getFieldName(field) + f = self_real.getFieldName(field, ancestry) if f==None: return default if len(f) < 1: print '\t"%s" wrong length for string conversion for field "%s"' % (f, field) @@ -576,7 +684,7 @@ class vrmlNode(object): print '\tvalue "%s" could not be used as a string for field "%s"' % (f[0], field) return default - def getFieldAsArray(self, field, group): + def getFieldAsArray(self, field, group, ancestry): ''' For this parser arrays are children ''' @@ -593,7 +701,7 @@ class vrmlNode(object): # For x3d, should work ok with vrml too # for x3d arrays are fields, vrml they are nodes, annoying but not tooo bad. - data_split = self.getFieldName(field) + data_split = self.getFieldName(field, ancestry) if not data_split: return [] array_data = ' '.join(data_split) @@ -660,7 +768,7 @@ class vrmlNode(object): return new_array - def getFieldAsStringArray(self, field): + def getFieldAsStringArray(self, field, ancestry): ''' Get a list of strings ''' @@ -698,7 +806,7 @@ class vrmlNode(object): def __repr__(self): level = self.getLevel() ind = ' ' * level - + print self.id if self.node_type==NODE_REFERENCE: brackets = '' elif self.node_type==NODE_NORMAL: @@ -717,7 +825,7 @@ class vrmlNode(object): text += ind + "(reference node)\n" return text - text += ind + 'FIELDS:\n' + text += ind + 'FIELDS:' + str(len(self.fields)) + '\n' for i,item in enumerate(self.fields): text += ind + 'FIELD:\n' @@ -743,7 +851,10 @@ class vrmlNode(object): # If we were an inline then try load the file if self.node_type == NODE_NORMAL and self.getSpec() == 'Inline': - url = self.getFieldAsString('url', None) + + ancestry = [] # Warning! - PROTO's using this wont work at all. + url = self.getFieldAsString('url', None, ancestry) + del ancestry if url != None: urls = [] @@ -786,7 +897,7 @@ class vrmlNode(object): lines.insert(0, 'root_node____') lines.append('}') ''' - ff = open('/test.txt', 'w') + ff = open('/root/test.txt', 'w') ff.writelines([l+'\n' for l in lines]) ''' @@ -801,8 +912,10 @@ class vrmlNode(object): return new_i def __parse(self, i): - # print 'parsing at', i, - # print i, self.id, self.lineno + ''' + print 'parsing at', i, + print i, self.id, self.lineno + ''' l = lines[i] if l=='[': @@ -811,9 +924,12 @@ class vrmlNode(object): i+=1 else: words = [] - node_type, new_i = is_nodeline(i, words) + proto_field_defs = [] + + node_type, new_i = is_nodeline(i, words, proto_field_defs) if not node_type: # fail for parsing new node. - raise "error" + print "Failed to parse new node" + raise ValueError if self.node_type==NODE_REFERENCE: # Only assign the reference and quit @@ -824,38 +940,55 @@ class vrmlNode(object): return new_i self.id = tuple(words) + self.proto_field_defs[:] = proto_field_defs # fill in DEF/USE key = self.getDefName() - if key != None: self.getDefDict()[ key ] = self + key = self.getProtoName() + proto_dict = self.getProtoDict() + if key != None: + proto_dict[ key ] = self + + else: # If we're a proto instance, add the proto node as our child. + spec = self.getSpec() + try: + self.children.append( proto_dict[spec] ) + #pass + except: + pass + + del spec + + del proto_dict, key + i = new_i # print self.id ok = True while ok: l = lines[i] - # print '\t', i, l + # print '\tDEBUG:', i, self.node_type, l if l=='': i+=1 continue if l=='}': - if self.node_type != NODE_NORMAL: - print 'wrong node ending, expected an } ' + str(i) - raise "" + if self.node_type != NODE_NORMAL: # also ends proto nodes, we may want a type for these too. + print 'wrong node ending, expected an } ' + str(i) + ' ' + str(self.node_type) + raise ValueError ### print "returning", i return i+1 if l==']': if self.node_type != NODE_ARRAY: - print 'wrong node ending, expected a ] ' + str(i) - raise "" + print 'wrong node ending, expected a ] ' + str(i) + ' ' + str(self.node_type) + raise ValueError ### print "returning", i return i+1 - node_type, new_i = is_nodeline(i, []) + node_type, new_i = is_nodeline(i, [], []) if node_type: # check text\n{ ### print '\t\tgroup', i child = vrmlNode(self, node_type, i) @@ -943,6 +1076,7 @@ class vrmlNode(object): # this IS a key but the previous value was not a key, ot it was a defined field. if (not iskey(field_context[-1])) or ((len(field_context)==3 and field_context[1]=='IS')): field_list.append(field_context) + field_context = [value[j]] else: # The last item was not a value, multiple keys are needed in some cases. @@ -965,17 +1099,26 @@ class vrmlNode(object): if value[0]=='field': # field SFFloat creaseAngle 4 + ''' #oldproto self.getFieldDict()[value[2]] = value[3:] # skip the first 3 values + ''' + #self.proto_field_defs.append(value) + self.proto_field_defs.append(value) else: # Get referenced field if len(value) >= 3 and value[1]=='IS': + self.fields.append(value) + + ''' try: value = [ value[0] ] + self.getFieldDict()[ value[2] ] except: print '\tWarning, field could not be found:', value, 'TODO add support for exposedField' print '\t', self.getFieldDict() self.fields.append(value) + ''' else: + print "ADDING '%s'" % value self.fields.append(value) i+=1 @@ -1014,13 +1157,14 @@ def vrml_parse(path): lines.append('}') # Use for testing our parsed output, so we can check on line numbers. - ''' - ff = open('/test.txt', 'w') + + ff = open('/root/test.txt', 'w') ff.writelines([l+'\n' for l in lines]) - ''' + ff.close() + # Now evaluate it - node_type, new_i = is_nodeline(0, []) + node_type, new_i = is_nodeline(0, [], []) if not node_type: return None, 'Error: VRML file has no starting Node' @@ -1195,12 +1339,12 @@ def translateScale(sca): mat[2][2] = sca[2] return mat -def translateTransform(node): - cent = node.getFieldAsFloatTuple('center', None) # (0.0, 0.0, 0.0) - rot = node.getFieldAsFloatTuple('rotation', None) # (0.0, 0.0, 1.0, 0.0) - sca = node.getFieldAsFloatTuple('scale', None) # (1.0, 1.0, 1.0) - scaori = node.getFieldAsFloatTuple('scaleOrientation', None) # (0.0, 0.0, 1.0, 0.0) - tx = node.getFieldAsFloatTuple('translation', None) # (0.0, 0.0, 0.0) +def translateTransform(node, ancestry): + cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0, 0.0) + rot = node.getFieldAsFloatTuple('rotation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) + sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0, 1.0) + scaori = node.getFieldAsFloatTuple('scaleOrientation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) + tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0, 0.0) if cent: cent_mat = TranslationMatrix(Vector(cent)).resize4x4() @@ -1232,11 +1376,11 @@ def translateTransform(node): return new_mat -def translateTexTransform(node): - cent = node.getFieldAsFloatTuple('center', None) # (0.0, 0.0) - rot = node.getFieldAsFloat('rotation', None) # 0.0 - sca = node.getFieldAsFloatTuple('scale', None) # (1.0, 1.0) - tx = node.getFieldAsFloatTuple('translation', None) # (0.0, 0.0) +def translateTexTransform(node, ancestry): + cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0) + rot = node.getFieldAsFloat('rotation', None, ancestry) # 0.0 + sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0) + tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0) if cent: @@ -1279,17 +1423,17 @@ def getFinalMatrix(node, mtx, ancestry): mtx = Matrix() for node_tx in transform_nodes: - mat = translateTransform(node_tx) + mat = translateTransform(node_tx, ancestry) mtx = mtx * mat return mtx -def importMesh_IndexedFaceSet(geom, bpyima): +def importMesh_IndexedFaceSet(geom, bpyima, ancestry): # print geom.lineno, geom.id, vrmlNode.DEF_NAMESPACE.keys() - ccw = geom.getFieldAsBool('ccw', True) - ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True) # per vertex or per face - ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True) + ccw = geom.getFieldAsBool('ccw', True, ancestry) + ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True, ancestry) # per vertex or per face + ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True, ancestry) # This is odd how point is inside Coordinate @@ -1298,14 +1442,14 @@ def importMesh_IndexedFaceSet(geom, bpyima): coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: ifs_points = coord.getFieldAsArray('point', 3) + if coord: ifs_points = coord.getFieldAsArray('point', 3, ancestry) else: coord = [] if not coord: print '\tWarnint: IndexedFaceSet has no points' return None, ccw - ifs_faces = geom.getFieldAsArray('coordIndex', 0) + ifs_faces = geom.getFieldAsArray('coordIndex', 0, ancestry) coords_tex = None if ifs_faces: # In rare cases this causes problems - no faces but UVs??? @@ -1315,8 +1459,8 @@ def importMesh_IndexedFaceSet(geom, bpyima): coords_tex = geom.getChildBySpec('TextureCoordinate') if coords_tex: - ifs_texpoints = coords_tex.getFieldAsArray('point', 2) - ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0) + ifs_texpoints = coords_tex.getFieldAsArray('point', 2, ancestry) + ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0, ancestry) if not ifs_texpoints: # IF we have no coords, then dont bother @@ -1329,11 +1473,11 @@ def importMesh_IndexedFaceSet(geom, bpyima): vcolor_spot = None # spot color when we dont have an array of colors if vcolor: # float to char - ifs_vcol = [[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3)] - ifs_color_index = geom.getFieldAsArray('colorIndex', 0) + ifs_vcol = [[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)] + ifs_color_index = geom.getFieldAsArray('colorIndex', 0, ancestry) if not ifs_vcol: - vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [])] + vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [], ancestry)] # Convert faces into somthing blender can use edges = [] @@ -1546,18 +1690,18 @@ def importMesh_IndexedFaceSet(geom, bpyima): return bpymesh, ccw -def importMesh_IndexedLineSet(geom): +def importMesh_IndexedLineSet(geom, ancestry): # VRML not x3d #coord = geom.getChildByName('coord') # 'Coordinate' coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: points = coord.getFieldAsArray('point', 3) + if coord: points = coord.getFieldAsArray('point', 3, ancestry) else: points = [] if not points: print '\tWarning: IndexedLineSet had no points' return None - ils_lines = geom.getFieldAsArray('coordIndex', 0) + ils_lines = geom.getFieldAsArray('coordIndex', 0, ancestry) lines = [] line = [] @@ -1596,11 +1740,11 @@ def importMesh_IndexedLineSet(geom): return bpycurve -def importMesh_PointSet(geom): +def importMesh_PointSet(geom, ancestry): # VRML not x3d #coord = geom.getChildByName('coord') # 'Coordinate' coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: points = coord.getFieldAsArray('point', 3) + if coord: points = coord.getFieldAsArray('point', 3, ancestry) else: points = [] # vcolor = geom.getChildByName('color') # blender dosnt have per vertex color @@ -1614,26 +1758,26 @@ GLOBALS['CIRCLE_DETAIL'] = 12 MATRIX_Z_TO_Y = RotationMatrix(90, 4, 'x') -def importMesh_Sphere(geom): +def importMesh_Sphere(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('radius', 0.5) * 2 # * 2 for the diameter + diameter = geom.getFieldAsFloat('radius', 0.5, ancestry) * 2 # * 2 for the diameter bpymesh = Mesh.Primitives.UVsphere(GLOBALS['CIRCLE_DETAIL'], GLOBALS['CIRCLE_DETAIL'], diameter) bpymesh.transform(MATRIX_Z_TO_Y) return bpymesh -def importMesh_Cylinder(geom): +def importMesh_Cylinder(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('radius', 1.0) * 2 # * 2 for the diameter - height = geom.getFieldAsFloat('height', 2) + diameter = geom.getFieldAsFloat('radius', 1.0, ancestry) * 2 # * 2 for the diameter + height = geom.getFieldAsFloat('height', 2, ancestry) bpymesh = Mesh.Primitives.Cylinder(GLOBALS['CIRCLE_DETAIL'], diameter, height) bpymesh.transform(MATRIX_Z_TO_Y) # Warning - Rely in the order Blender adds verts # not nice design but wont change soon. - bottom = geom.getFieldAsBool('bottom', True) - side = geom.getFieldAsBool('side', True) - top = geom.getFieldAsBool('top', True) + bottom = geom.getFieldAsBool('bottom', True, ancestry) + side = geom.getFieldAsBool('side', True, ancestry) + top = geom.getFieldAsBool('top', True, ancestry) if not top: # last vert is top center of tri fan. bpymesh.verts.delete([(GLOBALS['CIRCLE_DETAIL']+GLOBALS['CIRCLE_DETAIL'])+1]) @@ -1647,18 +1791,18 @@ def importMesh_Cylinder(geom): return bpymesh -def importMesh_Cone(geom): +def importMesh_Cone(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('bottomRadius', 1.0) * 2 # * 2 for the diameter - height = geom.getFieldAsFloat('height', 2) + diameter = geom.getFieldAsFloat('bottomRadius', 1.0, ancestry) * 2 # * 2 for the diameter + height = geom.getFieldAsFloat('height', 2, ancestry) bpymesh = Mesh.Primitives.Cone(GLOBALS['CIRCLE_DETAIL'], diameter, height) bpymesh.transform(MATRIX_Z_TO_Y) # Warning - Rely in the order Blender adds verts # not nice design but wont change soon. - bottom = geom.getFieldAsBool('bottom', True) - side = geom.getFieldAsBool('side', True) + bottom = geom.getFieldAsBool('bottom', True, ancestry) + side = geom.getFieldAsBool('side', True, ancestry) if not bottom: # last vert is on the bottom bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']+1]) @@ -1667,10 +1811,10 @@ def importMesh_Cone(geom): return bpymesh -def importMesh_Box(geom): +def importMesh_Box(geom, ancestry): # bpymesh = bpy.data.meshes.new() - size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0)) + size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0), ancestry) bpymesh = Mesh.Primitives.Cube(1.0) # Scale the box to the size set @@ -1714,7 +1858,7 @@ def importShape(node, ancestry): textx = appr.getChildBySpec('TextureTransform') if textx: - texmtx = translateTexTransform(textx) + texmtx = translateTexTransform(textx, ancestry) @@ -1726,28 +1870,28 @@ def importShape(node, ancestry): # all values between 0.0 and 1.0, defaults from VRML docs bpymat = bpy.data.materials.new() - bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2) - bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8]) + bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2, ancestry) + bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8], ancestry) # NOTE - blender dosnt support emmisive color # Store in mirror color and approximate with emit. - emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0]) + emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0], ancestry) bpymat.mirCol = emit bpymat.emit = (emit[0]+emit[1]+emit[2])/3.0 - bpymat.hard = int(1+(510*mat.getFieldAsFloat('shininess', 0.2))) # 0-1 -> 1-511 - bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0]) - bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0) + bpymat.hard = int(1+(510*mat.getFieldAsFloat('shininess', 0.2, ancestry))) # 0-1 -> 1-511 + bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0], ancestry) + bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0, ancestry) if bpymat.alpha < 0.999: bpymat.mode |= Material.Modes.ZTRANSP if ima: - ima_url = ima.getFieldAsString('url') + ima_url = ima.getFieldAsString('url', None, ancestry) if ima_url==None: - try: ima_url = ima.getFieldAsStringArray('url')[0] # in some cases we get a list of images. + try: ima_url = ima.getFieldAsStringArray('url', None, ancestry)[0] # in some cases we get a list of images. except: ima_url = None if ima_url==None: @@ -1772,8 +1916,8 @@ def importShape(node, ancestry): else: bpymat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL) - ima_repS = ima.getFieldAsBool('repeatS', True) - ima_repT = ima.getFieldAsBool('repeatT', True) + ima_repS = ima.getFieldAsBool('repeatS', True, ancestry) + ima_repT = ima.getFieldAsBool('repeatT', True, ancestry) # To make this work properly we'd need to scale the UV's too, better to ignore th # texture.repeat = max(1, ima_repS * 512), max(1, ima_repT * 512) @@ -1785,19 +1929,19 @@ def importShape(node, ancestry): geom_spec = geom.getSpec() ccw = True if geom_spec == 'IndexedFaceSet': - bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima) + bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima, ancestry) elif geom_spec == 'IndexedLineSet': - bpydata = importMesh_IndexedLineSet(geom) + bpydata = importMesh_IndexedLineSet(geom, ancestry) elif geom_spec == 'PointSet': - bpydata = importMesh_PointSet(geom) + bpydata = importMesh_PointSet(geom, ancestry) elif geom_spec == 'Sphere': - bpydata = importMesh_Sphere(geom) + bpydata = importMesh_Sphere(geom, ancestry) elif geom_spec == 'Box': - bpydata = importMesh_Box(geom) + bpydata = importMesh_Box(geom, ancestry) elif geom_spec == 'Cylinder': - bpydata = importMesh_Cylinder(geom) + bpydata = importMesh_Cylinder(geom, ancestry) elif geom_spec == 'Cone': - bpydata = importMesh_Cone(geom) + bpydata = importMesh_Cone(geom, ancestry) else: print '\tWarning: unsupported type "%s"' % geom_spec return @@ -1810,8 +1954,8 @@ def importShape(node, ancestry): bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpydata) if type(bpydata) == Types.MeshType: - is_solid = geom.getFieldAsBool('solid', True) - creaseAngle = geom.getFieldAsFloat('creaseAngle', None) + is_solid = geom.getFieldAsBool('solid', True, ancestry) + creaseAngle = geom.getFieldAsFloat('creaseAngle', None, ancestry) if creaseAngle != None: bpydata.maxSmoothAngle = 1+int(min(79, creaseAngle * RAD_TO_DEG)) @@ -1852,17 +1996,17 @@ def importShape(node, ancestry): bpyob.setMatrix( getFinalMatrix(node, None, ancestry) ) -def importLamp_PointLight(node): +def importLamp_PointLight(node, ancestry): vrmlname = node.getDefName() if not vrmlname: vrmlname = 'PointLight' - # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO - # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0)) # TODO - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0)) - intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher. - location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0)) - # is_on = node.getFieldAsBool('on', True) # TODO - radius = node.getFieldAsFloat('radius', 100.0) + # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO + # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO + color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry) + # is_on = node.getFieldAsBool('on', True, ancestry) # TODO + radius = node.getFieldAsFloat('radius', 100.0, ancestry) bpylamp = bpy.data.lamps.new() bpylamp.setType('Lamp') @@ -1874,15 +2018,15 @@ def importLamp_PointLight(node): return bpylamp, mtx -def importLamp_DirectionalLight(node): +def importLamp_DirectionalLight(node, ancestry): vrmlname = node.getDefName() if not vrmlname: vrmlname = 'DirectLight' # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0)) - direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0)) - intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher. - # is_on = node.getFieldAsBool('on', True) # TODO + color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) + direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry) + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + # is_on = node.getFieldAsBool('on', True, ancestry) # TODO bpylamp = bpy.data.lamps.new(vrmlname) bpylamp.setType('Sun') @@ -1896,20 +2040,20 @@ def importLamp_DirectionalLight(node): # looks like default values for beamWidth and cutOffAngle were swapped in VRML docs. -def importLamp_SpotLight(node): +def importLamp_SpotLight(node, ancestry): vrmlname = node.getDefName() if not vrmlname: vrmlname = 'SpotLight' - # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0) # TODO - # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0)) # TODO - beamWidth = node.getFieldAsFloat('beamWidth', 1.570796) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0)) - cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0)) - intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher. - location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0)) - # is_on = node.getFieldAsBool('on', True) # TODO - radius = node.getFieldAsFloat('radius', 100.0) + # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO + # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO + beamWidth = node.getFieldAsFloat('beamWidth', 1.570796, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) + cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry) + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry) + # is_on = node.getFieldAsBool('on', True, ancestry) # TODO + radius = node.getFieldAsFloat('radius', 100.0, ancestry) bpylamp = bpy.data.lamps.new(vrmlname) bpylamp.setType('Spot') @@ -1935,14 +2079,14 @@ def importLamp_SpotLight(node): def importLamp(node, spec, ancestry): if spec=='PointLight': - bpylamp,mtx = importLamp_PointLight(node) + bpylamp,mtx = importLamp_PointLight(node, ancestry) elif spec=='DirectionalLight': - bpylamp,mtx = importLamp_DirectionalLight(node) + bpylamp,mtx = importLamp_DirectionalLight(node, ancestry) elif spec=='SpotLight': - bpylamp,mtx = importLamp_SpotLight(node) + bpylamp,mtx = importLamp_SpotLight(node, ancestry) else: print "Error, not a lamp" - raise "" + raise ValueError bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpylamp) bpyob.setMatrix( getFinalMatrix(node, mtx, ancestry) ) @@ -1952,11 +2096,11 @@ def importViewpoint(node, ancestry): name = node.getDefName() if not name: name = 'Viewpoint' - fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - # jump = node.getFieldAsBool('jump', True) - orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0)) - position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 0.0)) - description = node.getFieldAsString('description', '') + fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + # jump = node.getFieldAsBool('jump', True, ancestry) + orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0), ancestry) + position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 0.0), ancestry) + description = node.getFieldAsString('description', '', ancestry) bpycam = bpy.data.cameras.new(name) @@ -1980,59 +2124,72 @@ def importTransform(node, ancestry): #def importTimeSensor(node): -def translatePositionInterpolator(node, ipo): - key = node.getFieldAsArray('key', 0) - keyValue = node.getFieldAsArray('keyValue', 3) - - loc_x = ipo.addCurve('LocX') - loc_y = ipo.addCurve('LocY') - loc_z = ipo.addCurve('LocZ') +def translatePositionInterpolator(node, ipo, ancestry): + key = node.getFieldAsArray('key', 0, ancestry) + keyValue = node.getFieldAsArray('keyValue', 3, ancestry) + try: + loc_x = ipo.addCurve('LocX') + loc_y = ipo.addCurve('LocY') + loc_z = ipo.addCurve('LocZ') + except ValueError: + return + loc_x.interpolation = loc_y.interpolation = loc_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR for i, time in enumerate(key): - x,y,z = keyValue[i] + try: x,y,z = keyValue[i] + except: continue loc_x.append((time,x)) loc_y.append((time,y)) loc_z.append((time,z)) -def translateOrientationInterpolator(node, ipo): - key = node.getFieldAsArray('key', 0) - keyValue = node.getFieldAsArray('keyValue', 4) +def translateOrientationInterpolator(node, ipo, ancestry): + key = node.getFieldAsArray('key', 0, ancestry) + keyValue = node.getFieldAsArray('keyValue', 4, ancestry) - rot_x = ipo.addCurve('RotX') - rot_y = ipo.addCurve('RotY') - rot_z = ipo.addCurve('RotZ') + try: + rot_x = ipo.addCurve('RotX') + rot_y = ipo.addCurve('RotY') + rot_z = ipo.addCurve('RotZ') + except ValueError: + return rot_x.interpolation = rot_y.interpolation = rot_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR for i, time in enumerate(key): + try: x,y,z,w = keyValue[i] + except: continue - mtx = translateRotation(keyValue[i]) + mtx = translateRotation((x,y,z,w)) eul = mtx.toEuler() rot_x.append((time,eul.x/10.0)) rot_y.append((time,eul.y/10.0)) rot_z.append((time,eul.z/10.0)) # Untested! -def translateScalarInterpolator(node, ipo): - key = node.getFieldAsArray('key', 0) - keyValue = node.getFieldAsArray('keyValue', 4) +def translateScalarInterpolator(node, ipo, ancestry): + key = node.getFieldAsArray('key', 0, ancestry) + keyValue = node.getFieldAsArray('keyValue', 4, ancestry) - sca_x = ipo.addCurve('SizeX') - sca_y = ipo.addCurve('SizeY') - sca_z = ipo.addCurve('SizeZ') + try: + sca_x = ipo.addCurve('ScaleX') + sca_y = ipo.addCurve('ScaleY') + sca_z = ipo.addCurve('ScaleZ') + except ValueError: + return sca_x.interpolation = sca_y.interpolation = sca_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR for i, time in enumerate(key): - x,y,z = keyValue[i] + try: x,y,z = keyValue[i] + except: continue sca_x.append((time,x/10.0)) sca_y.append((time,y/10.0)) sca_z.append((time,z/10.0)) -def translateTimeSensor(node, ipo): +def translateTimeSensor(node, ipo, ancestry): ''' Apply a time sensor to an IPO, VRML has many combinations of loop/start/stop/cycle times to give different results, for now just do the basics @@ -2041,15 +2198,15 @@ def translateTimeSensor(node, ipo): time_cu = ipo.addCurve('Time') time_cu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR - cycleInterval = node.getFieldAsFloat('cycleInterval', None) + cycleInterval = node.getFieldAsFloat('cycleInterval', None, ancestry) - startTime = node.getFieldAsFloat('startTime', 0.0) - stopTime = node.getFieldAsFloat('stopTime', 250.0) + startTime = node.getFieldAsFloat('startTime', 0.0, ancestry) + stopTime = node.getFieldAsFloat('stopTime', 250.0, ancestry) if cycleInterval != None: stopTime = startTime+cycleInterval - loop = node.getFieldAsBool('loop', False) + loop = node.getFieldAsBool('loop', False, ancestry) time_cu.append((1+startTime, 0.0)) time_cu.append((1+stopTime, 1.0/10.0))# anoying, the UI uses /10 @@ -2059,11 +2216,14 @@ def translateTimeSensor(node, ipo): time_cu.extend = Blender.IpoCurve.ExtendTypes.CYCLIC # or - EXTRAP, CYCLIC_EXTRAP, CONST, -def importRoute(node): +def importRoute(node, ancestry): ''' Animation route only at the moment ''' + if not hasattr(node, 'fields'): + return + routeIpoDict = node.getRouteIpoDict() def getIpo(id): @@ -2100,22 +2260,22 @@ ROUTE champFly001.bindTime TO vpTs.set_startTime if to_type == 'set_position': ipo = getIpo(to_id) set_data_from_node = defDict[from_id] - translatePositionInterpolator(set_data_from_node, ipo) + translatePositionInterpolator(set_data_from_node, ipo, ancestry) - if to_type == 'set_orientation': + if to_type in ('set_orientation', 'rotation'): ipo = getIpo(to_id) set_data_from_node = defDict[from_id] - translateOrientationInterpolator(set_data_from_node, ipo) + translateOrientationInterpolator(set_data_from_node, ipo, ancestry) if to_type == 'set_scale': ipo = getIpo(to_id) set_data_from_node = defDict[from_id] - translateScalarInterpolator(set_data_from_node, ipo) + translateScalarInterpolator(set_data_from_node, ipo, ancestry) - elif from_type == 'bindTime': + elif from_type =='bindTime': ipo = getIpo(from_id) time_node = defDict[to_id] - translateTimeSensor(time_node, ipo) + translateTimeSensor(time_node, ipo, ancestry) @@ -2147,6 +2307,12 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): # continue spec = node.getSpec() + ''' + prefix = node.getPrefix() + if prefix=='PROTO': + pass + el + ''' if spec=='Shape': importShape(node, ancestry) elif spec in ('PointLight', 'DirectionalLight', 'SpotLight'): @@ -2174,7 +2340,7 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): # After we import all nodes, route events - anim paths for node, ancestry in all_nodes: - importRoute(node) + importRoute(node, ancestry) for node, ancestry in all_nodes: if node.isRoot(): @@ -2289,24 +2455,31 @@ if __name__ == '__main__': # load_web3d('/fe/x3d/www.web3d.org/x3d/content/examples/Basic/StudentProjects/PlayRoom.x3d') # invalid UVs -''' -import os -# files = os.popen('find /fe/wrl -iname "*.wrl"').readlines() -# files = os.popen('find /fe/x3d -iname "*.x3d"').readlines() -files = os.popen('find /fe/x3d/X3dExamplesSavage -iname "*.x3d"').readlines() -files.sort() -tot = len(files) -for i, f in enumerate(files): - if i < 12803 or i > 1000000: - continue - #if i != 12686: - # continue + +def test(): + import os - f = f.strip() - print f, i, tot - sce = bpy.data.scenes.new(f.split('/')[-1]) - bpy.data.scenes.active = sce - # Window. - load_web3d(f, PREF_FLAT=True) -''' \ No newline at end of file + files = os.popen('find /fe/wrl -iname "*.wrl"').readlines() + # files = os.popen('find /fe/x3d -iname "*.x3d"').readlines() + # files = os.popen('find /fe/x3d/X3dExamplesSavage -iname "*.x3d"').readlines() + + files.sort() + tot = len(files) + for i, f in enumerate(files): + #if i < 126 or i > 1000000: + # continue + + if i < 181 or i > 1000000: + continue + + #if i != 12686: + # continue + + f = f.strip() + print f, i, tot + sce = bpy.data.scenes.new(str(i) + '_' + f.split('/')[-1]) + bpy.data.scenes.active = sce + # Window. + load_web3d(f, PREF_FLAT=True) + \ No newline at end of file From 05fc2aa9da96bb8451ec6c0db882d731914fdc3c Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 22 Dec 2008 16:56:14 +0000 Subject: [PATCH 088/252] pose_grab_with_ik_clear(): fix bug with memory used after being freed. --- source/blender/src/transform_conversions.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index f58eaefc628..dadeb71f73e 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -780,7 +780,7 @@ static void pose_grab_with_ik_clear(Object *ob) { bKinematicConstraint *data; bPoseChannel *pchan; - bConstraint *con; + bConstraint *con, *next; for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { /* clear all temporary lock flags */ @@ -788,7 +788,8 @@ static void pose_grab_with_ik_clear(Object *ob) pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* remove all temporary IK-constraints added */ - for (con= pchan->constraints.first; con; con= con->next) { + for (con= pchan->constraints.first; con; con= next) { + next= con->next; if (con->type==CONSTRAINT_TYPE_KINEMATIC) { data= con->data; if (data->flag & CONSTRAINT_IK_TEMP) { From 5a96981cc6d643c175397f2ec2369917332674f7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Dec 2008 06:47:43 +0000 Subject: [PATCH 089/252] improved PROTO support, works for many testfiles now. --- release/scripts/import_web3d.py | 221 +++++++++++++++++--------------- 1 file changed, 121 insertions(+), 100 deletions(-) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index a4b367b6df8..7542afcb5b9 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -36,6 +36,8 @@ __bpydoc__ = """\ This script is an importer for the X3D and VRML97 file formats. """ +DEBUG = False + # This should work without a blender at all try: from Blender.sys import exists @@ -244,44 +246,23 @@ def getNodePreText(i, words): # print "error value!!!", words return 0, -1 -def is_protoline(i, words, proto_field_defs): - - node_type = NODE_NORMAL - # print "PRPTOTOOOO ---- test", i, lines[i] - if not lines[i].startswith('PROTO' ): - # print 'not a proto' - return node_type, -1 - - words[:] = lines[i].split() # TODO - maybe multiline proto's exist? - - i+=1 - if lines[i].startswith('['): # ']\n' - while not lines[i].startswith(']'): - proto_field_defs.append(lines[i].split()) - i+=1 - i+=1 # advance past the ']\n' - - if lines[i].startswith('{'): - node_type = NODE_NORMAL - i+=1 # advance past the '{\n' - - elif lines[i].startswith('['): # does this even exist??, add incase - node_type = NODE_ARRAY - i+=1 # advance past the '{\n' - - print "IS PROTO", i, node_type - return node_type, i - -def is_nodeline(i, words, proto_field_defs): +def is_nodeline(i, words): if not lines[i][0].isalpha(): return 0, 0 + #if lines[i].startswith('field'): + # return 0, 0 + # Is this a prototype?? + if lines[i].startswith('PROTO'): + words[:] = lines[i].split() + return NODE_NORMAL, i+1 # TODO - assumes the next line is a '[\n', skip that + ''' proto_type, new_i = is_protoline(i, words, proto_field_defs) if new_i != -1: return proto_type, new_i - + ''' # Simple "var [" type if lines[i+1] == '[': @@ -292,7 +273,7 @@ def is_nodeline(i, words, proto_field_defs): node_type, new_i = getNodePreText(i, words) if not node_type: - print "not node_type", lines[i] + if DEBUG: print "not node_type", lines[i] return 0, 0 # Ok, we have a { after some values @@ -354,7 +335,7 @@ def is_numline(i): class vrmlNode(object): - __slots__ = 'id', 'fields', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode' + __slots__ = 'id', 'fields', 'proto_node', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode' def __init__(self, parent, node_type, lineno): self.id = None self.node_type = node_type @@ -369,6 +350,7 @@ class vrmlNode(object): # This is only set from the root nodes. # Having a filename also denotes a root node self.filename = None + self.proto_node = None # proto field definition eg: "field SFColor seatColor .6 .6 .1" # Store in the root node because each inline file needs its own root node and its own namespace self.DEF_NAMESPACE = None @@ -388,6 +370,7 @@ class vrmlNode(object): return self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict + self.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1" self.proto_fields = [] # proto field usage "diffuseColor IS seatColor" self.children = [] @@ -516,10 +499,10 @@ class vrmlNode(object): if child.getProtoName() == None: child.getSerialized(results, ancestry) else: - print "\n\n\n\nTEST!!!!!!!!!!!!!" - print child.getProtoName(), self.getSpec() + + if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), self.getSpec() if child.getProtoName()==self.getSpec(): - print "PROTO!!!!!!!!!!!!!!!!\n" + if DEBUG: "FoundProto!" child.getSerialized(results, ancestry) return results @@ -533,7 +516,7 @@ class vrmlNode(object): child.searchNodeTypeID(node_spec, results) return results - def getFieldName(self, field, ancestry): + def getFieldName(self, field, ancestry, AS_CHILD=False): self_real = self.getRealNode() # incase we're an instance for f in self_real.fields: @@ -546,39 +529,69 @@ class vrmlNode(object): # print "\n\n\n\n\n\nFOND IS!!!" f_proto_lookup = None + f_proto_child_lookup = None i = len(ancestry) while i: i -= 1 node = ancestry[i] + node = node.getRealNode() - # Get the default value from the proto, this can be overwridden by the proto instace - # 'field SFColor legColor .8 .4 .7' - for f_def in node.proto_field_defs: - if len(f_def) >= 4: - if f_def[0]=='field' and f_def[2]==field_id: - f_proto_lookup = f_def[3:] + # proto settings are stored in "self.proto_node" + if node.proto_node: + # Get the default value from the proto, this can be overwridden by the proto instace + # 'field SFColor legColor .8 .4 .7' + if AS_CHILD: + for child in node.proto_node.children: + #if child.id and len(child.id) >= 3 and child.id[2]==field_id: + if child.id and ('point' in child.id or 'points' in child.id): + f_proto_child_lookup = child + + else: + for f_def in node.proto_node.proto_field_defs: + if len(f_def) >= 4: + if f_def[0]=='field' and f_def[2]==field_id: + f_proto_lookup = f_def[3:] # Node instance, Will be 1 up from the proto-node in the ancestry list. but NOT its parent. # This is the setting as defined by the instance, including this setting is optional, # and will override the default PROTO value # eg: 'legColor 1 0 0' - for f_def in node.fields: - # print "\n\n\n\n\nASSSSSSSS", f_def - if len(f_def) >= 2: - if f_def[0]==field_id: - f_proto_lookup = f_def[1:] - # print "\n\n\n\nWOOOOHOOO", field, f_proto_lookup + if AS_CHILD: + for child in node.children: + if child.id and child.id[0]==field_id: + f_proto_child_lookup = child + else: + for f_def in node.fields: + if len(f_def) >= 2: + if f_def[0]==field_id: + if DEBUG: print "getFieldName(), found proto", f_def + f_proto_lookup = f_def[1:] + - return f_proto_lookup + if AS_CHILD: + if f_proto_child_lookup: + if DEBUG: + print "getFieldName() - AS_CHILD=True, child found" + print f_proto_child_lookup + return f_proto_child_lookup + else: + return f_proto_lookup else: - # Not using a proto - return f[1:] + if AS_CHILD: + return None + else: + # Not using a proto + return f[1:] + # print '\tfield not found', field # See if this is a proto name - - + if AS_CHILD: + child_array = None + for child in self_real.children: + if child.id and len(child.id) == 1 and child.id[0] == field: + return child return None @@ -690,13 +703,11 @@ class vrmlNode(object): ''' self_real = self.getRealNode() # incase we're an instance - child_array = None - for child in self_real.children: - # print "ID IS", child.id - if child.id and len(child.id) == 1 and child.id[0] == field: - child_array = child - break + child_array = self_real.getFieldName(field, ancestry, True) + #if type(child_array)==list: # happens occasionaly + # array_data = child_array + if child_array==None: # For x3d, should work ok with vrml too @@ -806,7 +817,6 @@ class vrmlNode(object): def __repr__(self): level = self.getLevel() ind = ' ' * level - print self.id if self.node_type==NODE_REFERENCE: brackets = '' elif self.node_type==NODE_NORMAL: @@ -825,14 +835,25 @@ class vrmlNode(object): text += ind + "(reference node)\n" return text + if self.proto_node: + text += ind + 'PROTO NODE...\n' + text += str(self.proto_node) + text += ind + 'PROTO NODE_DONE\n' + text += ind + 'FIELDS:' + str(len(self.fields)) + '\n' for i,item in enumerate(self.fields): text += ind + 'FIELD:\n' text += ind + str(item) +'\n' + + text += ind + 'PROTO_FIELD_DEFS:' + str(len(self.proto_field_defs)) + '\n' - #text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n' - text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n' + for i,item in enumerate(self.proto_field_defs): + text += ind + 'PROTO_FIELD:\n' + text += ind + str(item) +'\n' + + text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n' + #text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n' text += ind + 'CHILDREN: ' + str(len(self.children)) + '\n' for i, child in enumerate(self.children): @@ -843,8 +864,8 @@ class vrmlNode(object): return text - def parse(self, i): - new_i = self.__parse(i) + def parse(self, i, IS_PROTO_DATA=False): + new_i = self.__parse(i, IS_PROTO_DATA) # print self.id, self.getFilename() @@ -911,7 +932,7 @@ class vrmlNode(object): return new_i - def __parse(self, i): + def __parse(self, i, IS_PROTO_DATA=False): ''' print 'parsing at', i, print i, self.id, self.lineno @@ -924,9 +945,8 @@ class vrmlNode(object): i+=1 else: words = [] - proto_field_defs = [] - node_type, new_i = is_nodeline(i, words, proto_field_defs) + node_type, new_i = is_nodeline(i, words) if not node_type: # fail for parsing new node. print "Failed to parse new node" raise ValueError @@ -940,7 +960,6 @@ class vrmlNode(object): return new_i self.id = tuple(words) - self.proto_field_defs[:] = proto_field_defs # fill in DEF/USE key = self.getDefName() @@ -951,6 +970,17 @@ class vrmlNode(object): proto_dict = self.getProtoDict() if key != None: proto_dict[ key ] = self + + # Parse the proto nodes fields + self.proto_node = vrmlNode(self, NODE_ARRAY, new_i) + new_i = self.proto_node.parse(new_i) + + self.children.remove(self.proto_node) + + # print self.proto_node + + new_i += 1 # skip past the { + else: # If we're a proto instance, add the proto node as our child. spec = self.getSpec() @@ -988,12 +1018,10 @@ class vrmlNode(object): ### print "returning", i return i+1 - node_type, new_i = is_nodeline(i, [], []) + node_type, new_i = is_nodeline(i, []) if node_type: # check text\n{ - ### print '\t\tgroup', i child = vrmlNode(self, node_type, i) i = child.parse(i) - # print child.id, 'YYY' elif l=='[': # some files have these anonymous lists child = vrmlNode(self, NODE_ARRAY, i) @@ -1099,27 +1127,9 @@ class vrmlNode(object): if value[0]=='field': # field SFFloat creaseAngle 4 - ''' #oldproto - self.getFieldDict()[value[2]] = value[3:] # skip the first 3 values - ''' - #self.proto_field_defs.append(value) self.proto_field_defs.append(value) else: - # Get referenced field - if len(value) >= 3 and value[1]=='IS': - self.fields.append(value) - - ''' - try: - value = [ value[0] ] + self.getFieldDict()[ value[2] ] - except: - print '\tWarning, field could not be found:', value, 'TODO add support for exposedField' - print '\t', self.getFieldDict() - self.fields.append(value) - ''' - else: - print "ADDING '%s'" % value - self.fields.append(value) + self.fields.append(value) i+=1 def gzipOpen(path): @@ -1164,7 +1174,7 @@ def vrml_parse(path): # Now evaluate it - node_type, new_i = is_nodeline(0, [], []) + node_type, new_i = is_nodeline(0, []) if not node_type: return None, 'Error: VRML file has no starting Node' @@ -1180,9 +1190,8 @@ def vrml_parse(path): root.parse(0) # This prints a load of text - ''' - print root - ''' + if DEBUG: + print root return root, '' @@ -1199,7 +1208,7 @@ class x3dNode(vrmlNode): vrmlNode.__init__(self, parent, node_type, -1) self.x3dNode = x3dNode - def parse(self): + def parse(self, IS_PROTO_DATA=False): # print self.x3dNode.tagName define = self.x3dNode.getAttributeNode('DEF') @@ -1660,7 +1669,12 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): fv = f.verts for i,c in enumerate(fcol): color_index = fv[i].index # color index is vert index - if ifs_color_index: color_index = ifs_color_index[color_index] + if ifs_color_index: + try: + color_index = ifs_color_index[color_index] + except: + print '\tWarning: per vertex color index out of range' + continue if len(ifs_vcol) < color_index: c.r, c.g, c.b = ifs_vcol[color_index] @@ -1684,7 +1698,10 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): col = ifs_vcol[color_index] for i,c in enumerate(fcol): - c.r, c.g, c.b = col + try: + c.r, c.g, c.b = col + except: + pass # incase its not between 0 and 255 bpymesh.verts.delete([0,]) # EEKADOODLE @@ -2253,8 +2270,12 @@ ROUTE champFly001.bindTime TO vpTs.set_startTime for field in node.fields: if field and field[0]=='ROUTE': - from_id, from_type = field[1].split('.') - to_id, to_type = field[3].split('.') + try: + from_id, from_type = field[1].split('.') + to_id, to_type = field[3].split('.') + except: + print "Warning, invalid ROUTE", field + continue if from_type == 'value_changed': if to_type == 'set_position': @@ -2470,7 +2491,7 @@ def test(): #if i < 126 or i > 1000000: # continue - if i < 181 or i > 1000000: + if i != 1068: continue #if i != 12686: From 3a4ead8f0f5b4c8d7af96d8d1984d0469b0c200f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 24 Dec 2008 02:06:34 +0000 Subject: [PATCH 090/252] fix for own mistake - [#18119] Texture Paint: "clone from layer" button not drawn in buttons window --- source/blender/src/buttons_editing.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index c1539a46c86..7ba6f122d39 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -6416,7 +6416,7 @@ void brush_buttons(uiBlock *block, short sima, uiDefButF(block, NUMSLI, evt_nop, "Falloff ", 0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush"); uiDefButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, evt_nop, "P", 180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); uiDefButF(block, NUMSLI, evt_nop, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter"); - uiDefButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, evt_nop, "P", 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); + uiDefButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, evt_nop, "P", 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); uiBlockEndAlign(block); yco -= 110; @@ -6432,13 +6432,23 @@ void brush_buttons(uiBlock *block, short sima, } } else { - MTex *mtex= brush->mtex[brush->texact]; - - uiBlockSetCol(block, TH_BUT_SETTING2); - id= (mtex)? (ID*)mtex->tex: NULL; - xco= std_libbuttons(block, 0, yco, 0, NULL, evt_texbrowse, ID_TE, 0, id, NULL, menupoin, 0, 0, evt_texdel, 0, 0); - /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, evt_change, "Fixed", xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/ - uiBlockSetCol(block, TH_AUTO); + if ( + (sima==NULL) && /* 3D View */ + (settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0 && /* Projection Painting */ + (settings->imapaint.tool == PAINT_TOOL_CLONE) + ) { + butw = 130; + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_CLONE, B_REDR, "Clone Layer", 0,yco,butw,20, &settings->imapaint.flag, 0, 0, 0, 0, "Use another UV layer as clone source, otherwise use 3D the cursor as the source"); + } + else { + MTex *mtex= brush->mtex[brush->texact]; + + uiBlockSetCol(block, TH_BUT_SETTING2); + id= (mtex)? (ID*)mtex->tex: NULL; + xco= std_libbuttons(block, 0, yco, 0, NULL, evt_texbrowse, ID_TE, 0, id, NULL, menupoin, 0, 0, evt_texdel, 0, 0); + /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, evt_change, "Fixed", xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/ + uiBlockSetCol(block, TH_AUTO); + } } } From cbebe4ad46082198b5a59fd21efeb99b4e6fd7be Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 24 Dec 2008 15:46:26 +0000 Subject: [PATCH 091/252] * bpy curve api wouldn't give correct errors for bad arguments when appending nurbs. * the radius on the curves first point was ignored. * mesh_edges2curves.py was giving all points a tilt of 1.0 --- release/scripts/mesh_edges2curves.py | 6 +- source/blender/python/api2_2x/CurNurb.c | 122 ++++++++++-------------- source/blender/python/api2_2x/Curve.c | 2 - 3 files changed, 51 insertions(+), 79 deletions(-) diff --git a/release/scripts/mesh_edges2curves.py b/release/scripts/mesh_edges2curves.py index 006bdf10b49..670165dda51 100644 --- a/release/scripts/mesh_edges2curves.py +++ b/release/scripts/mesh_edges2curves.py @@ -112,7 +112,7 @@ def mesh2polys(): Window.EditMode(0) me = meshOb.getData(mesh=1) polygons= polysFromMesh(me) - w=t=1 + w = 1.0 cu= Curve.New() cu.name = me.name cu.setFlag(1) @@ -128,7 +128,7 @@ def mesh2polys(): vIdx= 0 v= poly[vIdx] - cu.appendNurb([v.co.x, v.co.y, v.co.z, w, t]) + cu.appendNurb((v.co.x, v.co.y, v.co.z, w)) vIdx += 1 cu[i].type= 0 # Poly Line @@ -139,7 +139,7 @@ def mesh2polys(): # Add all the points in the polyline. while vIdxpntsu; /* @@ -520,81 +517,58 @@ PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * value ) } else if( PySequence_Check( value ) ) { - size = PySequence_Size( value ); -/* printf("\ndbg: got a sequence of size %d\n", size ); */ - if( size == 4 || size == 5 || size == 6) { - BPoint *tmp; - - tmp = nurb->bp; /* save old pts */ - - nurb->bp = - ( BPoint * ) MEM_mallocN( sizeof( BPoint ) * - ( npoints + 1 ), - "CurNurb_append1" ); - if( !nurb->bp ) - return ( EXPP_ReturnPyObjError - ( PyExc_MemoryError, - "allocation failed" ) ); - - memmove( nurb->bp, tmp, sizeof( BPoint ) * npoints ); - if( tmp ) - MEM_freeN( tmp ); - - ++nurb->pntsu; - /* initialize new BPoint from old */ - memcpy( nurb->bp + npoints, nurb->bp, - sizeof( BPoint ) ); - - for( i = 0; i < 4; ++i ) { - PyObject *item = PySequence_GetItem( value, i ); - - if (item == NULL) - return NULL; - - - nurb->bp[npoints].vec[i] = ( float ) PyFloat_AsDouble( item ); - Py_DECREF( item ); - } - - if (size >= 5) { - PyObject *item = PySequence_GetItem( value, 4 ); - - if (item == NULL) - return NULL; - - nurb->bp[npoints].alfa = ( float ) PyFloat_AsDouble( item ); - Py_DECREF( item ); - } - else { - nurb->bp[npoints].alfa = 0.0f; - } - - if (size == 6) { - PyObject *item = PySequence_GetItem( value, 5 ); - - if (item == NULL) - return NULL; - - nurb->bp[npoints].radius = ( float ) PyFloat_AsDouble( item ); - Py_DECREF( item ); - } - else { - nurb->bp[npoints].radius = 1.0f; - } - - nurb->bp[npoints].weight = 0.0; /* softbody weight TODO - add access to this, is zero elsewhere but through blender is 1.0 by default */ - - makeknots( nurb, 1, nurb->flagu >> 1 ); - - } else { - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a sequence of 4 or 6 floats" ); + float xco, yco, zco, wval, tilt=0.0f, radius=1.0f; + PyObject *args; + BPoint *tmp; + + if (PyTuple_Check(args)) { + args= value; } + else { + args= PySequence_Tuple(value); + } + + if (!PyArg_ParseTuple(args, "ffff|ff", &xco, &yco, &zco, &wval, &tilt, &radius)) { + return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a sequence of 4 to 6 floats" ); + } + + if (args != value) { + Py_DECREF(args); + } + tmp = nurb->bp; /* save old pts */ + + nurb->bp = + ( BPoint * ) MEM_mallocN( sizeof( BPoint ) * + ( npoints + 1 ), + "CurNurb_append1" ); + if( !nurb->bp ) + return ( EXPP_ReturnPyObjError + ( PyExc_MemoryError, + "allocation failed" ) ); + + memmove( nurb->bp, tmp, sizeof( BPoint ) * npoints ); + if( tmp ) + MEM_freeN( tmp ); + + ++nurb->pntsu; + /* initialize new BPoint from old */ + memcpy( nurb->bp + npoints, nurb->bp, + sizeof( BPoint ) ); + + tmp= nurb->bp+npoints; + tmp->vec[0] = xco; + tmp->vec[1] = yco; + tmp->vec[2] = zco; + tmp->vec[3] = wval; + tmp->alfa = tilt; + tmp->radius = radius; + tmp->weight = 0.0; /* softbody weight TODO - add access to this, is zero elsewhere but through blender is 1.0 by default */ + + makeknots( nurb, 1, nurb->flagu >> 1 ); } else { /* bail with error */ - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a sequence of 4 to 6 floats" ); + return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a sequence of 4 to 6 floats" ); } diff --git a/source/blender/python/api2_2x/Curve.c b/source/blender/python/api2_2x/Curve.c index d1abde19de9..26208e600e6 100644 --- a/source/blender/python/api2_2x/Curve.c +++ b/source/blender/python/api2_2x/Curve.c @@ -822,7 +822,6 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * value ) new_nurb->bezt->f2 = SELECT; new_nurb->bezt->f3 = SELECT; new_nurb->bezt->hide = 0; - new_nurb->bezt->radius = 1.0; /* calchandlesNurb( new_nurb ); */ } else { /* set up bp */ new_nurb->pntsv = 1; @@ -832,7 +831,6 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * value ) new_nurb->flagv = 0; new_nurb->bp->f1 = 0; new_nurb->bp->hide = 0; - new_nurb->bp->radius = 1.0; new_nurb->knotsu = 0; /*makenots( new_nurb, 1, new_nurb->flagu >> 1); */ } From aa56346b1264f1a37992834b37f47ab48fd97380 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 24 Dec 2008 21:53:15 +0000 Subject: [PATCH 092/252] * disable back buffer selection drawing while projection painting (was redoing for every update while painting) * remove unneeded return from game engines py api - ConvertPythonToGameObject --- source/blender/src/drawview.c | 3 ++- source/gameengine/Ketsji/KX_GameObject.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 0942d5d1cdb..44b61c816a5 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -975,7 +975,8 @@ void backdrawview3d(int test) int m; #endif - if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || G.f & G_TEXTUREPAINT); + if( G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT ); + else if ((G.f & G_TEXTUREPAINT) && G.scene->toolsettings && (G.scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0); else if(G.obedit && G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)); else { G.vd->flag &= ~V3D_NEEDBACKBUFDRAW; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index e4a37b589a8..f2a554c6b2a 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -2082,7 +2082,6 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py PyErr_SetString(PyExc_TypeError, "Expected KX_GameObject or a string for a name of a KX_GameObject, None is invalid"); return false; } - return (py_none_ok ? true : false); } if (PyString_Check(value)) { From d91daaa5f690645153adf647c371262c9c6cb009 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 29 Dec 2008 14:26:36 +0000 Subject: [PATCH 093/252] MSVC project file update for ffmpeg device lib, release build --- projectfiles_vc9/blender/blender.vcproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projectfiles_vc9/blender/blender.vcproj b/projectfiles_vc9/blender/blender.vcproj index 8950ef822a1..a8c5fb0a5b5 100644 --- a/projectfiles_vc9/blender/blender.vcproj +++ b/projectfiles_vc9/blender/blender.vcproj @@ -73,7 +73,7 @@ Date: Mon, 29 Dec 2008 16:36:58 +0000 Subject: [PATCH 094/252] First batch of GE API cleanup. The principle is to replace most get/set methods of logic bricks by direct property access. To make porting of game code easier, the properties have usually the same type and use than the return values/parameters of the get/set methods. More details on http://wiki.blender.org/index.php/GameEngineDev/Python_API_Clean_Up Old methods are still available but will produce deprecation warnings on the console: " is deprecated, use the property instead" You can avoid these messages by turning on the "Ignore deprecation warnings" option in Game menu. PyDoc is updated to include the new properties and display a deprecation warning for the get/set methods that are being deprecated. --- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 4 + source/gameengine/Expressions/PyObjectPlus.h | 15 +- source/gameengine/Expressions/Value.cpp | 12 + source/gameengine/Expressions/Value.h | 5 + .../GameLogic/SCA_ActuatorSensor.cpp | 24 ++ .../gameengine/GameLogic/SCA_ActuatorSensor.h | 1 + .../gameengine/GameLogic/SCA_DelaySensor.cpp | 45 ++++ source/gameengine/GameLogic/SCA_DelaySensor.h | 1 + source/gameengine/GameLogic/SCA_ISensor.cpp | 222 ++++++++++++----- source/gameengine/GameLogic/SCA_ISensor.h | 12 +- .../GameLogic/SCA_JoystickSensor.cpp | 161 +++++++++++- .../gameengine/GameLogic/SCA_JoystickSensor.h | 3 + .../GameLogic/SCA_KeyboardSensor.cpp | 179 ++++++++++--- .../gameengine/GameLogic/SCA_KeyboardSensor.h | 16 +- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 235 +++++++++++------- source/gameengine/GameLogic/SCA_MouseSensor.h | 10 +- .../GameLogic/SCA_PropertyActuator.cpp | 35 +++ .../GameLogic/SCA_PropertyActuator.h | 1 + .../GameLogic/SCA_PropertySensor.cpp | 52 ++++ .../gameengine/GameLogic/SCA_PropertySensor.h | 1 + .../GameLogic/SCA_PythonController.cpp | 24 +- .../GameLogic/SCA_PythonController.h | 1 + .../GameLogic/SCA_RandomActuator.cpp | 64 ++++- .../gameengine/GameLogic/SCA_RandomActuator.h | 1 + .../GamePlayer/ghost/GPG_Application.cpp | 3 + source/gameengine/Ketsji/KX_PolyProxy.cpp | 32 +-- source/gameengine/PyDoc/KX_ActuatorSensor.py | 7 + source/gameengine/PyDoc/SCA_DelaySensor.py | 17 ++ source/gameengine/PyDoc/SCA_ILogicBrick.py | 9 + source/gameengine/PyDoc/SCA_ISensor.py | 34 ++- source/gameengine/PyDoc/SCA_JoystickSensor.py | 59 ++++- source/gameengine/PyDoc/SCA_KeyboardSensor.py | 67 ++++- source/gameengine/PyDoc/SCA_MouseSensor.py | 11 + .../gameengine/PyDoc/SCA_PropertyActuator.py | 11 + source/gameengine/PyDoc/SCA_PropertySensor.py | 17 ++ .../gameengine/PyDoc/SCA_PythonController.py | 10 + source/gameengine/PyDoc/SCA_RandomActuator.py | 32 +++ 37 files changed, 1184 insertions(+), 249 deletions(-) diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 4410763ec53..f046942af75 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -81,6 +81,7 @@ /***/ #include "GPU_extensions.h" +#include "Value.h" #ifdef __cplusplus extern "C" { @@ -139,6 +140,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool game2ipo = (SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0); bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0); + bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0); // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(area); @@ -195,6 +197,8 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetUseFixedTime(usefixed); ketsjiengine->SetTimingDisplay(frameRate, profile, properties); + CValue::SetDeprecationWarnings(nodepwarnings); + //lock frame and camera enabled - storing global values int tmp_lay= G.scene->lay; diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 3a054454a0b..55998ce1c97 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -185,7 +185,10 @@ static inline void Py_Fatal(const char *M) { #define KX_PYMETHODTABLE(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, (PY_METHODCHAR)class_name::method_name##_doc} -#define KX_PYMETHODTABLE_NOARG(class_name, method_name) \ +#define KX_PYMETHODTABLE_O(class_name, method_name) \ + {#method_name , (PyCFunction) class_name::sPy##method_name, METH_O, (PY_METHODCHAR)class_name::method_name##_doc} + +#define KX_PYMETHODTABLE_NOARGS(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, (PY_METHODCHAR)class_name::method_name##_doc} /** @@ -195,7 +198,15 @@ static inline void Py_Fatal(const char *M) { const 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) \ +#define KX_PYMETHODDEF_DOC_VARARGS(class_name, method_name, doc_string) \ +const char class_name::method_name##_doc[] = doc_string; \ +PyObject* class_name::Py##method_name(PyObject*, PyObject* args) + +#define KX_PYMETHODDEF_DOC_O(class_name, method_name, doc_string) \ +const char class_name::method_name##_doc[] = doc_string; \ +PyObject* class_name::Py##method_name(PyObject*, PyObject* value) + +#define KX_PYMETHODDEF_DOC_NOARGS(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ PyObject* class_name::Py##method_name(PyObject*) diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 7296dfbec10..f2b5569c76e 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -32,6 +32,7 @@ ////////////////////////////////////////////////////////////////////// double CValue::m_sZeroVec[3] = {0.0,0.0,0.0}; +bool CValue::m_ignore_deprecation_warnings(false); #ifndef NO_EXP_PYTHON_EMBEDDING @@ -849,4 +850,15 @@ void CValue::SetValue(CValue* newval) } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// +/* deprecation warning management */ +void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings) +{ + m_ignore_deprecation_warnings = ignoreDeprecationWarnings; +} + +void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way) +{ + if (!m_ignore_deprecation_warnings) + printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way); +} diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 74fcdae5756..56a4991af27 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -318,6 +318,10 @@ public: STR_String op2str(VALUE_OPERATOR op); + /** enable/disable display of deprecation warnings */ + static void SetDeprecationWarnings(bool ignoreDeprecationWarnings); + /** Shows a deprecation warning */ + static void ShowDeprecationWarning(const char* method,const char* prop); // setting / getting flags inline void SetSelected(bool bSelected) { m_ValFlags.Selected = bSelected; } @@ -349,6 +353,7 @@ private: ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage) int m_refcount; // Reference Counter static double m_sZeroVec[3]; + static bool m_ignore_deprecation_warnings; }; diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index 7c37b237d60..5ad28dbf329 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -149,21 +149,44 @@ PyParentObject SCA_ActuatorSensor::Parents[] = { }; PyMethodDef SCA_ActuatorSensor::Methods[] = { + //Deprecated functions ------> {"getActuator", (PyCFunction) SCA_ActuatorSensor::sPyGetActuator, METH_NOARGS, (PY_METHODCHAR)GetActuator_doc}, {"setActuator", (PyCFunction) SCA_ActuatorSensor::sPySetActuator, METH_VARARGS, (PY_METHODCHAR)SetActuator_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; PyObject* SCA_ActuatorSensor::_getattr(const STR_String& attr) { + if (attr == "actuator") { + return PyString_FromString(m_checkactname); + } _getattr_up(SCA_ISensor); /* implicit return! */ } +int SCA_ActuatorSensor::_setattr(const STR_String& attr, PyObject *value) { + if (PyString_Check(value)) { + char* sval = PyString_AsString(value); + if (attr == "actuator") { + SCA_IActuator* act = GetParent()->FindActuator(STR_String(sval)); + if (act) { + m_checkactname = sval; + m_actuator = act; + return 0; + } + PyErr_SetString(PyExc_AttributeError, "string does not correspond to an actuator"); + return 1; + } + } + return SCA_ISensor::_setattr(attr, value); +} + /* 3. getActuator */ const char SCA_ActuatorSensor::GetActuator_doc[] = "getActuator()\n" "\tReturn the Actuator with which the sensor operates.\n"; PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self) { + ShowDeprecationWarning("getActuator()", "the actuator property"); return PyString_FromString(m_checkactname); } @@ -175,6 +198,7 @@ const char SCA_ActuatorSensor::SetActuator_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_ActuatorSensor::PySetActuator(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setActuator()", "the actuator property"); /* We should query whether the name exists. Or should we create a prop */ /* on the fly? */ char *actNameArg = NULL; diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index a71145f6852..4fe4700602c 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -62,6 +62,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); /* 3. setProperty */ KX_PYMETHOD_DOC(SCA_ActuatorSensor,SetActuator); diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index f15d4c7249f..362483b58a2 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -158,6 +158,7 @@ PyParentObject SCA_DelaySensor::Parents[] = { }; PyMethodDef SCA_DelaySensor::Methods[] = { + //Deprecated functions ------> /* setProperty */ {"setDelay", (PyCFunction) SCA_DelaySensor::sPySetDelay, METH_VARARGS, (PY_METHODCHAR)SetDelay_doc}, {"setDuration", (PyCFunction) SCA_DelaySensor::sPySetDuration, METH_VARARGS, (PY_METHODCHAR)SetDuration_doc}, @@ -166,13 +167,51 @@ PyMethodDef SCA_DelaySensor::Methods[] = { {"getDelay", (PyCFunction) SCA_DelaySensor::sPyGetDelay, METH_NOARGS, (PY_METHODCHAR)GetDelay_doc}, {"getDuration", (PyCFunction) SCA_DelaySensor::sPyGetDuration, METH_NOARGS, (PY_METHODCHAR)GetDuration_doc}, {"getRepeat", (PyCFunction) SCA_DelaySensor::sPyGetRepeat, METH_NOARGS, (PY_METHODCHAR)GetRepeat_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; PyObject* SCA_DelaySensor::_getattr(const STR_String& attr) { + if (attr == "delay") { + return PyInt_FromLong(m_delay); + } + if (attr == "duration") { + return PyInt_FromLong(m_duration); + } + if (attr == "repeat") { + return PyInt_FromLong(m_repeat); + } _getattr_up(SCA_ISensor); } +int SCA_DelaySensor::_setattr(const STR_String& attr, PyObject *value) { + if (PyInt_Check(value)) { + int ival = PyInt_AsLong(value); + if (attr == "delay") { + if (ival < 0) { + PyErr_SetString(PyExc_ValueError, "Delay cannot be negative"); + return 1; + } + m_delay = ival; + return 0; + } + if (attr == "duration") { + if (ival < 0) { + PyErr_SetString(PyExc_ValueError, "Duration cannot be negative"); + return 1; + } + m_duration = ival; + return 0; + } + if (attr == "repeat") { + m_repeat = (ival != 0); + return 0; + } + } + return SCA_ISensor::_setattr(attr, value); +} + + const char SCA_DelaySensor::SetDelay_doc[] = "setDelay(delay)\n" "\t- delay: length of the initial OFF period as number of frame\n" @@ -180,6 +219,7 @@ const char SCA_DelaySensor::SetDelay_doc[] = "\tSet the initial delay before the positive trigger\n"; PyObject* SCA_DelaySensor::PySetDelay(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setDelay()", "the delay property"); int delay; if(!PyArg_ParseTuple(args, "i", &delay)) { @@ -201,6 +241,7 @@ const char SCA_DelaySensor::SetDuration_doc[] = "\tIf > 0, a negative trigger is fired at the end of the ON pulse.\n"; PyObject* SCA_DelaySensor::PySetDuration(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setDuration()", "the duration property"); int duration; if(!PyArg_ParseTuple(args, "i", &duration)) { @@ -221,6 +262,7 @@ const char SCA_DelaySensor::SetRepeat_doc[] = "\tSet the sensor repeat mode\n"; PyObject* SCA_DelaySensor::PySetRepeat(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setRepeat()", "the repeat property"); int repeat; if(!PyArg_ParseTuple(args, "i", &repeat)) { @@ -235,6 +277,7 @@ const char SCA_DelaySensor::GetDelay_doc[] = "\tReturn the delay parameter value\n"; PyObject* SCA_DelaySensor::PyGetDelay(PyObject* self) { + ShowDeprecationWarning("getDelay()", "the delay property"); return PyInt_FromLong(m_delay); } @@ -243,6 +286,7 @@ const char SCA_DelaySensor::GetDuration_doc[] = "\tReturn the duration parameter value\n"; PyObject* SCA_DelaySensor::PyGetDuration(PyObject* self) { + ShowDeprecationWarning("getDuration()", "the duration property"); return PyInt_FromLong(m_duration); } @@ -251,6 +295,7 @@ const char SCA_DelaySensor::GetRepeat_doc[] = "\tReturn the repeat parameter value\n"; PyObject* SCA_DelaySensor::PyGetRepeat(PyObject* self) { + ShowDeprecationWarning("getRepeat()", "the repeat property"); return BoolToPyArg(m_repeat); } diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h index a997fabe3cd..ff3afe16542 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.h +++ b/source/gameengine/GameLogic/SCA_DelaySensor.h @@ -61,6 +61,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); /* setProperty */ KX_PYMETHOD_DOC(SCA_DelaySensor,SetDelay); diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index b10ac676464..6e46c8504bb 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -139,71 +139,6 @@ void SCA_ISensor::DecLink() { } } -/* python integration */ - -PyTypeObject SCA_ISensor::Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, - "SCA_ISensor", - sizeof(SCA_ISensor), - 0, - PyDestructor, - 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, - 0, - 0, - 0, - 0 -}; - -PyParentObject SCA_ISensor::Parents[] = { - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; -PyMethodDef SCA_ISensor::Methods[] = { - {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, - METH_NOARGS, (PY_METHODCHAR)IsPositive_doc}, - {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered, - METH_VARARGS, (PY_METHODCHAR)IsTriggered_doc}, - {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, - METH_NOARGS, (PY_METHODCHAR)GetUsePosPulseMode_doc}, - {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, - METH_VARARGS, (PY_METHODCHAR)SetUsePosPulseMode_doc}, - {"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency, - METH_NOARGS, (PY_METHODCHAR)GetFrequency_doc}, - {"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency, - METH_VARARGS, (PY_METHODCHAR)SetFrequency_doc}, - {"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode, - METH_NOARGS, (PY_METHODCHAR)GetUseNegPulseMode_doc}, - {"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode, - METH_VARARGS, (PY_METHODCHAR)SetUseNegPulseMode_doc}, - {"getInvert", (PyCFunction) SCA_ISensor::sPyGetInvert, - METH_NOARGS, (PY_METHODCHAR)GetInvert_doc}, - {"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert, - METH_VARARGS, (PY_METHODCHAR)SetInvert_doc}, - {"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel, - METH_NOARGS, (PY_METHODCHAR)GetLevel_doc}, - {"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel, - METH_VARARGS, (PY_METHODCHAR)SetLevel_doc}, - {"reset", (PyCFunction) SCA_ISensor::sPyReset, - METH_NOARGS, (PY_METHODCHAR)Reset_doc}, - {NULL,NULL} //Sentinel -}; - - -PyObject* -SCA_ISensor::_getattr(const STR_String& attr) -{ - _getattr_up(SCA_ILogicBrick); -} - - void SCA_ISensor::RegisterToManager() { // sensor is just activated, initialize it @@ -275,13 +210,17 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) } } } +/* ----------------------------------------------- */ +/* Python Functions */ +/* ----------------------------------------------- */ -/* Python functions: */ +//Deprecated Functions ------> const char SCA_ISensor::IsPositive_doc[] = "isPositive()\n" "\tReturns whether the sensor is in an active state.\n"; PyObject* SCA_ISensor::PyIsPositive(PyObject* self) { + ShowDeprecationWarning("isPositive()", "the read-only positive property"); int retval = IsPositiveTrigger(); return PyInt_FromLong(retval); } @@ -291,6 +230,7 @@ const char SCA_ISensor::IsTriggered_doc[] = "\tReturns whether the sensor has triggered the current controller.\n"; PyObject* SCA_ISensor::PyIsTriggered(PyObject* self) { + ShowDeprecationWarning("isTriggered()", "the read-only triggered property"); // check with the current controller int retval = 0; if (SCA_PythonController::m_sCurrentController) @@ -306,6 +246,7 @@ const char SCA_ISensor::GetUsePosPulseMode_doc[] = "\tReturns whether positive pulse mode is active.\n"; PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self) { + ShowDeprecationWarning("getUsePosPulseMode()", "the usePosPulseMode property"); return BoolToPyArg(m_pos_pulsemode); } @@ -319,6 +260,7 @@ const char SCA_ISensor::SetUsePosPulseMode_doc[] = "\tSet whether to do pulsing when positive pulses occur.\n"; PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setUsePosPulseMode()", "the usePosPulseMode property"); int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_pos_pulsemode = PyArgToBool(pyarg); @@ -333,6 +275,7 @@ const char SCA_ISensor::GetFrequency_doc[] = "\tReturns the frequency of the updates in pulse mode.\n" ; PyObject* SCA_ISensor::PyGetFrequency(PyObject* self) { + ShowDeprecationWarning("getFrequency()", "the frequency property"); return PyInt_FromLong(m_pulse_frequency); } @@ -346,6 +289,7 @@ const char SCA_ISensor::SetFrequency_doc[] = "\tIf the frequency is negative, it is set to 0.\n" ; PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrequency()", "the frequency property"); int pulse_frequencyArg = 0; if(!PyArg_ParseTuple(args, "i", &pulse_frequencyArg)) { @@ -368,6 +312,7 @@ const char SCA_ISensor::GetInvert_doc[] = "\tReturns whether or not pulses from this sensor are inverted.\n" ; PyObject* SCA_ISensor::PyGetInvert(PyObject* self) { + ShowDeprecationWarning("getInvert()", "the invert property"); return BoolToPyArg(m_invert); } @@ -377,6 +322,7 @@ const char SCA_ISensor::SetInvert_doc[] = "\tSet whether to invert pulses.\n"; PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setInvert()", "the invert property"); int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_invert = PyArgToBool(pyarg); @@ -392,6 +338,7 @@ const char SCA_ISensor::GetLevel_doc[] = "\tA edge detector will wait for a state change before generating a pulse.\n"; PyObject* SCA_ISensor::PyGetLevel(PyObject* self) { + ShowDeprecationWarning("getLevel()", "the level property"); return BoolToPyArg(m_level); } @@ -401,6 +348,7 @@ const char SCA_ISensor::SetLevel_doc[] = "\tSet whether to detect level or edge transition when entering a state.\n"; PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setLevel()", "the level property"); int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_level = PyArgToBool(pyarg); @@ -412,6 +360,7 @@ const char SCA_ISensor::GetUseNegPulseMode_doc[] = "\tReturns whether negative pulse mode is active.\n"; PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self) { + ShowDeprecationWarning("getUseNegPulseMode()", "the useNegPulseMode property"); return BoolToPyArg(m_neg_pulsemode); } @@ -422,21 +371,156 @@ const char SCA_ISensor::SetUseNegPulseMode_doc[] = "\tSet whether to do pulsing when negative pulses occur.\n"; PyObject* SCA_ISensor::PySetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setUseNegPulseMode()", "the useNegPulseMode property"); int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_neg_pulsemode = PyArgToBool(pyarg); Py_Return; } +//<------Deprecated -const char SCA_ISensor::Reset_doc[] = +KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, "reset()\n" "\tReset sensor internal state, effect depends on the type of sensor and settings.\n" -"\tThe sensor is put in its initial state as if it was just activated.\n"; -PyObject* SCA_ISensor::PyReset(PyObject* self) +"\tThe sensor is put in its initial state as if it was just activated.\n") { Init(); Py_Return; } +/* ----------------------------------------------- */ +/* Python Integration Hooks */ +/* ----------------------------------------------- */ +PyTypeObject SCA_ISensor::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "SCA_ISensor", + sizeof(SCA_ISensor), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject SCA_ISensor::Parents[] = { + &SCA_ISensor::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; +PyMethodDef SCA_ISensor::Methods[] = { + //Deprecated functions -----> + {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, + METH_NOARGS, (PY_METHODCHAR)IsPositive_doc}, + {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered, + METH_VARARGS, (PY_METHODCHAR)IsTriggered_doc}, + {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, + METH_NOARGS, (PY_METHODCHAR)GetUsePosPulseMode_doc}, + {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, + METH_VARARGS, (PY_METHODCHAR)SetUsePosPulseMode_doc}, + {"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency, + METH_NOARGS, (PY_METHODCHAR)GetFrequency_doc}, + {"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency, + METH_VARARGS, (PY_METHODCHAR)SetFrequency_doc}, + {"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode, + METH_NOARGS, (PY_METHODCHAR)GetUseNegPulseMode_doc}, + {"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode, + METH_VARARGS, (PY_METHODCHAR)SetUseNegPulseMode_doc}, + {"getInvert", (PyCFunction) SCA_ISensor::sPyGetInvert, + METH_NOARGS, (PY_METHODCHAR)GetInvert_doc}, + {"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert, + METH_VARARGS, (PY_METHODCHAR)SetInvert_doc}, + {"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel, + METH_NOARGS, (PY_METHODCHAR)GetLevel_doc}, + {"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel, + METH_VARARGS, (PY_METHODCHAR)SetLevel_doc}, + //<----- Deprecated + KX_PYMETHODTABLE_NOARGS(SCA_ISensor, reset), + {NULL,NULL} //Sentinel +}; + +PyObject* +SCA_ISensor::_getattr(const STR_String& attr) +{ + if (attr == "usePosPulseMode") + return PyInt_FromLong(m_pos_pulsemode); + if (attr == "useNegPulseMode") + return PyInt_FromLong(m_neg_pulsemode); + if (attr == "frequency") + return PyInt_FromLong(m_pulse_frequency); + if (attr == "invert") + return PyInt_FromLong(m_invert); + if (attr == "level") + return PyInt_FromLong(m_level); + if (attr == "triggered") + { + int retval = 0; + if (SCA_PythonController::m_sCurrentController) + retval = SCA_PythonController::m_sCurrentController->IsTriggered(this); + return PyInt_FromLong(retval); + } + if (attr == "positive") + { + int retval = IsPositiveTrigger(); + return PyInt_FromLong(retval); + } + + _getattr_up(SCA_ILogicBrick); +} + +int SCA_ISensor::_setattr(const STR_String& attr, PyObject *value) +{ + if (attr == "triggered") + PyErr_SetString(PyExc_AttributeError, "attribute \"triggered\" is read only"); + if (attr == "positive") + PyErr_SetString(PyExc_AttributeError, "attribute \"positive\" is read only"); + + if (PyInt_Check(value)) + { + int val = PyInt_AsLong(value); + + if (attr == "usePosPulseMode") + { + m_pos_pulsemode = (val != 0); + return 0; + } + + if (attr == "useNegPulseMode") + { + m_neg_pulsemode = (val != 0); + return 0; + } + + if (attr == "invert") + { + m_invert = (val != 0); + return 0; + } + + if (attr == "level") + { + m_level = (val != 0); + return 0; + } + + if (attr == "frequency") + { + if (val < 0) + val = 0; + m_pulse_frequency = val; + return 0; + } + } + + return SCA_ILogicBrick::_setattr(attr, value); +} /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index d1872009291..1b57c4621e4 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -93,8 +93,7 @@ public: virtual bool Evaluate(CValue* event) = 0; virtual bool IsPositiveTrigger(); virtual void Init(); - - virtual PyObject* _getattr(const STR_String& attr); + virtual CValue* GetReplica()=0; /** Set parameters for the pulsing behaviour. @@ -141,6 +140,11 @@ public: { return !m_links; } /* Python functions: */ + + virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); + + //Deprecated functions -----> KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode); @@ -153,8 +157,8 @@ public: KX_PYMETHOD_DOC(SCA_ISensor,SetInvert); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetLevel); KX_PYMETHOD_DOC(SCA_ISensor,SetLevel); - KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,Reset); - + //<------ + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,reset); }; #endif //__SCA_ISENSOR diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 8b96840b149..ec5921bad85 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -304,6 +304,7 @@ PyParentObject SCA_JoystickSensor::Parents[] = { PyMethodDef SCA_JoystickSensor::Methods[] = { + //Deprecated functions ------> {"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, (PY_METHODCHAR)GetIndex_doc}, {"setIndex", (PyCFunction) SCA_JoystickSensor::sPySetIndex, METH_O, (PY_METHODCHAR)SetIndex_doc}, {"getAxis", (PyCFunction) SCA_JoystickSensor::sPyGetAxis, METH_NOARGS, (PY_METHODCHAR)GetAxis_doc}, @@ -313,27 +314,144 @@ PyMethodDef SCA_JoystickSensor::Methods[] = { {"setThreshold", (PyCFunction) SCA_JoystickSensor::sPySetThreshold, METH_VARARGS, (PY_METHODCHAR)SetThreshold_doc}, {"getButton", (PyCFunction) SCA_JoystickSensor::sPyGetButton, METH_NOARGS, (PY_METHODCHAR)GetButton_doc}, {"setButton", (PyCFunction) SCA_JoystickSensor::sPySetButton, METH_O, (PY_METHODCHAR)SetButton_doc}, - {"getButtonValue",(PyCFunction) SCA_JoystickSensor::sPyGetButtonValue, METH_NOARGS,(PY_METHODCHAR)GetButtonValue_doc}, {"getHat", (PyCFunction) SCA_JoystickSensor::sPyGetHat, METH_NOARGS, (PY_METHODCHAR)GetHat_doc}, {"setHat", (PyCFunction) SCA_JoystickSensor::sPySetHat, METH_VARARGS, (PY_METHODCHAR)SetHat_doc}, {"getNumAxes", (PyCFunction) SCA_JoystickSensor::sPyNumberOfAxes, METH_NOARGS, (PY_METHODCHAR)NumberOfAxes_doc}, {"getNumButtons",(PyCFunction) SCA_JoystickSensor::sPyNumberOfButtons,METH_NOARGS, (PY_METHODCHAR)NumberOfButtons_doc}, {"getNumHats", (PyCFunction) SCA_JoystickSensor::sPyNumberOfHats, METH_NOARGS, (PY_METHODCHAR)NumberOfHats_doc}, {"isConnected", (PyCFunction) SCA_JoystickSensor::sPyConnected, METH_NOARGS, (PY_METHODCHAR)Connected_doc}, + {"getButtonValue",(PyCFunction) SCA_JoystickSensor::sPyGetButtonValue, METH_NOARGS,(PY_METHODCHAR)GetButtonValue_doc}, + //<----- Deprecated + {"getButtonActiveList",(PyCFunction) SCA_JoystickSensor::sPyGetButtonActiveList, METH_NOARGS,(PY_METHODCHAR)GetButtonActiveList_doc}, + {"getButtonStatus",(PyCFunction) SCA_JoystickSensor::sPyGetButtonStatus, METH_VARARGS,(PY_METHODCHAR)GetButtonStatus_doc}, {NULL,NULL} //Sentinel }; PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + if (attr == "axisPosition") { + if(joy) + return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); + else + return Py_BuildValue("[iiii]", 0, 0, 0, 0); + } + if (attr == "numAxis") { + return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); + } + if (attr == "numButtons") { + return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); + } + if (attr == "numHats") { + return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); + } + if (attr == "connected") { + return PyBool_FromLong( joy ? joy->Connected() : 0 ); + } + if (attr == "index") { + return PyInt_FromLong(m_joyindex); + } + if (attr == "threshold") { + return PyInt_FromLong(m_precision); + } + if (attr == "button") { + return PyInt_FromLong(m_button); + } + if (attr == "axis") { + return Py_BuildValue("[ii]",m_axis, m_axisf); + } + if (attr == "hat") { + return Py_BuildValue("[ii]",m_hat, m_hatf); + } _getattr_up(SCA_ISensor); } +int SCA_JoystickSensor::_setattr(const STR_String& attr, PyObject *value) { + if (attr == "axisPosition") { + PyErr_SetString(PyExc_AttributeError, "axisPosition is read only"); + return 1; + } + if (attr == "numAxis") { + PyErr_SetString(PyExc_AttributeError, "numaxis is read only"); + return 1; + } + if (attr == "numButtons") { + PyErr_SetString(PyExc_AttributeError, "numbuttons is read only"); + return 1; + } + if (attr == "numHats") { + PyErr_SetString(PyExc_AttributeError, "numhats is read only"); + return 1; + } + if (attr == "connected") { + PyErr_SetString(PyExc_AttributeError, "connected is read only"); + return 1; + } + if (PyInt_Check(value)) { + int ival = PyInt_AsLong(value); + if (attr == "index") { + if (ival < 0 || ival >= JOYINDEX_MAX) { + PyErr_SetString(PyExc_ValueError, "joystick index out of range"); + return 1; + } + m_joyindex = ival; + } else if (attr == "threshold") { + m_precision = ival; + } else if (attr == "button") { + if (ival < 0) { + PyErr_SetString(PyExc_ValueError, "button out of range"); + return 1; + } + m_button = ival; + } + return 0; + } + if (PySequence_Check(value)) { + if (attr == "axis" || attr == "hat") { + if (PySequence_Size(value) != 2) { + PyErr_SetString(PyExc_ValueError, "value must be sequence of 2 integers"); + return 1; + } + int ival = -1; + int ivalf = -1; + PyObject *item = PySequence_GetItem(value, 0); /* new ref */ + ival = PyInt_AsLong(item); + Py_DECREF(item); + item = PySequence_GetItem(value, 1); /* new ref */ + ivalf = PyInt_AsLong(item); + Py_DECREF(item); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_ValueError, "one or more of the items in the sequence was not an integer"); + return 1; + } + if (attr == "axis") { + if (ival < 1 || ival > 2 || ivalf < 0 || ivalf > 3) { + PyErr_SetString(PyExc_ValueError, "items in the sequence are out of range"); + return 1; + } + m_axis = ival; + m_axisf = ivalf; + } else { + if (ival < 1 || ival > 2) { + PyErr_SetString(PyExc_ValueError, "items in the sequence are out of range"); + return 1; + } + m_hat = ival; + m_hatf = ivalf; + } + } + return 0; + } + return SCA_ISensor::_setattr(attr, value); +} + /* get index ---------------------------------------------------------- */ const char SCA_JoystickSensor::GetIndex_doc[] = "getIndex\n" "\tReturns the joystick index to use.\n"; PyObject* SCA_JoystickSensor::PyGetIndex( PyObject* self ) { + ShowDeprecationWarning("getIndex()", "the index property"); return PyInt_FromLong(m_joyindex); } @@ -343,6 +461,7 @@ const char SCA_JoystickSensor::SetIndex_doc[] = "setIndex\n" "\tSets the joystick index to use.\n"; PyObject* SCA_JoystickSensor::PySetIndex( PyObject* self, PyObject* value ) { + ShowDeprecationWarning("setIndex()", "the index property"); 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"); @@ -358,6 +477,7 @@ const char SCA_JoystickSensor::GetAxis_doc[] = "getAxis\n" "\tReturns the current axis this sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) { + ShowDeprecationWarning("getAxis()", "the axis property"); return Py_BuildValue("[ii]",m_axis, m_axisf); } @@ -367,6 +487,7 @@ const char SCA_JoystickSensor::SetAxis_doc[] = "setAxis\n" "\tSets the current axis this sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) { + ShowDeprecationWarning("setAxis()", "the axis property"); int axis,axisflag; if(!PyArg_ParseTuple(args, "ii", &axis, &axisflag)){ @@ -383,6 +504,7 @@ const char SCA_JoystickSensor::GetAxisValue_doc[] = "getAxisValue\n" "\tReturns a list of the values for the current state of each axis.\n"; PyObject* SCA_JoystickSensor::PyGetAxisValue( PyObject* self) { + ShowDeprecationWarning("getAxisValue()", "the axisPosition property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); if(joy) return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); @@ -396,6 +518,7 @@ const char SCA_JoystickSensor::GetThreshold_doc[] = "getThreshold\n" "\tReturns the threshold of the axis.\n"; PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) { + ShowDeprecationWarning("getThreshold()", "the threshold property"); return PyInt_FromLong(m_precision); } @@ -405,6 +528,7 @@ const char SCA_JoystickSensor::SetThreshold_doc[] = "setThreshold\n" "\tSets the threshold of the axis.\n"; PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) { + ShowDeprecationWarning("setThreshold()", "the threshold property"); int thresh; if(!PyArg_ParseTuple(args, "i", &thresh)){ return NULL; @@ -418,6 +542,7 @@ const char SCA_JoystickSensor::GetButton_doc[] = "getButton\n" "\tReturns the current button this sensor is checking.\n"; PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) { + ShowDeprecationWarning("getButton()", "the button property"); return PyInt_FromLong(m_button); } @@ -426,6 +551,7 @@ const char SCA_JoystickSensor::SetButton_doc[] = "setButton\n" "\tSets the button the sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* value ) { + ShowDeprecationWarning("setButton()", "the button property"); int button = PyInt_AsLong(value); if(button==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "expected an int"); @@ -440,6 +566,15 @@ const char SCA_JoystickSensor::GetButtonValue_doc[] = "getButtonValue\n" "\tReturns a list containing the indicies of the current pressed state of each button.\n"; PyObject* SCA_JoystickSensor::PyGetButtonValue( PyObject* self) { + ShowDeprecationWarning("getButtonValue()", "getButtonActiveList"); + return PyGetButtonActiveList(self); +} + +/* get button active list -------------------------------------------------- */ +const char SCA_JoystickSensor::GetButtonActiveList_doc[] = +"getButtonActiveList\n" +"\tReturns a list containing the indicies of the button currently pressed.\n"; +PyObject* SCA_JoystickSensor::PyGetButtonActiveList( PyObject* self) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); PyObject *ls = PyList_New(0); PyObject *value; @@ -457,11 +592,30 @@ PyObject* SCA_JoystickSensor::PyGetButtonValue( PyObject* self) { return ls; } +/* get button status -------------------------------------------------- */ +const char SCA_JoystickSensor::GetButtonStatus_doc[] = +"getButtonStatus(buttonIndex)\n" +"\tReturns a bool of the current pressed state of the specified button.\n"; +PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* self, PyObject* args ) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + PyObject *value; + int index; + + if(!PyArg_ParseTuple(args, "i", &index)){ + return NULL; + } + if(joy && index >= 0 && index < joy->GetNumberOfButtons()) { + return PyBool_FromLong(joy->aButtonPressIsPositive(index) ? 1 : 0); + } + return PyBool_FromLong(0); +} + /* get hat ----------------------------------------------------------- */ const char SCA_JoystickSensor::GetHat_doc[] = "getHat\n" "\tReturns the current direction of the hat.\n"; PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) { + ShowDeprecationWarning("getHat()", "the hat property"); return Py_BuildValue("[ii]",m_hat, m_hatf); } @@ -471,6 +625,7 @@ const char SCA_JoystickSensor::SetHat_doc[] = "setHat\n" "\tSets the hat the sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) { + ShowDeprecationWarning("setHat()", "the hat property"); int hat,hatflag; if(!PyArg_ParseTuple(args, "ii", &hat, &hatflag)){ return NULL; @@ -486,6 +641,7 @@ const char SCA_JoystickSensor::NumberOfAxes_doc[] = "getNumAxes\n" "\tReturns the number of axes .\n"; PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) { + ShowDeprecationWarning("getNumAxes()", "the numAxis property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); // when the joystick is null their is 0 exis still. dumb but scripters should use isConnected() return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); @@ -496,6 +652,7 @@ const char SCA_JoystickSensor::NumberOfButtons_doc[] = "getNumButtons\n" "\tReturns the number of buttons .\n"; PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) { + ShowDeprecationWarning("getNumButtons()", "the numButtons property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); } @@ -505,6 +662,7 @@ const char SCA_JoystickSensor::NumberOfHats_doc[] = "getNumHats\n" "\tReturns the number of hats .\n"; PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) { + ShowDeprecationWarning("getNumHats()", "the numHats property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); } @@ -513,6 +671,7 @@ const 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 ) { + ShowDeprecationWarning("getConnected()", "the connected property"); 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 d316ad1119c..03653070db7 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -122,6 +122,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); /* Joystick Index */ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex); @@ -136,6 +137,8 @@ public: KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButton); KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetButton); KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButtonValue); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButtonActiveList); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,GetButtonStatus); /* Hats */ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetHat); KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetHat); diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index fa39a13679f..f880cd7768e 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -545,42 +545,17 @@ void SCA_KeyboardSensor::LogKeystrokes(void) /* ------------------------------------------------------------------------- */ -/* Python functions : specific */ +/* Python Functions */ /* ------------------------------------------------------------------------- */ - -PyObject* SCA_KeyboardSensor::PySetAllMode(PyObject* self, - PyObject* args, - PyObject* kwds) -{ - bool allkeys; - - if (!PyArg_ParseTuple(args, "i", &allkeys)) - { - return NULL; - } - - m_bAllKeys = allkeys; - Py_Return -} - - - -PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self, - PyObject* args, - PyObject* kwds) -{ -// printf("sPyIsPositive\n"); - return ((SCA_KeyboardSensor*) self)->PyIsPositive(self); -} - - +//Deprecated -----> /** 1. GetKey : check which key this sensor looks at */ const char SCA_KeyboardSensor::GetKey_doc[] = "getKey()\n" "\tReturn the code of the key this sensor is listening to.\n" ; PyObject* SCA_KeyboardSensor::PyGetKey(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getKey()", "the key property"); return PyInt_FromLong(m_hotkey); } @@ -591,6 +566,7 @@ const char SCA_KeyboardSensor::SetKey_doc[] = "\tSet the key this sensor should listen to.\n" ; PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setKey()", "the key property"); int keyCode; if(!PyArg_ParseTuple(args, "i", &keyCode)) { @@ -611,6 +587,7 @@ const char SCA_KeyboardSensor::GetHold1_doc[] = "\tsensor is listening to.\n" ; PyObject* SCA_KeyboardSensor::PyGetHold1(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getHold1()", "the hold1 property"); return PyInt_FromLong(m_qual); } @@ -621,6 +598,7 @@ const char SCA_KeyboardSensor::SetHold1_doc[] = "\tSet the first modifier to the key this sensor should listen to.\n" ; PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setHold1()", "the hold1 property"); int keyCode; if(!PyArg_ParseTuple(args, "i", &keyCode)) { @@ -641,6 +619,7 @@ const char SCA_KeyboardSensor::GetHold2_doc[] = "\tsensor is listening to.\n" ; PyObject* SCA_KeyboardSensor::PyGetHold2(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getHold2()", "the hold2 property"); return PyInt_FromLong(m_qual2); } @@ -651,6 +630,7 @@ const char SCA_KeyboardSensor::SetHold2_doc[] = "\tSet the first modifier to the key this sensor should listen to.\n" ; PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setHold2()", "the hold2 property"); int keyCode; if(!PyArg_ParseTuple(args, "i", &keyCode)) { @@ -671,6 +651,8 @@ const char SCA_KeyboardSensor::GetPressedKeys_doc[] = PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getPressedKeys()", "getEventList()"); + SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); int num = inputdev->GetNumJustEvents(); @@ -711,6 +693,8 @@ const char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] = PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys(PyObject* self, PyObject* args, PyObject* kwds) { +ShowDeprecationWarning("getCurrentlyPressedKeys()", "getEventList()"); + SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); int num = inputdev->GetNumActiveEvents(); @@ -743,9 +727,54 @@ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); Py_Return; } +//<---- Deprecated + +KX_PYMETHODDEF_DOC_NOARGS(SCA_KeyboardSensor, getEventList, +"getEventList()\n" +"\tGet the list of the keyboard events in this frame.\n") +{ + SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); + + PyObject* resultlist = PyList_New(0); + + for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++) + { + const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i); + if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) + { + PyObject* keypair = PyList_New(2); + PyList_SetItem(keypair,0,PyInt_FromLong(i)); + PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_Append(resultlist,keypair); + } + } + return resultlist; +} + +KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, +"getKeyStatus(keycode)\n" +"\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n") +{ + if (PyInt_Check(value)) + { + int keycode = PyInt_AsLong(value); + + if ((keycode < SCA_IInputDevice::KX_BEGINKEY) + || (keycode > SCA_IInputDevice::KX_ENDKEY)){ + PyErr_SetString(PyExc_AttributeError, "invalid keycode specified!"); + return NULL; + } + + SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); + const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode); + return PyInt_FromLong(inevent.m_status); + } + + Py_Return; +} /* ------------------------------------------------------------------------- */ -/* Python functions : integration hooks */ +/* Python Integration Hooks */ /* ------------------------------------------------------------------------- */ PyTypeObject SCA_KeyboardSensor::Type = { @@ -776,23 +805,91 @@ PyParentObject SCA_KeyboardSensor::Parents[] = { }; PyMethodDef SCA_KeyboardSensor::Methods[] = { - {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, (PY_METHODCHAR)GetKey_doc}, - {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, (PY_METHODCHAR)SetKey_doc}, - {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, (PY_METHODCHAR)GetHold1_doc}, - {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, (PY_METHODCHAR)SetHold1_doc}, - {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, (PY_METHODCHAR)GetHold2_doc}, - {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, (PY_METHODCHAR)SetHold2_doc}, -// {"getUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetUseAllKeys, METH_VARARGS, (PY_METHODCHAR)GetUseAllKeys_doc}, -// {"setUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPySetUseAllKeys, METH_VARARGS, (PY_METHODCHAR)SetUseAllKeys_doc}, - {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetPressedKeys_doc}, - {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetCurrentlyPressedKeys_doc}, -// {"getKeyEvents", (PyCFunction) SCA_KeyboardSensor::sPyGetKeyEvents, METH_VARARGS, (PY_METHODCHAR)GetKeyEvents_doc}, - {NULL,NULL} //Sentinel + //Deprecated functions ------> + {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, (PY_METHODCHAR)GetKey_doc}, + {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, (PY_METHODCHAR)SetKey_doc}, + {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, (PY_METHODCHAR)GetHold1_doc}, + {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, (PY_METHODCHAR)SetHold1_doc}, + {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, (PY_METHODCHAR)GetHold2_doc}, + {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, (PY_METHODCHAR)SetHold2_doc}, + {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetPressedKeys_doc}, + {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetCurrentlyPressedKeys_doc}, + //<----- Deprecated + KX_PYMETHODTABLE_NOARGS(SCA_KeyboardSensor, getEventList), + KX_PYMETHODTABLE_O(SCA_KeyboardSensor, getKeyStatus), + {NULL,NULL} //Sentinel }; PyObject* SCA_KeyboardSensor::_getattr(const STR_String& attr) { + if (attr == "key") + return PyInt_FromLong(m_hotkey); + + if (attr == "hold1") + return PyInt_FromLong(m_qual); + + if (attr == "hold2") + return PyInt_FromLong(m_qual2); + + if (attr == "toggleProperty") + return PyString_FromString(m_toggleprop); + + if (attr == "targetProperty") + return PyString_FromString(m_targetprop); + + if (attr == "useAllKeys") + return PyInt_FromLong(m_bAllKeys); + _getattr_up(SCA_ISensor); } +int SCA_KeyboardSensor::_setattr(const STR_String& attr, PyObject *value) +{ + if (PyInt_Check(value)) + { + int val = PyInt_AsLong(value); + + if (attr == "key") + { + m_hotkey = val; + return 0; + } + + if (attr == "hold1") + { + m_qual = val; + return 0; + } + + if (attr == "hold2") + { + m_qual2 = val; + return 0; + } + + if (attr == "useAllKeys") + { + m_bAllKeys = (val != 0); + return 0; + } + } + + if (PyString_Check(value)) + { + STR_String val = PyString_AsString(value); + if (attr == "logToggleProperty") + { + m_toggleprop = val; + return 0; + } + + if (attr == "logTargetProperty") + { + m_targetprop = val; + return 0; + } + } + + return SCA_ISensor::_setattr(attr, value); +} diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index b86f6931d27..4efbe9366cc 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -127,15 +127,9 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); - - PyObject* PySetAllMode(PyObject* self, - PyObject* args, - PyObject* kwds); - static PyObject* sPySetAllMode(PyObject* self, - PyObject* args, - PyObject* kwds); - + //Deprecated functions -----> /** 1. GetKey : check which key this sensor looks at */ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetKey); /** 2. SetKey: change the key to look at */ @@ -152,6 +146,12 @@ public: KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetPressedKeys); /** 9. GetCurrrentlyPressedKeys: */ KX_PYMETHOD_DOC(SCA_KeyboardSensor,GetCurrentlyPressedKeys); + // <------ + + // KeyEvents: + KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,getEventList); + // KeyStatus: + KX_PYMETHOD_DOC_O(SCA_KeyboardSensor,getKeyStatus); }; #endif //__KX_KEYBOARDSENSOR diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index d4952ce4777..9562003aec0 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -25,7 +25,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): José I. Romero (cleanup and fixes) * * ***** END GPL LICENSE BLOCK ***** */ @@ -59,6 +59,29 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, m_mousemode = mousemode; m_triggermode = true; + UpdateHotkey(); + Init(); +} + +void SCA_MouseSensor::Init() +{ + m_val = (m_invert)?1:0; /* stores the latest attribute */ + m_reset = true; +} + +SCA_MouseSensor::~SCA_MouseSensor() +{ + /* Nothing to be done here. */ +} + +void SCA_MouseSensor::UpdateHotkey() +{ + // gosh, this function is so damn stupid + // its here because of a design mistake in the mouse sensor, it should only + // have 3 trigger modes (button, wheel, move), and let the user set the + // hotkey separately, like the other sensors. but instead it has a mode for + // each friggin key and i have to update the hotkey based on it... genius! + switch (m_mousemode) { case KX_MOUSESENSORMODE_LEFTBUTTON: m_hotkey = SCA_IInputDevice::KX_LEFTMOUSE; @@ -78,22 +101,8 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, default: ; /* ignore, no hotkey */ } - Init(); } -void SCA_MouseSensor::Init() -{ - m_val = (m_invert)?1:0; /* stores the latest attribute */ - m_reset = true; -} - -SCA_MouseSensor::~SCA_MouseSensor() -{ - /* Nothing to be done here. */ -} - - - CValue* SCA_MouseSensor::GetReplica() { SCA_MouseSensor* replica = new SCA_MouseSensor(*this); @@ -137,15 +146,6 @@ bool SCA_MouseSensor::Evaluate(CValue* event) bool reset = m_reset && m_level; SCA_IInputDevice* mousedev = m_pMouseMgr->GetInputDevice(); - - -// SCA_ILogicBrick::RegisterEvent(event); -// if (m_mousemode == KX_MOUSESENSORMODE_MOVEMENT) cout << "\nChecking for movement..."; -//CValue* val = event->GetProperty("val"); - - /* both MOUSEX and MOUSEY. Treat all of these as key-presses. */ - /* So, treat KX_MOUSESENSORMODE_POSITION as */ - /* KX_MOUSESENSORMODE_POSITIONX || KX_MOUSESENSORMODE_POSITIONY */ m_reset = false; switch (m_mousemode) { case KX_MOUSESENSORMODE_LEFTBUTTON: @@ -155,42 +155,34 @@ bool SCA_MouseSensor::Evaluate(CValue* event) case KX_MOUSESENSORMODE_WHEELDOWN: { const SCA_InputEvent& event = mousedev->GetEventValue(m_hotkey); - if (event.m_status == SCA_InputEvent::KX_JUSTACTIVATED) - { + switch (event.m_status){ + case SCA_InputEvent::KX_JUSTACTIVATED: m_val = 1; result = true; - } else - { - if (event.m_status == SCA_InputEvent::KX_JUSTRELEASED) + break; + case SCA_InputEvent::KX_JUSTRELEASED: + m_val = 0; + result = true; + break; + case SCA_InputEvent::KX_ACTIVE: + if (m_val == 0) + { + m_val = 1; + if (m_level) + result = true; + } + break; + default: + if (m_val == 1) { m_val = 0; result = true; - } else - { - if (event.m_status == SCA_InputEvent::KX_ACTIVE) - { - if (m_val == 0) - { - m_val = 1; - if (m_level) - { - result = true; - } - } - } else - { - if (m_val == 1) - { - m_val = 0; - result = true; - } - } } + break; } break; } case KX_MOUSESENSORMODE_MOVEMENT: - { const SCA_InputEvent& eventX = mousedev->GetEventValue(SCA_IInputDevice::KX_MOUSEX); const SCA_InputEvent& eventY = mousedev->GetEventValue(SCA_IInputDevice::KX_MOUSEY); @@ -198,27 +190,26 @@ bool SCA_MouseSensor::Evaluate(CValue* event) if (eventX.m_status == SCA_InputEvent::KX_JUSTACTIVATED || eventY.m_status == SCA_InputEvent::KX_JUSTACTIVATED || eventX.m_status == SCA_InputEvent::KX_ACTIVE || - eventY.m_status == SCA_InputEvent::KX_ACTIVE) - + eventY.m_status == SCA_InputEvent::KX_ACTIVE) { m_val = 1; result = true; - } else - { - if (eventX.m_status == SCA_InputEvent::KX_JUSTRELEASED || + } + else if (eventX.m_status == SCA_InputEvent::KX_JUSTRELEASED || eventY.m_status == SCA_InputEvent::KX_JUSTRELEASED ) + { + m_val = 0; + result = true; + } + else //KX_NO_IMPUTSTATUS + { + if (m_val == 1) { m_val = 0; result = true; - } else - { - if (m_val == 1) - { - m_val = 0; - result = true; - } } } + break; } default: @@ -243,18 +234,67 @@ void SCA_MouseSensor::setY(short y) bool SCA_MouseSensor::isValid(SCA_MouseSensor::KX_MOUSESENSORMODE m) { - bool res = false; - - res = ((m > KX_MOUSESENSORMODE_NODEF) && (m < KX_MOUSESENSORMODE_MAX)); - - return res; + return ((m > KX_MOUSESENSORMODE_NODEF) && (m < KX_MOUSESENSORMODE_MAX)); } /* ------------------------------------------------------------------------- */ /* Python functions */ /* ------------------------------------------------------------------------- */ -/* Integration hooks ------------------------------------------------------- */ +//Deprecated functions ------> +/* get x position ---------------------------------------------------------- */ +const char SCA_MouseSensor::GetXPosition_doc[] = +"getXPosition\n" +"\tReturns the x-coordinate of the mouse sensor, in frame coordinates.\n" +"\tThe lower-left corner is the origin. The coordinate is given in\n" +"\tpixels\n"; +PyObject* SCA_MouseSensor::PyGetXPosition(PyObject* self, + PyObject* args, + PyObject* kwds) { + ShowDeprecationWarning("getXPosition()", "the position property"); + return PyInt_FromLong(m_x); +} + +/* get y position ---------------------------------------------------------- */ +const char SCA_MouseSensor::GetYPosition_doc[] = +"getYPosition\n" +"\tReturns the y-coordinate of the mouse sensor, in frame coordinates.\n" +"\tThe lower-left corner is the origin. The coordinate is given in\n" +"\tpixels\n"; +PyObject* SCA_MouseSensor::PyGetYPosition(PyObject* self, + PyObject* args, + PyObject* kwds) { + ShowDeprecationWarning("getYPosition()", "the position property"); + return PyInt_FromLong(m_y); +} +//<----- Deprecated + +KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, +"getButtonStatus(button)\n" +"\tGet the given button's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n") +{ + if (PyInt_Check(value)) + { + int button = PyInt_AsLong(value); + + if ((button < SCA_IInputDevice::KX_LEFTMOUSE) + || (button > SCA_IInputDevice::KX_MIDDLEMOUSE)){ + PyErr_SetString(PyExc_ValueError, "invalid button specified!"); + return NULL; + } + + SCA_IInputDevice* mousedev = m_pMouseMgr->GetInputDevice(); + const SCA_InputEvent& event = mousedev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) button); + return PyInt_FromLong(event.m_status); + } + + Py_Return; +} + +/* ------------------------------------------------------------------------- */ +/* Python Integration Hooks */ +/* ------------------------------------------------------------------------- */ + PyTypeObject SCA_MouseSensor::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -283,37 +323,54 @@ PyParentObject SCA_MouseSensor::Parents[] = { }; PyMethodDef SCA_MouseSensor::Methods[] = { + //Deprecated functions ------> {"getXPosition", (PyCFunction) SCA_MouseSensor::sPyGetXPosition, METH_VARARGS, (PY_METHODCHAR)GetXPosition_doc}, {"getYPosition", (PyCFunction) SCA_MouseSensor::sPyGetYPosition, METH_VARARGS, (PY_METHODCHAR)GetYPosition_doc}, + //<----- Deprecated + KX_PYMETHODTABLE_O(SCA_MouseSensor, getButtonStatus), {NULL,NULL} //Sentinel }; PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) { + if (attr == "position") + return Py_BuildValue("[ii]", m_x, m_y); + + if (attr == "mode") + return PyInt_FromLong(m_mousemode); + _getattr_up(SCA_ISensor); } -/* get x position ---------------------------------------------------------- */ -const char SCA_MouseSensor::GetXPosition_doc[] = -"getXPosition\n" -"\tReturns the x-coordinate of the mouse sensor, in frame coordinates.\n" -"\tThe lower-left corner is the origin. The coordinate is given in\n" -"\tpixels\n"; -PyObject* SCA_MouseSensor::PyGetXPosition(PyObject* self, - PyObject* args, - PyObject* kwds) { - return PyInt_FromLong(m_x); -} +int SCA_MouseSensor::_setattr(const STR_String& attr, PyObject *value) +{ + if (PyInt_Check(value)) + { + int val = PyInt_AsLong(value); -/* get y position ---------------------------------------------------------- */ -const char SCA_MouseSensor::GetYPosition_doc[] = -"getYPosition\n" -"\tReturns the y-coordinate of the mouse sensor, in frame coordinates.\n" -"\tThe lower-left corner is the origin. The coordinate is given in\n" -"\tpixels\n"; -PyObject* SCA_MouseSensor::PyGetYPosition(PyObject* self, - PyObject* args, - PyObject* kwds) { - return PyInt_FromLong(m_y); + if (attr == "mode") + { + if ((val < KX_MOUSESENSORMODE_NODEF) + || (val > KX_MOUSESENSORMODE_MAX)){ + + PyErr_SetString(PyExc_ValueError, "invalid mode specified!"); + return NULL; + } + + m_mousemode = val; + UpdateHotkey(); + return 0; + } + } + else + { + if (attr == "position") + { + PyErr_SetString(PyExc_AttributeError, "read-only property!"); + return NULL; + } + } + + return SCA_ISensor::_setattr(attr, value); } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 26a1c5e3fd2..6d6e641c798 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -24,7 +24,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): José I. Romero (cleanup and fixes) * * ***** END GPL LICENSE BLOCK ***** */ @@ -87,6 +87,8 @@ class SCA_MouseSensor : public SCA_ISensor bool isValid(KX_MOUSESENSORMODE); + void UpdateHotkey(); + SCA_MouseSensor(class SCA_MouseManager* keybdmgr, int startx,int starty, short int mousemode, @@ -108,11 +110,17 @@ class SCA_MouseSensor : public SCA_ISensor /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); + //Deprecated functions -----> /* read x-coordinate */ KX_PYMETHOD_DOC(SCA_MouseSensor,GetXPosition); /* read y-coordinate */ KX_PYMETHOD_DOC(SCA_MouseSensor,GetYPosition); + //<----- deprecated + + // get button status + KX_PYMETHOD_DOC_O(SCA_MouseSensor,getButtonStatus); }; diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index 3b541e87f02..f8509fe380e 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -245,17 +245,48 @@ PyParentObject SCA_PropertyActuator::Parents[] = { }; PyMethodDef SCA_PropertyActuator::Methods[] = { + //Deprecated functions ------> {"setProperty", (PyCFunction) SCA_PropertyActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, {"getProperty", (PyCFunction) SCA_PropertyActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, {"setValue", (PyCFunction) SCA_PropertyActuator::sPySetValue, METH_VARARGS, (PY_METHODCHAR)SetValue_doc}, {"getValue", (PyCFunction) SCA_PropertyActuator::sPyGetValue, METH_VARARGS, (PY_METHODCHAR)GetValue_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; PyObject* SCA_PropertyActuator::_getattr(const STR_String& attr) { + if (attr == "property") { + return PyString_FromString(m_propname); + } + if (attr == "value") { + return PyString_FromString(m_exprtxt); + } _getattr_up(SCA_IActuator); } +int SCA_PropertyActuator::_setattr(const STR_String& attr, PyObject *value) { + if (PyString_Check(value)) { + char* sval = PyString_AsString(value); + if (attr == "property") { + CValue* prop = GetParent()->FindIdentifier(sval); + bool error = prop->IsError(); + prop->Release(); + if (!prop->IsError()) { + m_propname = sval; + return 0; + } else { + PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); + return 1; + } + } + if (attr == "value") { + m_exprtxt = sval; + return 0; + } + } + return SCA_IActuator::_setattr(attr, value); +} + /* 1. setProperty */ const char SCA_PropertyActuator::SetProperty_doc[] = "setProperty(name)\n" @@ -264,6 +295,7 @@ const char SCA_PropertyActuator::SetProperty_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the 'property' property"); /* Check whether the name exists first ! */ char *nameArg; if (!PyArg_ParseTuple(args, "s", &nameArg)) { @@ -288,6 +320,7 @@ const char SCA_PropertyActuator::GetProperty_doc[] = "\tReturn the property on which the actuator operates.\n"; PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getProperty()", "the 'property' property"); return PyString_FromString(m_propname); } @@ -300,6 +333,7 @@ const char SCA_PropertyActuator::SetValue_doc[] = "\t action is ignored.\n"; PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setValue()", "the value property"); char *valArg; if(!PyArg_ParseTuple(args, "s", &valArg)) { return NULL; @@ -316,6 +350,7 @@ const char SCA_PropertyActuator::GetValue_doc[] = "\tReturns the value with which the actuator operates.\n"; PyObject* SCA_PropertyActuator::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getValue()", "the value property"); return PyString_FromString(m_exprtxt); } diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index 1e435684572..cdfeee4c67d 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -86,6 +86,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); // python wrapped methods KX_PYMETHOD_DOC(SCA_PropertyActuator,SetProperty); diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 64e3d49c6cb..19ee85207bb 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -333,25 +333,72 @@ PyParentObject SCA_PropertySensor::Parents[] = { }; PyMethodDef SCA_PropertySensor::Methods[] = { + //Deprecated functions ------> {"getType", (PyCFunction) SCA_PropertySensor::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc}, {"setType", (PyCFunction) SCA_PropertySensor::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc}, {"getProperty", (PyCFunction) SCA_PropertySensor::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, {"setProperty", (PyCFunction) SCA_PropertySensor::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, {"getValue", (PyCFunction) SCA_PropertySensor::sPyGetValue, METH_VARARGS, (PY_METHODCHAR)GetValue_doc}, {"setValue", (PyCFunction) SCA_PropertySensor::sPySetValue, METH_VARARGS, (PY_METHODCHAR)SetValue_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; PyObject* SCA_PropertySensor::_getattr(const STR_String& attr) { + if (attr == "type") { + return PyInt_FromLong(m_checktype); + } + if (attr == "property") { + return PyString_FromString(m_checkpropname); + } + if (attr == "value") { + return PyString_FromString(m_checkpropval); + } _getattr_up(SCA_ISensor); /* implicit return! */ } +int SCA_PropertySensor::_setattr(const STR_String& attr, PyObject *value) { + if (PyInt_Check(value)) { + int ival = PyInt_AsLong(value); + if (attr == "type") { + if ((ival <= KX_PROPSENSOR_NODEF) || (ival >= KX_PROPSENSOR_MAX)) { + PyErr_SetString(PyExc_ValueError, "type out of range"); + return 1; + } + m_checktype = ival; + } + return 0; + } + if (PyString_Check(value)) { + char* sval = PyString_AsString(value); + if (attr == "property") { + CValue *prop = FindIdentifier(STR_String(sval)); + bool error = prop->IsError(); + prop->Release(); + if (error) { + PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); + return 1; + } + m_checkpropname = sval; + } else if (attr == "value") { + if (!validValueForProperty(sval, m_checkpropname)) { + PyErr_SetString(PyExc_ValueError, "string does not represent a suitable value for the property"); + return 1; + } + m_checkpropval = sval; + } + return 0; + } + return SCA_ISensor::_setattr(attr, value); +} + /* 1. getType */ const char SCA_PropertySensor::GetType_doc[] = "getType()\n" "\tReturns the type of check this sensor performs.\n"; PyObject* SCA_PropertySensor::PyGetType(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getType()", "the type property"); return PyInt_FromLong(m_checktype); } @@ -364,6 +411,7 @@ const char SCA_PropertySensor::SetType_doc[] = "\tSet the type of check to perform.\n"; PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setType()", "the type property"); int typeArg; if (!PyArg_ParseTuple(args, "i", &typeArg)) { @@ -384,6 +432,7 @@ const char SCA_PropertySensor::GetProperty_doc[] = "\tReturn the property with which the sensor operates.\n"; PyObject* SCA_PropertySensor::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getProperty()", "the 'property' property"); return PyString_FromString(m_checkpropname); } @@ -395,6 +444,7 @@ const char SCA_PropertySensor::SetProperty_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the 'property' property"); /* We should query whether the name exists. Or should we create a prop */ /* on the fly? */ char *propNameArg = NULL; @@ -419,6 +469,7 @@ const char SCA_PropertySensor::GetValue_doc[] = "\tReturns the value with which the sensor operates.\n"; PyObject* SCA_PropertySensor::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getValue()", "the value property"); return PyString_FromString(m_checkpropval); } @@ -431,6 +482,7 @@ const char SCA_PropertySensor::SetValue_doc[] = "\t action is ignored.\n"; PyObject* SCA_PropertySensor::PySetValue(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setValue()", "the value property"); /* Here, we need to check whether the value is 'valid' for this property.*/ /* We know that the property exists, or is NULL. */ char *propValArg = NULL; diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index 6871cb3afdc..81203c78f9d 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -90,6 +90,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); /* 1. getType */ KX_PYMETHOD_DOC(SCA_PropertySensor,GetType); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index c354ab39747..e879481a444 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -233,9 +233,11 @@ PyMethodDef SCA_PythonController::Methods[] = { {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc}, {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc}, {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, (PY_METHODCHAR)SCA_PythonController::GetSensor_doc}, - {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS}, {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O}, + //Deprecated functions ------> + {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS}, {"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_NOARGS}, + //<----- Deprecated {NULL,NULL} //Sentinel }; @@ -329,9 +331,27 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) PyObject* SCA_PythonController::_getattr(const STR_String& attr) { + if (attr == "script") { + return PyString_FromString(m_scriptText); + } + if (attr == "state") { + return PyInt_FromLong(m_statemask); + } _getattr_up(SCA_IController); } +int SCA_PythonController::_setattr(const STR_String& attr, PyObject *value) +{ + if (attr == "script") { + PyErr_SetString(PyExc_AttributeError, "script is read only, use setScript() to update the script"); + return 1; + } + if (attr == "state") { + PyErr_SetString(PyExc_AttributeError, "state is read only"); + return 1; + } + return SCA_IController::_setattr(attr, value); +} PyObject* SCA_PythonController::PyGetActuators(PyObject* self) @@ -420,6 +440,7 @@ SCA_PythonController::PyGetSensors(PyObject* self) /* 1. getScript */ PyObject* SCA_PythonController::PyGetScript(PyObject* self) { + ShowDeprecationWarning("getScript()", "the script property"); return PyString_FromString(m_scriptText); } @@ -443,6 +464,7 @@ PyObject* SCA_PythonController::PySetScript(PyObject* self, PyObject* value) /* 1. getScript */ PyObject* SCA_PythonController::PyGetState(PyObject* self) { + ShowDeprecationWarning("getState()", "the state property"); return PyInt_FromLong(m_statemask); } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index d9b2e242bea..1918cc488d8 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -77,6 +77,7 @@ class SCA_PythonController : public SCA_IController static PyObject* sPyAddActiveActuator(PyObject* self, PyObject* args); virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetSensors); KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetActuators); diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 7b50a483cd8..8dd405c3d82 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -339,6 +339,7 @@ PyParentObject SCA_RandomActuator::Parents[] = { }; PyMethodDef SCA_RandomActuator::Methods[] = { + //Deprecated functions ------> {"setSeed", (PyCFunction) SCA_RandomActuator::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc}, {"getSeed", (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_VARARGS, (PY_METHODCHAR)GetSeed_doc}, {"getPara1", (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_VARARGS, (PY_METHODCHAR)GetPara1_doc}, @@ -346,6 +347,7 @@ PyMethodDef SCA_RandomActuator::Methods[] = { {"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_VARARGS, (PY_METHODCHAR)GetDistribution_doc}, {"setProperty", (PyCFunction) SCA_RandomActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, {"getProperty", (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, + //<----- Deprecated {"setBoolConst", (PyCFunction) SCA_RandomActuator::sPySetBoolConst, METH_VARARGS, (PY_METHODCHAR)SetBoolConst_doc}, {"setBoolUniform", (PyCFunction) SCA_RandomActuator::sPySetBoolUniform, METH_VARARGS, (PY_METHODCHAR)SetBoolUniform_doc}, {"setBoolBernouilli",(PyCFunction) SCA_RandomActuator::sPySetBoolBernouilli, METH_VARARGS, (PY_METHODCHAR)SetBoolBernouilli_doc}, @@ -360,9 +362,60 @@ PyMethodDef SCA_RandomActuator::Methods[] = { }; PyObject* SCA_RandomActuator::_getattr(const STR_String& attr) { + if (attr == "seed") { + return PyInt_FromLong(m_base->GetSeed()); + } + if (attr == "para1") { + return PyFloat_FromDouble(m_parameter1); + } + if (attr == "para2") { + return PyFloat_FromDouble(m_parameter2); + } + if (attr == "distribution") { + return PyInt_FromLong(m_distribution); + } + if (attr == "property") { + return PyString_FromString(m_propname); + } _getattr_up(SCA_IActuator); } +int SCA_RandomActuator::_setattr(const STR_String& attr, PyObject *value) +{ + if (attr == "para1") { + PyErr_SetString(PyExc_AttributeError, "para1 is read only"); + } + if (attr == "para2") { + PyErr_SetString(PyExc_AttributeError, "para2 is read only"); + } + if (attr == "distribution") { + PyErr_SetString(PyExc_AttributeError, "distribution is read only"); + } + if (PyInt_Check(value)) { + int ival = PyInt_AsLong(value); + if (attr == "seed") { + m_base->SetSeed(ival); + } + return 0; + } + if (PyString_Check(value)) { + char* sval = PyString_AsString(value); + if (attr == "property") { + CValue* prop = GetParent()->FindIdentifier(sval); + bool error = prop->IsError(); + prop->Release(); + if (!prop->IsError()) { + m_propname = sval; + return 0; + } else { + PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); + return 1; + } + } + } + return SCA_IActuator::_setattr(attr, value); +} + /* 1. setSeed */ const char SCA_RandomActuator::SetSeed_doc[] = "setSeed(seed)\n" @@ -371,6 +424,7 @@ const char SCA_RandomActuator::SetSeed_doc[] = "\tequal series. If the seed is 0, the generator will produce\n" "\tthe same value on every call.\n"; PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setSeed()", "the seed property"); long seedArg; if(!PyArg_ParseTuple(args, "i", &seedArg)) { return NULL; @@ -386,6 +440,7 @@ const char SCA_RandomActuator::GetSeed_doc[] = "\tReturns the initial seed of the generator. Equal seeds produce\n" "\tequal series.\n"; PyObject* SCA_RandomActuator::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getSeed()", "the seed property"); return PyInt_FromLong(m_base->GetSeed()); } @@ -396,6 +451,7 @@ const char SCA_RandomActuator::GetPara1_doc[] = "\tto the documentation of the generator types for the meaning\n" "\tof this value."; PyObject* SCA_RandomActuator::PyGetPara1(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getPara1()", "the para1 property"); return PyFloat_FromDouble(m_parameter1); } @@ -406,6 +462,7 @@ const char SCA_RandomActuator::GetPara2_doc[] = "\tto the documentation of the generator types for the meaning\n" "\tof this value."; PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getPara2()", "the para2 property"); return PyFloat_FromDouble(m_parameter2); } @@ -414,6 +471,7 @@ const char SCA_RandomActuator::GetDistribution_doc[] = "getDistribution()\n" "\tReturns the type of the active distribution.\n"; PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getDistribution()", "the distribution property"); return PyInt_FromLong(m_distribution); } @@ -424,6 +482,7 @@ const char SCA_RandomActuator::SetProperty_doc[] = "\tSet the property to which the random value is assigned. If the \n" "\tgenerator and property types do not match, the assignment is ignored.\n"; PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the 'property' property"); char *nameArg; if (!PyArg_ParseTuple(args, "s", &nameArg)) { return NULL; @@ -446,6 +505,7 @@ const char SCA_RandomActuator::GetProperty_doc[] = "\tReturn the property to which the random value is assigned. If the \n" "\tgenerator and property types do not match, the assignment is ignored.\n"; PyObject* SCA_RandomActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getProperty()", "the 'property' property"); return PyString_FromString(m_propname); } @@ -463,9 +523,7 @@ PyObject* SCA_RandomActuator::PySetBoolConst(PyObject* self, } m_distribution = KX_RANDOMACT_BOOL_CONST; - if (paraArg) { - m_parameter1 = 1; - } + m_parameter1 = (paraArg) ? 1.0 : 0.0; Py_Return; } diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index f6da0595d1a..2fc14f9a0b7 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -97,6 +97,7 @@ class SCA_RandomActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); /* 1. setSeed */ KX_PYMETHOD_DOC(SCA_RandomActuator,SetSeed); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index d0a2d0b05f2..e858c852b70 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -530,6 +530,7 @@ 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); + bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0); if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); @@ -604,6 +605,8 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) m_ketsjiengine->SetAudioDevice(m_audiodevice); m_ketsjiengine->SetTimingDisplay(frameRate, false, false); + CValue::SetDeprecationWarnings(nodepwarnings); + m_ketsjiengine->SetUseFixedTime(fixed_framerate); m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties); diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index c6f6bc2db01..bb9072b34dc 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -65,15 +65,15 @@ PyParentObject KX_PolyProxy::Parents[] = { }; 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_NOARGS(KX_PolyProxy,getMaterialIndex), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getNumVertex), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,isVisible), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,isCollider), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterialName), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getTextureName), KX_PYMETHODTABLE(KX_PolyProxy,getVertexIndex), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMesh), - KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterial), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMesh), + KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterial), {NULL,NULL} //Sentinel }; @@ -171,7 +171,7 @@ void KX_PolyProxy::ReplicaSetName(STR_String) {}; // stuff for python integration -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialIndex, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, "getMaterialIndex() : return the material index of the polygon in the mesh\n") { RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial(); @@ -186,31 +186,31 @@ KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialIndex, return PyInt_FromLong(matid); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getNumVertex, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex, "getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n") { return PyInt_FromLong(m_polygon->VertexCount()); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isVisible, +KX_PYMETHODDEF_DOC_NOARGS(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, +KX_PYMETHODDEF_DOC_NOARGS(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, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName, "getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n") { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getTextureName, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getTextureName, "getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n") { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); @@ -239,14 +239,14 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, return PyInt_FromLong(0); } -KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMesh, +KX_PYMETHODDEF_DOC_NOARGS(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, +KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial, "getMaterial() : returns a material\n") { RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial(); diff --git a/source/gameengine/PyDoc/KX_ActuatorSensor.py b/source/gameengine/PyDoc/KX_ActuatorSensor.py index cdfbf27576e..b0e138a8009 100644 --- a/source/gameengine/PyDoc/KX_ActuatorSensor.py +++ b/source/gameengine/PyDoc/KX_ActuatorSensor.py @@ -8,15 +8,22 @@ class KX_ActuatorSensor(SCA_ISensor): Actuator sensor detect change in actuator state of the parent object. It generates a positive pulse if the corresponding actuator is activated and a negative pulse if the actuator is deactivated. + + Properties: + + @ivar actuator: the name of the actuator that the sensor is monitoring. + @type actuator: string """ def getActuator(): """ + DEPRECATED: use the actuator property Return the Actuator with which the sensor operates. @rtype: string """ def setActuator(name): """ + DEPRECATED: use the actuator property Sets the Actuator with which to operate. If there is no Actuator of this name, the function has no effect. diff --git a/source/gameengine/PyDoc/SCA_DelaySensor.py b/source/gameengine/PyDoc/SCA_DelaySensor.py index 19df589ea7b..b99ed08bed5 100644 --- a/source/gameengine/PyDoc/SCA_DelaySensor.py +++ b/source/gameengine/PyDoc/SCA_DelaySensor.py @@ -13,9 +13,21 @@ class SCA_DelaySensor(SCA_ISensor): The sensor runs the OFF-ON cycle once unless the repeat option is set: the OFF-ON cycle repeats indefinately (or the OFF cycle if duration is 0). Use SCA_ISensor::reset() at any time to restart sensor. + + Properties: + + @ivar delay: length of the initial OFF period as number of frame, 0 for immediate trigger. + @type delay: integer. + @ivar duration: length of the ON period in number of frame after the initial OFF period. + If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. + @type duration: integer + @ivar repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. + @type repeat: integer + """ def setDelay(delay): """ + DEPRECATED: use the delay property Set the initial delay before the positive trigger. @param delay: length of the initial OFF period as number of frame, 0 for immediate trigger @@ -23,6 +35,7 @@ class SCA_DelaySensor(SCA_ISensor): """ def setDuration(duration): """ + DEPRECATED: use the duration property Set the duration of the ON pulse after initial delay and the generation of the positive trigger. If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. @@ -31,6 +44,7 @@ class SCA_DelaySensor(SCA_ISensor): """ def setRepeat(repeat): """ + DEPRECATED: use the repeat property Set if the sensor repeat mode. @param repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. @@ -38,18 +52,21 @@ class SCA_DelaySensor(SCA_ISensor): """ def getDelay(): """ + DEPRECATED: use the delay property Return the delay parameter value. @rtype: integer """ def getDuration(): """ + DEPRECATED: use the duration property Return the duration parameter value @rtype: integer """ def getRepeat(): """ + DEPRECATED: use the repeat property Return the repeat parameter value @rtype: KX_TRUE or KX_FALSE diff --git a/source/gameengine/PyDoc/SCA_ILogicBrick.py b/source/gameengine/PyDoc/SCA_ILogicBrick.py index ea09fcaea37..18cb900f28d 100644 --- a/source/gameengine/PyDoc/SCA_ILogicBrick.py +++ b/source/gameengine/PyDoc/SCA_ILogicBrick.py @@ -5,6 +5,9 @@ from KX_GameObject import * class SCA_ILogicBrick: """ Base class for all logic bricks. + + @ivar executePriority: This determines the order controllers are evaluated, and actuators are activated (lower priority is executed first). + @type executePriority: int """ def getOwner(): @@ -13,6 +16,8 @@ class SCA_ILogicBrick: @rtype: L{KX_GameObject} """ + + #--The following methods are deprecated-- def setExecutePriority(priority): """ Sets the priority of this logic brick. @@ -20,6 +25,8 @@ class SCA_ILogicBrick: This determines the order controllers are evaluated, and actuators are activated. Bricks with lower priority will be executed first. + Deprecated: Use the "executePriority" property instead. + @type priority: integer @param priority: the priority of this logic brick. """ @@ -27,6 +34,8 @@ class SCA_ILogicBrick: """ Gets the execution priority of this logic brick. + Deprecated: Use the "executePriority" property instead. + @rtype: integer @return: this logic bricks current priority. """ diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py index 14858505e24..ab35996aa50 100644 --- a/source/gameengine/PyDoc/SCA_ISensor.py +++ b/source/gameengine/PyDoc/SCA_ISensor.py @@ -5,8 +5,35 @@ from SCA_ILogicBrick import * class SCA_ISensor(SCA_ILogicBrick): """ Base class for all sensor logic bricks. + + @ivar usePosPulseMode: Flag to turn positive pulse mode on and off. + @type usePosPulseMode: boolean + @ivar useNegPulseMode: Flag to turn negative pulse mode on and off. + @type useNegPulseMode: boolean + @ivar frequency: The frequency for pulse mode sensors. + @type frequency: int + @ivar level: Flag to set whether to detect level or edge transition when entering a state. + It makes a difference only in case of logic state transition (state actuator). + A level detector will immediately generate a pulse, negative or positive + depending on the sensor condition, as soon as the state is activated. + A edge detector will wait for a state change before generating a pulse. + @type level: boolean + @ivar invert: Flag to set if this sensor activates on positive or negative events. + @type invert: boolean + @ivar triggered: True if this sensor brick is in a positive state. (Read only) + @type triggered: boolean + @ivar positive: True if this sensor brick is in a positive state. (Read only) + @type positive: boolean """ + def reset(): + """ + Reset sensor internal state, effect depends on the type of sensor and settings. + + The sensor is put in its initial state as if it was just activated. + """ + + #--The following methods are deprecated-- def isPositive(): """ True if this sensor brick is in a positive state. @@ -82,10 +109,3 @@ class SCA_ISensor(SCA_ILogicBrick): @param level: Detect level instead of edge? (KX_TRUE, KX_FALSE) @type level: boolean """ - def reset(): - """ - Reset sensor internal state, effect depends on the type of sensor and settings. - - The sensor is put in its initial state as if it was just activated. - """ - diff --git a/source/gameengine/PyDoc/SCA_JoystickSensor.py b/source/gameengine/PyDoc/SCA_JoystickSensor.py index d1dab9afcaf..111ee7f4cfa 100644 --- a/source/gameengine/PyDoc/SCA_JoystickSensor.py +++ b/source/gameengine/PyDoc/SCA_JoystickSensor.py @@ -5,15 +5,58 @@ from SCA_ISensor import * class SCA_JoystickSensor(SCA_ISensor): """ This sensor detects player joystick events. + + Properties: + + @ivar axisPosition: (read-only) The state of the joysticks axis as a list of 4 values, each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. + The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls. + left:[-32767, 0, ...], right:[32767, 0, ...], up:[0, -32767, ...], down:[0, 32767, ...] + @type axisPosition: [integer, integer, integer, integer] + @ivar numAxis: (read-only) The number of axes for the joystick at this index. + @type numAxis: integer + @ivar numButtons: (read-only) The number of buttons for the joystick at this index. + @type numButtons: integer + @ivar numHats: (read-only) The number of hats for the joystick at this index. + @type numHats: integer + @ivar connected: (read-only) True if a joystick is connected at this joysticks index. + @type connected: boolean + @ivar index: The joystick index to use (from 0 to 7). The first joystick is always 0. + @type index: integer + @ivar threshold: Axis threshold. Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive. + @type threshold: integer + @ivar button: The button index the sensor reacts to (first button = 0). When the "All Events" toggle is set, this option has no effect. + @type button: integer + @ivar axis: The axis this sensor reacts to, as a list of two values [axisIndex, axisDirection] + axisIndex: the axis index to use when detecting axis movement, 1=primary directional control, 2=secondary directional control. + axisDirection: 0=right, 1=up, 2=left, 3=down + @type axis: [integer, integer] + @ivar hat: The hat the sensor reacts to, as a list of two values: [hatIndex, hatDirection] + hatIndex: the hat index to use when detecting hat movement, 1=primary hat, 2=secondary hat. + hatDirection: 0-11 + @type hat: [integer, integer] """ + def getButtonActiveList(): + """ + Returns a list containing the indicies of the currently pressed buttons. + @rtype: list + """ + def getButtonStatus(buttonIndex): + """ + Returns a bool of the current pressed state of the specified button. + @param buttonIndex: the button index, 0=first button + @type buttonIndex: integer + @rtype: bool + """ def getIndex(): """ + DEPRECATED: use the 'index' property. Returns the joystick index to use (from 1 to 8). @rtype: integer """ def setIndex(index): """ + DEPRECATED: use the 'index' property. Sets the joystick index to use. @param index: The index of this joystick sensor, Clamped between 1 and 8. @type index: integer @@ -21,6 +64,7 @@ class SCA_JoystickSensor(SCA_ISensor): """ def getAxis(): """ + DEPRECATED: use the 'axis' property. Returns the current axis this sensor reacts to. See L{getAxisValue()} for the current axis state. @rtype: list @return: 2 values returned are [axisIndex, axisDirection] - see L{setAxis()} for their purpose. @@ -28,6 +72,7 @@ class SCA_JoystickSensor(SCA_ISensor): """ def setAxis(axisIndex, axisDirection): """ + DEPRECATED: use the 'axis' property. @param axisIndex: Set the axis index to use when detecting axis movement. @type axisIndex: integer from 1 to 2 @param axisDirection: Set the axis direction used for detecting motion. 0:right, 1:up, 2:left, 3:down. @@ -36,6 +81,7 @@ class SCA_JoystickSensor(SCA_ISensor): """ def getAxisValue(): """ + DEPRECATED: use the 'axisPosition' property. Returns the state of the joysticks axis. See differs to L{getAxis()} returning the current state of the joystick. @rtype: list @return: 4 values, each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. @@ -47,60 +93,71 @@ class SCA_JoystickSensor(SCA_ISensor): """ def getThreshold(): """ + DEPRECATED: use the 'threshold' property. Get the axis threshold. See L{setThreshold()} for details. @rtype: integer """ def setThreshold(threshold): """ + DEPRECATED: use the 'threshold' property. Set the axis threshold. @param threshold: Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive. @type threshold: integer """ def getButton(): """ + DEPRECATED: use the 'button' property. Returns the button index the sensor reacts to. See L{getButtonValue()} for a list of pressed buttons. @rtype: integer @note: When the "All Events" toggle is set, this option has no effect. """ def setButton(index): """ + DEPRECATED: use the 'button' property. Sets the button index the sensor reacts to when the "All Events" option is not set. @note: When the "All Events" toggle is set, this option has no effect. """ def getButtonValue(): """ + DEPRECATED: use the 'getButtonActiveList' method. Returns a list containing the indicies of the currently pressed buttons. @rtype: list """ def getHat(): """ + DEPRECATED: use the 'hat' property. Returns the current hat direction this sensor is set to. [hatNumber, hatDirection]. @rtype: list @note: When the "All Events" toggle is set, this option has no effect. """ - def setHat(index): + def setHat(index,direction): """ + DEPRECATED: use the 'hat' property. Sets the hat index the sensor reacts to when the "All Events" option is not set. @type index: integer """ def getNumAxes(): """ + DEPRECATED: use the 'numAxis' property. Returns the number of axes for the joystick at this index. @rtype: integer """ def getNumButtons(): """ + DEPRECATED: use the 'numButtons' property. Returns the number of buttons for the joystick at this index. @rtype: integer """ def getNumHats(): """ + DEPRECATED: use the 'numHats' property. Returns the number of hats for the joystick at this index. @rtype: integer """ def isConnected(): """ + DEPRECATED: use the 'connected' property. Returns True if a joystick is detected at this joysticks index. @rtype: bool """ diff --git a/source/gameengine/PyDoc/SCA_KeyboardSensor.py b/source/gameengine/PyDoc/SCA_KeyboardSensor.py index 2f741f7d6a2..f6a7a7d8a97 100644 --- a/source/gameengine/PyDoc/SCA_KeyboardSensor.py +++ b/source/gameengine/PyDoc/SCA_KeyboardSensor.py @@ -7,44 +7,99 @@ class SCA_KeyboardSensor(SCA_ISensor): A keyboard sensor detects player key presses. See module L{GameKeys} for keycode values. - """ + @ivar key: The key code this sensor is looking for. + @type key: keycode from L{GameKeys} module + @ivar hold1: The key code for the first modifier this sensor is looking for. + @type hold1: keycode from L{GameKeys} module + @ivar hold2: The key code for the second modifier this sensor is looking for. + @type hold2: keycode from L{GameKeys} module + @ivar toggleProperty: The name of the property that indicates whether or not to log keystrokes as a string. + @type toggleProperty: string + @ivar targetProperty: The name of the property that receives keystrokes in case in case a string is logged. + @type targetProperty: string + @ivar useAllKeys: Flag to determine whether or not to accept all keys. + @type useAllKeys: boolean + """ + def getEventList(): + """ + Get a list of pressed keys that have either been pressed, or just released, or are active this frame. + + @rtype: list of key status. [[keycode, status]] + @return: A list of keyboard events + """ + + def getKeyStatus(keycode): + """ + Get the status of a key. + + @rtype: key state (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED) + @return: The state of the given key + @type keycode: integer + @param keycode: The code that represents the key you want to get the state of + """ + + #--The following methods are deprecated-- def getKey(): """ Returns the key code this sensor is looking for. + + Deprecated: Use the "key" property instead. + + @rtype: keycode from L{GameKeys} module """ def setKey(keycode): """ Set the key this sensor should listen for. + Deprecated: Use the "key" property instead. + @type keycode: keycode from L{GameKeys} module """ def getHold1(): """ Returns the key code for the first modifier this sensor is looking for. + + Deprecated: Use the "hold1" property instead. + + @rtype: keycode from L{GameKeys} module """ - def setHold1(): + def setHold1(keycode): """ Sets the key code for the first modifier this sensor should look for. + + Deprecated: Use the "hold1" property instead. + + @type keycode: keycode from L{GameKeys} module """ def getHold2(): """ Returns the key code for the second modifier this sensor is looking for. + + Deprecated: Use the "hold2" property instead. + + @rtype: keycode from L{GameKeys} module """ - def setHold2(): + def setHold2(keycode): """ Sets the key code for the second modifier this sensor should look for. + + Deprecated: Use the "hold2" property instead. + + @type keycode: keycode from L{GameKeys} module """ def getPressedKeys(): """ Get a list of keys that have either been pressed, or just released this frame. + Deprecated: Use getEventList() instead. + @rtype: list of key status. [[keycode, status]] """ @@ -52,7 +107,7 @@ class SCA_KeyboardSensor(SCA_ISensor): """ Get a list of currently pressed keys that have either been pressed, or just released + Deprecated: Use getEventList() instead. + @rtype: list of key status. [[keycode, status]] - """ - - + """ \ No newline at end of file diff --git a/source/gameengine/PyDoc/SCA_MouseSensor.py b/source/gameengine/PyDoc/SCA_MouseSensor.py index 06b261f67fa..9550cbb4105 100644 --- a/source/gameengine/PyDoc/SCA_MouseSensor.py +++ b/source/gameengine/PyDoc/SCA_MouseSensor.py @@ -5,10 +5,20 @@ from SCA_ISensor import * class SCA_MouseSensor(SCA_ISensor): """ Mouse Sensor logic brick. + + Properties: + + @ivar position: current [x,y] coordinates of the mouse, in frame coordinates (pixels) + @type position: [integer,interger] + @ivar mode: sensor mode: 1=KX_MOUSESENSORMODE_LEFTBUTTON 2=KX_MOUSESENSORMODE_MIDDLEBUTTON + 3=KX_MOUSESENSORMODE_RIGHTBUTTON 4=KX_MOUSESENSORMODE_WHEELUP + 5=KX_MOUSESENSORMODE_WHEELDOWN 9=KX_MOUSESENSORMODE_MOVEMENT + @type mode: integer """ def getXPosition(): """ + DEPRECATED: use the position property Gets the x coordinate of the mouse. @rtype: integer @@ -16,6 +26,7 @@ class SCA_MouseSensor(SCA_ISensor): """ def getYPosition(): """ + DEPRECATED: use the position property Gets the y coordinate of the mouse. @rtype: integer diff --git a/source/gameengine/PyDoc/SCA_PropertyActuator.py b/source/gameengine/PyDoc/SCA_PropertyActuator.py index dc1233ddfb7..52aefcae651 100644 --- a/source/gameengine/PyDoc/SCA_PropertyActuator.py +++ b/source/gameengine/PyDoc/SCA_PropertyActuator.py @@ -5,9 +5,17 @@ from SCA_IActuator import * class SCA_PropertyActuator(SCA_IActuator): """ Property Actuator + + Properties: + + @ivar property: the property on which to operate. + @type property: string + @ivar value: the value with which the actuator operates. + @type value: string """ def setProperty(prop): """ + DEPRECATED: use the 'property' property Set the property on which to operate. If there is no property of this name, the call is ignored. @@ -17,12 +25,14 @@ class SCA_PropertyActuator(SCA_IActuator): """ def getProperty(): """ + DEPRECATED: use the 'property' property Returns the name of the property on which to operate. @rtype: string """ def setValue(value): """ + DEPRECATED: use the 'value' property Set the value with which the actuator operates. If the value is not compatible with the type of the @@ -32,6 +42,7 @@ class SCA_PropertyActuator(SCA_IActuator): """ def getValue(): """ + DEPRECATED: use the 'value' property Gets the value with which this actuator operates. @rtype: string diff --git a/source/gameengine/PyDoc/SCA_PropertySensor.py b/source/gameengine/PyDoc/SCA_PropertySensor.py index 22de8d8b986..949ffd3b703 100644 --- a/source/gameengine/PyDoc/SCA_PropertySensor.py +++ b/source/gameengine/PyDoc/SCA_PropertySensor.py @@ -5,10 +5,22 @@ from SCA_ISensor import * class SCA_PropertySensor(SCA_ISensor): """ Activates when the game object property matches. + + Properties: + + @ivar type: type of check on the property: + KX_PROPSENSOR_EQUAL(1), KX_PROPSENSOR_NOTEQUAL(2), KX_PROPSENSOR_INTERVAL(3), + KX_PROPSENSOR_CHANGED(4), KX_PROPSENSOR_EXPRESSION(5) + @type type: integer + @ivar property: the property with which the sensor operates. + @type property: string + @ivar value: the value with which the sensor compares to the value of the property. + @type value: string """ def getType(): """ + DEPRECATED: use the type property Gets when to activate this sensor. @return: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, @@ -18,6 +30,7 @@ class SCA_PropertySensor(SCA_ISensor): def setType(checktype): """ + DEPRECATED: use the type property Set the type of check to perform. @type checktype: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, @@ -27,6 +40,7 @@ class SCA_PropertySensor(SCA_ISensor): def getProperty(): """ + DEPRECATED: use the property property Return the property with which the sensor operates. @rtype: string @@ -34,6 +48,7 @@ class SCA_PropertySensor(SCA_ISensor): """ def setProperty(name): """ + DEPRECATED: use the property property Sets the property with which to operate. If there is no property of that name, this call is ignored. @@ -41,6 +56,7 @@ class SCA_PropertySensor(SCA_ISensor): """ def getValue(): """ + DEPRECATED: use the value property Return the value with which the sensor compares to the value of the property. @rtype: string @@ -48,6 +64,7 @@ class SCA_PropertySensor(SCA_ISensor): """ def setValue(value): """ + DEPRECATED: use the value property Set the value with which the sensor operates. If the value is not compatible with the type of the property, the subsequent action is ignored. diff --git a/source/gameengine/PyDoc/SCA_PythonController.py b/source/gameengine/PyDoc/SCA_PythonController.py index 6d91736d636..06f2b7e9d1d 100644 --- a/source/gameengine/PyDoc/SCA_PythonController.py +++ b/source/gameengine/PyDoc/SCA_PythonController.py @@ -6,6 +6,14 @@ class SCA_PythonController(SCA_IController): """ A Python controller uses a Python script to activate it's actuators, based on it's sensors. + + Properties: + + @ivar script: the Python script this controller executes + @type script: string, read-only + @ivar state: the controllers state bitmask. + This can be used with the GameObject's state to test if the controller is active. + @type state: integer """ def getSensors(): @@ -36,6 +44,7 @@ class SCA_PythonController(SCA_IController): """ def getScript(): """ + DEPRECATED: use the script property Gets the Python script this controller executes. @rtype: string @@ -48,6 +57,7 @@ class SCA_PythonController(SCA_IController): """ def getState(): """ + DEPRECATED: use the state property Get the controllers state bitmask, this can be used with the GameObject's state to test if the the controller is active. This for instance will always be true however you could compare with a previous state to see when the state was activated. GameLogic.getCurrentController().getState() & GameLogic.getCurrentController().getOwner().getState() diff --git a/source/gameengine/PyDoc/SCA_RandomActuator.py b/source/gameengine/PyDoc/SCA_RandomActuator.py index 353b398b1ff..000a1af7846 100644 --- a/source/gameengine/PyDoc/SCA_RandomActuator.py +++ b/source/gameengine/PyDoc/SCA_RandomActuator.py @@ -5,9 +5,35 @@ from SCA_IActuator import * class SCA_RandomActuator(SCA_IActuator): """ Random Actuator + + Properties: + + @ivar seed: Seed of the random number generator. + Equal seeds produce equal series. If the seed is 0, + the generator will produce the same value on every call. + @type seed: integer + @ivar para1: the first parameter of the active distribution. + Refer to the documentation of the generator types for the meaning + of this value. + @type para1: float, read-only + @ivar para2: the second parameter of the active distribution. + Refer to the documentation of the generator types for the meaning + of this value. + @type para2: float, read-only + @ivar distribution: distribution type: + KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, KX_RANDOMACT_BOOL_BERNOUILLI, + KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, KX_RANDOMACT_INT_POISSON, + KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, + KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL + @type distribution: integer, read-only + @ivar property: the name of the property to set with the random value. + If the generator and property types do not match, the assignment is ignored. + @type property: string + """ def setSeed(seed): """ + DEPRECATED: use the seed property Sets the seed of the random number generator. Equal seeds produce equal series. If the seed is 0, @@ -17,12 +43,14 @@ class SCA_RandomActuator(SCA_IActuator): """ def getSeed(): """ + DEPRECATED: use the seed property Returns the initial seed of the generator. @rtype: integer """ def getPara1(): """ + DEPRECATED: use the para1 property Returns the first parameter of the active distribution. Refer to the documentation of the generator types for the meaning @@ -32,6 +60,7 @@ class SCA_RandomActuator(SCA_IActuator): """ def getPara2(): """ + DEPRECATED: use the para2 property Returns the second parameter of the active distribution. Refer to the documentation of the generator types for the meaning @@ -41,6 +70,7 @@ class SCA_RandomActuator(SCA_IActuator): """ def getDistribution(): """ + DEPRECATED: use the distribution property Returns the type of random distribution. @rtype: distribution type @@ -51,6 +81,7 @@ class SCA_RandomActuator(SCA_IActuator): """ def setProperty(property): """ + DEPRECATED: use the property property Set the property to which the random value is assigned. If the generator and property types do not match, the assignment is ignored. @@ -60,6 +91,7 @@ class SCA_RandomActuator(SCA_IActuator): """ def getProperty(): """ + DEPRECATED: use the property property Returns the name of the property to set. @rtype: string From bd97dd0846d6c22375965634d236fa39bc8d84fc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 30 Dec 2008 05:00:19 +0000 Subject: [PATCH 095/252] mistake in previous commit, stopped CurNurbs from appending --- source/blender/python/api2_2x/CurNurb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/python/api2_2x/CurNurb.c b/source/blender/python/api2_2x/CurNurb.c index bd360585b19..456f11e4a54 100644 --- a/source/blender/python/api2_2x/CurNurb.c +++ b/source/blender/python/api2_2x/CurNurb.c @@ -521,7 +521,7 @@ PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * value ) PyObject *args; BPoint *tmp; - if (PyTuple_Check(args)) { + if (PyTuple_Check(value)) { args= value; } else { From cbc3c7e8785d21490346d4c2eed8380de6ede378 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 30 Dec 2008 08:25:36 +0000 Subject: [PATCH 096/252] script was adding UV's rather then vertex Colors (this was correct before uv & vcol layers existed) --- release/scripts/vertexpaint_from_material.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release/scripts/vertexpaint_from_material.py b/release/scripts/vertexpaint_from_material.py index 2df5b7e721f..9668c521f3a 100644 --- a/release/scripts/vertexpaint_from_material.py +++ b/release/scripts/vertexpaint_from_material.py @@ -27,6 +27,7 @@ def matcol(mat): int(mat.R*255),\ int(mat.G*255),\ int(mat.B*255) + else: return None def mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR): @@ -47,7 +48,7 @@ def mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR): me= ob.getData(mesh=1) try: - me.faceUV=True + me.vertexColors=True except: # no faces continue From cbceb6c8b2806587a45e05946cb591bd119cc801 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 30 Dec 2008 16:44:34 +0000 Subject: [PATCH 097/252] BGE API cleanup: more consistent type check on set attribute (mouse and keyboard so far). Check type after name so that the user get a type error when assigning a wrong type to a built-in attribute. --- .../GameLogic/SCA_KeyboardSensor.cpp | 85 +++++++++++-------- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 39 +++++---- 2 files changed, 69 insertions(+), 55 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index f880cd7768e..0e014628ac7 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -846,49 +846,64 @@ SCA_KeyboardSensor::_getattr(const STR_String& attr) int SCA_KeyboardSensor::_setattr(const STR_String& attr, PyObject *value) { - if (PyInt_Check(value)) + if (attr == "key") { - int val = PyInt_AsLong(value); - - if (attr == "key") - { - m_hotkey = val; - return 0; - } - - if (attr == "hold1") - { - m_qual = val; - return 0; - } - - if (attr == "hold2") - { - m_qual2 = val; - return 0; - } - - if (attr == "useAllKeys") - { - m_bAllKeys = (val != 0); - return 0; + if (!PyInt_Check(value)){ + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; } + m_hotkey = PyInt_AsLong(value); + return 0; } - if (PyString_Check(value)) + if (attr == "hold1") { - STR_String val = PyString_AsString(value); - if (attr == "logToggleProperty") - { - m_toggleprop = val; - return 0; + if (!PyInt_Check(value)){ + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; } + m_qual = PyInt_AsLong(value); + return 0; + } + + if (attr == "hold2") + { + if (!PyInt_Check(value)){ + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; + } + m_qual2 = PyInt_AsLong(value); + return 0; + } - if (attr == "logTargetProperty") - { - m_targetprop = val; - return 0; + if (attr == "useAllKeys") + { + if (!PyInt_Check(value)){ + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; } + m_bAllKeys = (PyInt_AsLong(value) != 0); + return 0; + } + + if (attr == "logToggleProperty") + { + if (!PyString_Check(value)){ + PyErr_SetString(PyExc_TypeError, "expected a string"); + return 1; + } + m_toggleprop = PyString_AsString(value); + return 0; + } + + if (attr == "logTargetProperty") + { + if (!PyString_Check(value)){ + PyErr_SetString(PyExc_TypeError, "expected a string"); + return 1; + } + m_targetprop = PyString_AsString(value); + return 0; } return SCA_ISensor::_setattr(attr, value); diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 9562003aec0..8281eed47bc 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -343,31 +343,30 @@ PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) { int SCA_MouseSensor::_setattr(const STR_String& attr, PyObject *value) { - if (PyInt_Check(value)) + if (attr == "mode") { + if (!PyInt_Check(value)){ + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; + } + int val = PyInt_AsLong(value); - - if (attr == "mode") - { - if ((val < KX_MOUSESENSORMODE_NODEF) - || (val > KX_MOUSESENSORMODE_MAX)){ - - PyErr_SetString(PyExc_ValueError, "invalid mode specified!"); - return NULL; - } - - m_mousemode = val; - UpdateHotkey(); - return 0; + + if ((val < KX_MOUSESENSORMODE_NODEF) + || (val > KX_MOUSESENSORMODE_MAX)){ + PyErr_SetString(PyExc_ValueError, "invalid mode specified!"); + return 1; } + + m_mousemode = val; + UpdateHotkey(); + return 0; } - else + + if (attr == "position") { - if (attr == "position") - { - PyErr_SetString(PyExc_AttributeError, "read-only property!"); - return NULL; - } + PyErr_SetString(PyExc_AttributeError, "'position' is a read-only property!"); + return 1; } return SCA_ISensor::_setattr(attr, value); From eee013d9b918a9582951fa71919fa17e07e6e775 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 31 Dec 2008 02:13:38 +0000 Subject: [PATCH 098/252] use higher precession pi --- release/scripts/animation_bake_constraints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/animation_bake_constraints.py b/release/scripts/animation_bake_constraints.py index 58e9e2b1d02..16855828460 100644 --- a/release/scripts/animation_bake_constraints.py +++ b/release/scripts/animation_bake_constraints.py @@ -155,7 +155,7 @@ usrObjectNamePrefix= "" # if that armature had bones (spine, neck, arm) and the bone prefix was "a." # the bones and IPO curves will be (a.spine, a.neck, a.arm) -R2D = 18/3.1415 # radian to grad +R2D = 18/3.141592653589793 # radian to grad BLENDER_VERSION = Blender.Get('version') # Gets the current scene, there can be many scenes in 1 blend file. From 2dfd34994fb2a5d7d8ca57a7ce1fa18e7047463e Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 31 Dec 2008 20:35:20 +0000 Subject: [PATCH 099/252] BGE API cleanup: introduction of a generic framework to link Python attributes to logic brick class member. See KX_PYATTRIBUTE macros in PyObjectPlus.h. --- .../gameengine/Expressions/PyObjectPlus.cpp | 443 ++++++++++++++++++ source/gameengine/Expressions/PyObjectPlus.h | 101 ++++ .../GameLogic/SCA_JoystickSensor.cpp | 114 +---- .../gameengine/GameLogic/SCA_JoystickSensor.h | 30 +- .../GameLogic/SCA_KeyboardSensor.cpp | 94 +--- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 69 ++- source/gameengine/GameLogic/SCA_MouseSensor.h | 4 +- 7 files changed, 638 insertions(+), 217 deletions(-) diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 1eca527151a..c31587628b0 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -131,6 +131,449 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) return 1; } +PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr) +{ + const PyAttributeDef *attrdef; + for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) + { + if (attr == attrdef->m_name) + { + if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) + { + // fake attribute, ignore + return NULL; + } + char *ptr = reinterpret_cast(self)+attrdef->m_offset; + if (attrdef->m_length > 1) + { + PyObject* resultlist = PyList_New(attrdef->m_length); + for (int i=0; im_length; i++) + { + switch (attrdef->m_type) { + case KX_PYATTRIBUTE_TYPE_BOOL: + { + bool *val = reinterpret_cast(ptr); + ptr += sizeof(bool); + PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + break; + } + case KX_PYATTRIBUTE_TYPE_SHORT: + { + short int *val = reinterpret_cast(ptr); + ptr += sizeof(short int); + PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + break; + } + case KX_PYATTRIBUTE_TYPE_INT: + { + int *val = reinterpret_cast(ptr); + ptr += sizeof(int); + PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + break; + } + case KX_PYATTRIBUTE_TYPE_FLOAT: + { + float *val = reinterpret_cast(ptr); + ptr += sizeof(float); + PyList_SetItem(resultlist,i,PyFloat_FromDouble(*val)); + break; + } + default: + // no support for array of complex data + return NULL; + } + } + return resultlist; + } + else + { + switch (attrdef->m_type) { + case KX_PYATTRIBUTE_TYPE_BOOL: + { + bool *val = reinterpret_cast(ptr); + return PyInt_FromLong(*val); + } + case KX_PYATTRIBUTE_TYPE_SHORT: + { + short int *val = reinterpret_cast(ptr); + return PyInt_FromLong(*val); + } + case KX_PYATTRIBUTE_TYPE_INT: + { + int *val = reinterpret_cast(ptr); + return PyInt_FromLong(*val); + } + case KX_PYATTRIBUTE_TYPE_FLOAT: + { + float *val = reinterpret_cast(ptr); + return PyFloat_FromDouble(*val); + } + case KX_PYATTRIBUTE_TYPE_STRING: + { + STR_String *val = reinterpret_cast(ptr); + return PyString_FromString(*val); + } + default: + return NULL; + } + } + } + } + return NULL; +} + +int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr, PyObject *value) +{ + const PyAttributeDef *attrdef; + void *undoBuffer = NULL; + void *sourceBuffer = NULL; + size_t bufferSize = 0; + + for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) + { + if (attr == attrdef->m_name) + { + if (attrdef->m_access == KX_PYATTRIBUTE_RO || + attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) + { + PyErr_SetString(PyExc_AttributeError, "property is read-only"); + return 1; + } + char *ptr = reinterpret_cast(self)+attrdef->m_offset; + if (attrdef->m_length > 1) + { + if (!PySequence_Check(value)) + { + PyErr_SetString(PyExc_TypeError, "expected a sequence"); + return 1; + } + if (PySequence_Size(value) != attrdef->m_length) + { + PyErr_SetString(PyExc_TypeError, "incorrect number of elements in sequence"); + return 1; + } + switch (attrdef->m_type) + { + case KX_PYATTRIBUTE_TYPE_BOOL: + bufferSize = sizeof(bool); + break; + case KX_PYATTRIBUTE_TYPE_SHORT: + bufferSize = sizeof(short int); + break; + case KX_PYATTRIBUTE_TYPE_INT: + bufferSize = sizeof(int); + break; + case KX_PYATTRIBUTE_TYPE_FLOAT: + bufferSize = sizeof(float); + break; + default: + // should not happen + PyErr_SetString(PyExc_AttributeError, "Unsupported attribute type, report to blender.org"); + return 1; + } + // let's implement a smart undo method + bufferSize *= attrdef->m_length; + undoBuffer = malloc(bufferSize); + sourceBuffer = ptr; + if (undoBuffer) + { + memcpy(undoBuffer, sourceBuffer, bufferSize); + } + for (int i=0; im_length; i++) + { + PyObject *item = PySequence_GetItem(value, i); /* new ref */ + // we can decrement the reference immediately, the reference count + // is at least 1 because the item is part of an array + Py_DECREF(item); + switch (attrdef->m_type) + { + case KX_PYATTRIBUTE_TYPE_BOOL: + { + bool *var = reinterpret_cast(ptr); + ptr += sizeof(bool); + if (PyInt_Check(item)) + { + *var = (PyInt_AsLong(item) != 0); + } + else if (PyBool_Check(item)) + { + *var = (item == Py_True); + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer or a bool"); + goto UNDO_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_SHORT: + { + short int *var = reinterpret_cast(ptr); + ptr += sizeof(short int); + if (PyInt_Check(item)) + { + long val = PyInt_AsLong(item); + if (val < attrdef->m_imin || val > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "item value out of range"); + goto UNDO_AND_ERROR; + } + *var = (short int)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + goto UNDO_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_INT: + { + int *var = reinterpret_cast(ptr); + ptr += sizeof(int); + if (PyInt_Check(item)) + { + long val = PyInt_AsLong(item); + if (val < attrdef->m_imin || val > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "item value out of range"); + goto UNDO_AND_ERROR; + } + *var = (int)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + goto UNDO_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_FLOAT: + { + float *var = reinterpret_cast(ptr); + ptr += sizeof(float); + if (PyFloat_Check(item)) + { + double val = PyFloat_AsDouble(item); + if (val < attrdef->m_fmin || val > attrdef->m_fmax) + { + PyErr_SetString(PyExc_ValueError, "item value out of range"); + goto UNDO_AND_ERROR; + } + *var = (float)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected a float"); + goto UNDO_AND_ERROR; + } + break; + } + default: + // should not happen + PyErr_SetString(PyExc_AttributeError, "attribute type check error, report to blender.org"); + goto UNDO_AND_ERROR; + } + } + // no error, call check function if any + if (attrdef->m_function != NULL) + { + if ((*attrdef->m_function)(self) != 0) + { + // post check returned an error, restore values + UNDO_AND_ERROR: + if (undoBuffer) + { + memcpy(sourceBuffer, undoBuffer, bufferSize); + free(undoBuffer); + } + return 1; + } + } + if (undoBuffer) + free(undoBuffer); + return 0; + } + else // simple attribute value + { + + if (attrdef->m_function != NULL) + { + // post check function is provided, prepare undo buffer + sourceBuffer = ptr; + switch (attrdef->m_type) + { + case KX_PYATTRIBUTE_TYPE_BOOL: + bufferSize = sizeof(bool); + break; + case KX_PYATTRIBUTE_TYPE_SHORT: + bufferSize = sizeof(short); + break; + case KX_PYATTRIBUTE_TYPE_INT: + bufferSize = sizeof(int); + break; + case KX_PYATTRIBUTE_TYPE_FLOAT: + bufferSize = sizeof(float); + break; + case KX_PYATTRIBUTE_TYPE_STRING: + sourceBuffer = reinterpret_cast(ptr)->Ptr(); + if (sourceBuffer) + bufferSize = strlen(reinterpret_cast(sourceBuffer))+1; + break; + default: + PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org"); + return 1; + } + if (bufferSize) + { + undoBuffer = malloc(bufferSize); + if (undoBuffer) + { + memcpy(undoBuffer, sourceBuffer, bufferSize); + } + } + } + + switch (attrdef->m_type) + { + case KX_PYATTRIBUTE_TYPE_BOOL: + { + bool *var = reinterpret_cast(ptr); + if (PyInt_Check(value)) + { + *var = (PyInt_AsLong(value) != 0); + } + else if (PyBool_Check(value)) + { + *var = (value == Py_True); + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer or a bool"); + goto FREE_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_SHORT: + { + short int *var = reinterpret_cast(ptr); + if (PyInt_Check(value)) + { + long val = PyInt_AsLong(value); + if (val < attrdef->m_imin || val > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "value out of range"); + goto FREE_AND_ERROR; + } + *var = (short int)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + goto FREE_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_INT: + { + int *var = reinterpret_cast(ptr); + if (PyInt_Check(value)) + { + long val = PyInt_AsLong(value); + if (val < attrdef->m_imin || val > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "value out of range"); + goto FREE_AND_ERROR; + } + *var = (int)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + goto FREE_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_FLOAT: + { + float *var = reinterpret_cast(ptr); + if (PyFloat_Check(value)) + { + double val = PyFloat_AsDouble(value); + if (val < attrdef->m_fmin || val > attrdef->m_fmax) + { + PyErr_SetString(PyExc_ValueError, "value out of range"); + goto FREE_AND_ERROR; + } + *var = (float)val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected a float"); + goto FREE_AND_ERROR; + } + break; + } + case KX_PYATTRIBUTE_TYPE_STRING: + { + STR_String *var = reinterpret_cast(ptr); + if (PyString_Check(value)) + { + char *val = PyString_AsString(value); + if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax) + { + PyErr_SetString(PyExc_ValueError, "string length out of range"); + goto FREE_AND_ERROR; + } + *var = val; + } + else + { + PyErr_SetString(PyExc_TypeError, "expected a string"); + goto FREE_AND_ERROR; + } + break; + } + default: + // should not happen + PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org"); + goto FREE_AND_ERROR; + } + } + // check if post processing is needed + if (attrdef->m_function != NULL) + { + if ((*attrdef->m_function)(self) != 0) + { + // restore value + if (undoBuffer) + { + if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING) + { + // special case for STR_String: restore the string + STR_String *var = reinterpret_cast(ptr); + *var = reinterpret_cast(undoBuffer); + } + else + { + // other field type have direct values + memcpy(ptr, undoBuffer, bufferSize); + } + } + FREE_AND_ERROR: + if (undoBuffer) + free(undoBuffer); + return 1; + } + } + if (undoBuffer) + free(undoBuffer); + return 0; + } + } + return -1; +} + /*------------------------------ * PyObjectPlus repr -- representations ------------------------------*/ diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 55998ce1c97..016fa293d73 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -86,6 +86,7 @@ static inline void Py_Fatal(const char *M) { public: \ static PyTypeObject Type; \ static PyMethodDef Methods[]; \ + static PyAttributeDef Attributes[]; \ static PyParentObject Parents[]; \ virtual PyTypeObject *GetType(void) {return &Type;}; \ virtual PyParentObject *GetParents(void) {return Parents;} @@ -210,6 +211,104 @@ PyObject* class_name::Py##method_name(PyObject*, PyObject* value) const char class_name::method_name##_doc[] = doc_string; \ PyObject* class_name::Py##method_name(PyObject*) +/** + * Attribute management + */ +enum KX_PYATTRIBUTE_TYPE { + KX_PYATTRIBUTE_TYPE_BOOL, + KX_PYATTRIBUTE_TYPE_SHORT, + KX_PYATTRIBUTE_TYPE_INT, + KX_PYATTRIBUTE_TYPE_FLOAT, + KX_PYATTRIBUTE_TYPE_STRING, + KX_PYATTRIBUTE_TYPE_DUMMY, +}; + +enum KX_PYATTRIBUTE_ACCESS { + KX_PYATTRIBUTE_RW, + KX_PYATTRIBUTE_RO +}; + +typedef int (*KX_PYATTRIBUTE_FUNCTION)(void *self); + +typedef struct KX_PYATTRIBUTE_DEF { + const char *m_name; // name of the python attribute + KX_PYATTRIBUTE_TYPE m_type; // type of value + KX_PYATTRIBUTE_ACCESS m_access; // read/write access or read-only + int m_imin; // minimum value in case of integer attributes + int m_imax; // maximum value in case of integer attributes + float m_fmin; // minimum value in case of float attributes + float m_fmax; // maximum value in case of float attributes + size_t m_offset; // position of field in structure + size_t m_length; // length of array, 1=simple attribute + KX_PYATTRIBUTE_FUNCTION m_function; // static function to check the assignment, returns 0 if no error + // The following pointers are just used to have compile time check for attribute type. + // It would have been good to use a union but that would require C99 compatibility + // to initialize specific union fields through designated initializers. + struct { + bool *m_boolPtr; + short int *m_shortPtr; + int *m_intPtr; + float *m_floatPtr; + STR_String *m_stringPtr; + } m_typeCheck; +} PyAttributeDef; + +#define KX_PYATTRIBUTE_DUMMY(name) \ + { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, 0, 1, NULL, {NULL, NULL, NULL, NULL, NULL} } + +#define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, offsetof(object,field), 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, offsetof(object,field), 1, &object::function, {&((object *)0)->field, NULL, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, offsetof(object,field), 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } + +#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + +#define KX_PYATTRIBUTE_INT_RW(name,min,max,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + +#define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), 1, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), length, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} } +#define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + +#define KX_PYATTRIBUTE_STRING_RW(name,min,max,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } +#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, NULL, NULL, NULL, &((object *)0)->field} } +#define KX_PYATTRIBUTE_STRING_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1 , NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } + /*------------------------------ * PyObjectPlus ------------------------------*/ @@ -240,6 +339,8 @@ public: { return ((PyObjectPlus*) PyObj)->_getattr(STR_String(attr)); } + static PyObject *_getattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr); + static int _setattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr, PyObject *value); virtual int _delattr(const STR_String& attr); virtual int _setattr(const STR_String& attr, PyObject *value); // _setattr method diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index ec5921bad85..ce9058448ac 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -327,6 +327,21 @@ PyMethodDef SCA_JoystickSensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_JoystickSensor::Attributes[] = { + KX_PYATTRIBUTE_SHORT_RW("index",0,JOYINDEX_MAX-1,SCA_JoystickSensor,m_joyindex), + KX_PYATTRIBUTE_INT_RW("threshold",0,32768,SCA_JoystickSensor,m_precision), + KX_PYATTRIBUTE_INT_RW("button",0,100,SCA_JoystickSensor,m_button), + KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("axis",0,3,SCA_JoystickSensor,m_axis,2,CheckAxis), + KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("hat",0,12,SCA_JoystickSensor,m_hat,2,CheckHat), + // dummy attributes will just be read-only in _setattr + // you still need to defined them in _getattr + KX_PYATTRIBUTE_DUMMY("axisPosition"), + KX_PYATTRIBUTE_DUMMY("numAxis"), + KX_PYATTRIBUTE_DUMMY("numButtons"), + KX_PYATTRIBUTE_DUMMY("numHats"), + KX_PYATTRIBUTE_DUMMY("connected"), + { NULL } //Sentinel +}; PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); @@ -348,100 +363,17 @@ PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { if (attr == "connected") { return PyBool_FromLong( joy ? joy->Connected() : 0 ); } - if (attr == "index") { - return PyInt_FromLong(m_joyindex); - } - if (attr == "threshold") { - return PyInt_FromLong(m_precision); - } - if (attr == "button") { - return PyInt_FromLong(m_button); - } - if (attr == "axis") { - return Py_BuildValue("[ii]",m_axis, m_axisf); - } - if (attr == "hat") { - return Py_BuildValue("[ii]",m_hat, m_hatf); - } + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); } -int SCA_JoystickSensor::_setattr(const STR_String& attr, PyObject *value) { - if (attr == "axisPosition") { - PyErr_SetString(PyExc_AttributeError, "axisPosition is read only"); - return 1; - } - if (attr == "numAxis") { - PyErr_SetString(PyExc_AttributeError, "numaxis is read only"); - return 1; - } - if (attr == "numButtons") { - PyErr_SetString(PyExc_AttributeError, "numbuttons is read only"); - return 1; - } - if (attr == "numHats") { - PyErr_SetString(PyExc_AttributeError, "numhats is read only"); - return 1; - } - if (attr == "connected") { - PyErr_SetString(PyExc_AttributeError, "connected is read only"); - return 1; - } - if (PyInt_Check(value)) { - int ival = PyInt_AsLong(value); - if (attr == "index") { - if (ival < 0 || ival >= JOYINDEX_MAX) { - PyErr_SetString(PyExc_ValueError, "joystick index out of range"); - return 1; - } - m_joyindex = ival; - } else if (attr == "threshold") { - m_precision = ival; - } else if (attr == "button") { - if (ival < 0) { - PyErr_SetString(PyExc_ValueError, "button out of range"); - return 1; - } - m_button = ival; - } - return 0; - } - if (PySequence_Check(value)) { - if (attr == "axis" || attr == "hat") { - if (PySequence_Size(value) != 2) { - PyErr_SetString(PyExc_ValueError, "value must be sequence of 2 integers"); - return 1; - } - int ival = -1; - int ivalf = -1; - PyObject *item = PySequence_GetItem(value, 0); /* new ref */ - ival = PyInt_AsLong(item); - Py_DECREF(item); - item = PySequence_GetItem(value, 1); /* new ref */ - ivalf = PyInt_AsLong(item); - Py_DECREF(item); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_ValueError, "one or more of the items in the sequence was not an integer"); - return 1; - } - if (attr == "axis") { - if (ival < 1 || ival > 2 || ivalf < 0 || ivalf > 3) { - PyErr_SetString(PyExc_ValueError, "items in the sequence are out of range"); - return 1; - } - m_axis = ival; - m_axisf = ivalf; - } else { - if (ival < 1 || ival > 2) { - PyErr_SetString(PyExc_ValueError, "items in the sequence are out of range"); - return 1; - } - m_hat = ival; - m_hatf = ivalf; - } - } - return 0; - } +int SCA_JoystickSensor::_setattr(const STR_String& attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; return SCA_ISensor::_setattr(attr, value); } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index 03653070db7..25103b3c6bc 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -37,11 +37,11 @@ class SCA_JoystickSensor :public SCA_ISensor class SCA_JoystickManager* m_pJoystickMgr; /** - * Axis 1-or-2 + * Axis 1-or-2, MUST be followed by m_axisf */ int m_axis; /** - * Axis flag to find direction + * Axis flag to find direction, MUST be an int */ int m_axisf; /** @@ -53,11 +53,11 @@ class SCA_JoystickSensor :public SCA_ISensor */ int m_buttonf; /** - * The actual hat + * The actual hat. MUST be followed by m_hatf */ int m_hat; /** - * Flag to find direction 1-12 + * Flag to find direction 0-11, MUST be an int */ int m_hatf; /** @@ -147,6 +147,28 @@ public: KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfButtons); KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats); KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected); + + /* attribute check */ + static int CheckAxis(void *self) + { + SCA_JoystickSensor* sensor = reinterpret_cast(self); + if (sensor->m_axis < 1 || sensor->m_axis > 2) + { + PyErr_SetString(PyExc_ValueError, "axis number must be 1 or 2"); + return 1; + } + return 0; + } + static int CheckHat(void *self) + { + SCA_JoystickSensor* sensor = reinterpret_cast(self); + if (sensor->m_hat < 1 || sensor->m_hat > 2) + { + PyErr_SetString(PyExc_ValueError, "hat number must be 1 or 2"); + return 1; + } + return 0; + } }; diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index 0e014628ac7..a05f9ae9879 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -820,91 +820,29 @@ PyMethodDef SCA_KeyboardSensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_KeyboardSensor::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("useAllKeys",SCA_KeyboardSensor,m_bAllKeys), + KX_PYATTRIBUTE_INT_RW("key",0,1000,SCA_KeyboardSensor,m_hotkey), + KX_PYATTRIBUTE_SHORT_RW("hold1",0,1000,SCA_KeyboardSensor,m_qual), + KX_PYATTRIBUTE_SHORT_RW("hold2",0,1000,SCA_KeyboardSensor,m_qual2), + KX_PYATTRIBUTE_STRING_RW("toggleProperty",0,100,SCA_KeyboardSensor,m_toggleprop), + KX_PYATTRIBUTE_STRING_RW("targetProperty",0,100,SCA_KeyboardSensor,m_targetprop), + { NULL } //Sentinel +}; + PyObject* SCA_KeyboardSensor::_getattr(const STR_String& attr) { - if (attr == "key") - return PyInt_FromLong(m_hotkey); - - if (attr == "hold1") - return PyInt_FromLong(m_qual); - - if (attr == "hold2") - return PyInt_FromLong(m_qual2); - - if (attr == "toggleProperty") - return PyString_FromString(m_toggleprop); - - if (attr == "targetProperty") - return PyString_FromString(m_targetprop); - - if (attr == "useAllKeys") - return PyInt_FromLong(m_bAllKeys); - + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); } int SCA_KeyboardSensor::_setattr(const STR_String& attr, PyObject *value) { - if (attr == "key") - { - if (!PyInt_Check(value)){ - PyErr_SetString(PyExc_TypeError, "expected an integer"); - return 1; - } - m_hotkey = PyInt_AsLong(value); - return 0; - } - - if (attr == "hold1") - { - if (!PyInt_Check(value)){ - PyErr_SetString(PyExc_TypeError, "expected an integer"); - return 1; - } - m_qual = PyInt_AsLong(value); - return 0; - } - - if (attr == "hold2") - { - if (!PyInt_Check(value)){ - PyErr_SetString(PyExc_TypeError, "expected an integer"); - return 1; - } - m_qual2 = PyInt_AsLong(value); - return 0; - } - - if (attr == "useAllKeys") - { - if (!PyInt_Check(value)){ - PyErr_SetString(PyExc_TypeError, "expected an integer"); - return 1; - } - m_bAllKeys = (PyInt_AsLong(value) != 0); - return 0; - } - - if (attr == "logToggleProperty") - { - if (!PyString_Check(value)){ - PyErr_SetString(PyExc_TypeError, "expected a string"); - return 1; - } - m_toggleprop = PyString_AsString(value); - return 0; - } - - if (attr == "logTargetProperty") - { - if (!PyString_Check(value)){ - PyErr_SetString(PyExc_TypeError, "expected a string"); - return 1; - } - m_targetprop = PyString_AsString(value); - return 0; - } - + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; return SCA_ISensor::_setattr(attr, value); } diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 8281eed47bc..14d9c898980 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -59,7 +59,7 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, m_mousemode = mousemode; m_triggermode = true; - UpdateHotkey(); + UpdateHotkey(this); Init(); } @@ -74,33 +74,37 @@ SCA_MouseSensor::~SCA_MouseSensor() /* Nothing to be done here. */ } -void SCA_MouseSensor::UpdateHotkey() +int SCA_MouseSensor::UpdateHotkey(void *self) { // gosh, this function is so damn stupid // its here because of a design mistake in the mouse sensor, it should only // have 3 trigger modes (button, wheel, move), and let the user set the // hotkey separately, like the other sensors. but instead it has a mode for // each friggin key and i have to update the hotkey based on it... genius! - - switch (m_mousemode) { + SCA_MouseSensor* sensor = reinterpret_cast(self); + + switch (sensor->m_mousemode) { case KX_MOUSESENSORMODE_LEFTBUTTON: - m_hotkey = SCA_IInputDevice::KX_LEFTMOUSE; + sensor->m_hotkey = SCA_IInputDevice::KX_LEFTMOUSE; break; case KX_MOUSESENSORMODE_MIDDLEBUTTON: - m_hotkey = SCA_IInputDevice::KX_MIDDLEMOUSE; + sensor->m_hotkey = SCA_IInputDevice::KX_MIDDLEMOUSE; break; case KX_MOUSESENSORMODE_RIGHTBUTTON: - m_hotkey = SCA_IInputDevice::KX_RIGHTMOUSE; + sensor->m_hotkey = SCA_IInputDevice::KX_RIGHTMOUSE; break; case KX_MOUSESENSORMODE_WHEELUP: - m_hotkey = SCA_IInputDevice::KX_WHEELUPMOUSE; + sensor->m_hotkey = SCA_IInputDevice::KX_WHEELUPMOUSE; break; case KX_MOUSESENSORMODE_WHEELDOWN: - m_hotkey = SCA_IInputDevice::KX_WHEELDOWNMOUSE; + sensor->m_hotkey = SCA_IInputDevice::KX_WHEELDOWNMOUSE; break; default: ; /* ignore, no hotkey */ } + // return value is used in _setattr(), + // 0=attribute checked ok (see Attributes array definition) + return 0; } CValue* SCA_MouseSensor::GetReplica() @@ -331,44 +335,25 @@ PyMethodDef SCA_MouseSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) { - if (attr == "position") - return Py_BuildValue("[ii]", m_x, m_y); - - if (attr == "mode") - return PyInt_FromLong(m_mousemode); - +PyAttributeDef SCA_MouseSensor::Attributes[] = { + KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",KX_MOUSESENSORMODE_NODEF,KX_MOUSESENSORMODE_MAX-1,SCA_MouseSensor,m_mousemode,UpdateHotkey), + KX_PYATTRIBUTE_SHORT_ARRAY_RO("position",SCA_MouseSensor,m_x,2), + { NULL } //Sentinel +}; + +PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) +{ + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); } int SCA_MouseSensor::_setattr(const STR_String& attr, PyObject *value) { - if (attr == "mode") - { - if (!PyInt_Check(value)){ - PyErr_SetString(PyExc_TypeError, "expected an integer"); - return 1; - } - - int val = PyInt_AsLong(value); - - if ((val < KX_MOUSESENSORMODE_NODEF) - || (val > KX_MOUSESENSORMODE_MAX)){ - PyErr_SetString(PyExc_ValueError, "invalid mode specified!"); - return 1; - } - - m_mousemode = val; - UpdateHotkey(); - return 0; - } - - if (attr == "position") - { - PyErr_SetString(PyExc_AttributeError, "'position' is a read-only property!"); - return 1; - } - + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; return SCA_ISensor::_setattr(attr, value); } diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 6d6e641c798..58ee96c8856 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -58,7 +58,7 @@ class SCA_MouseSensor : public SCA_ISensor SCA_IInputDevice::KX_EnumInputs m_hotkey; /** - * valid x coordinate + * valid x coordinate, MUST be followed by y coordinate */ short m_x; @@ -87,7 +87,7 @@ class SCA_MouseSensor : public SCA_ISensor bool isValid(KX_MOUSESENSORMODE); - void UpdateHotkey(); + static int UpdateHotkey(void *self); SCA_MouseSensor(class SCA_MouseManager* keybdmgr, int startx,int starty, From abd4934d1aeceafaa2fc242f00db0ba53a7e24db Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 1 Jan 2009 16:18:54 +0000 Subject: [PATCH 100/252] fix for a memory leak in NMesh (deprecated api) while looking at bug report... [#18139] Memory Leaks while using Py_BuildValue --- source/blender/python/api2_2x/NMesh.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c index 2e82c55155f..22f619c5f31 100644 --- a/source/blender/python/api2_2x/NMesh.c +++ b/source/blender/python/api2_2x/NMesh.c @@ -1476,7 +1476,7 @@ static PyObject *NMesh_update( PyObject *self, PyObject *a, PyObject *kwd ) static PyObject *NMesh_getVertexInfluences( PyObject * self, PyObject * args ) { int index; - PyObject *influence_list = NULL; + PyObject *influence_list = NULL, *item; Object *object = ( ( BPy_NMesh * ) self )->object; Mesh *me = ( ( BPy_NMesh * ) self )->mesh; @@ -1516,9 +1516,11 @@ static PyObject *NMesh_getVertexInfluences( PyObject * self, PyObject * args ) for( i = 0; i < totinfluences; i++, sweight++ ) { bDeformGroup *defgroup = (bDeformGroup *) BLI_findlink( &object->defbase, sweight->def_nr ); - if( defgroup ) - PyList_Append( influence_list, Py_BuildValue( "[sf]", - defgroup->name, sweight->weight ) ); + if( defgroup ) { + item = Py_BuildValue( "[sf]", defgroup->name, sweight->weight ); + PyList_Append( influence_list, item); + Py_DECREF(item); + } } } From cc569504d0468ec19a1018ea804aa418c134cb0f Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Fri, 2 Jan 2009 17:43:56 +0000 Subject: [PATCH 101/252] BGE API Cleanup: update the python attribute definition framework. * Value clamping to min/max is now supported as an option for integer, float and string attribute (for string clamping=trim to max length) * Post check function now take PyAttributeDef parameter so that more generic function can be written. * Definition of SCA_ILogicBrick::CheckProperty() function to check that a string attribute contains a valid property name of the parent game object. * Definition of enum attribute vi KX_PYATTRIBUTE_ENUM... macros. Enum are handled just like integer but to be totally paranoid, the sizeof() of the enum member is check at run time to match integer size. * More bricks updated to use the framework. --- .../gameengine/Expressions/PyObjectPlus.cpp | 146 ++++++++++++++---- source/gameengine/Expressions/PyObjectPlus.h | 90 ++++++----- .../GameLogic/SCA_ActuatorSensor.cpp | 39 +++-- .../gameengine/GameLogic/SCA_ActuatorSensor.h | 1 + .../gameengine/GameLogic/SCA_DelaySensor.cpp | 45 ++---- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 18 ++- source/gameengine/GameLogic/SCA_ILogicBrick.h | 3 + source/gameengine/GameLogic/SCA_ISensor.cpp | 73 +++------ .../GameLogic/SCA_JoystickSensor.cpp | 10 +- .../gameengine/GameLogic/SCA_JoystickSensor.h | 22 ++- .../GameLogic/SCA_KeyboardSensor.cpp | 10 +- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 6 +- source/gameengine/GameLogic/SCA_MouseSensor.h | 2 +- .../GameLogic/SCA_PropertyActuator.cpp | 37 ++--- .../GameLogic/SCA_PropertySensor.cpp | 65 +++----- .../gameengine/GameLogic/SCA_PropertySensor.h | 9 +- .../GameLogic/SCA_RandomActuator.cpp | 61 +++----- .../gameengine/GameLogic/SCA_RandomActuator.h | 1 - 18 files changed, 326 insertions(+), 312 deletions(-) diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index c31587628b0..8fd99c8d267 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -164,6 +164,14 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); break; } + case KX_PYATTRIBUTE_TYPE_ENUM: + // enum are like int, just make sure the field size is the same + if (sizeof(int) != attrdef->m_size) + { + Py_DECREF(resultlist); + return NULL; + } + // walkthrough case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast(ptr); @@ -180,6 +188,7 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel } default: // no support for array of complex data + Py_DECREF(resultlist); return NULL; } } @@ -198,6 +207,13 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel short int *val = reinterpret_cast(ptr); return PyInt_FromLong(*val); } + case KX_PYATTRIBUTE_TYPE_ENUM: + // enum are like int, just make sure the field size is the same + if (sizeof(int) != attrdef->m_size) + { + return NULL; + } + // walkthrough case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast(ptr); @@ -260,6 +276,7 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con case KX_PYATTRIBUTE_TYPE_SHORT: bufferSize = sizeof(short int); break; + case KX_PYATTRIBUTE_TYPE_ENUM: case KX_PYATTRIBUTE_TYPE_INT: bufferSize = sizeof(int); break; @@ -313,7 +330,14 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con if (PyInt_Check(item)) { long val = PyInt_AsLong(item); - if (val < attrdef->m_imin || val > attrdef->m_imax) + if (attrdef->m_clamp) + { + if (val < attrdef->m_imin) + val = attrdef->m_imin; + else if (val > attrdef->m_imax) + val = attrdef->m_imax; + } + else if (val < attrdef->m_imin || val > attrdef->m_imax) { PyErr_SetString(PyExc_ValueError, "item value out of range"); goto UNDO_AND_ERROR; @@ -327,6 +351,14 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con } break; } + case KX_PYATTRIBUTE_TYPE_ENUM: + // enum are equivalent to int, just make sure that the field size matches: + if (sizeof(int) != attrdef->m_size) + { + PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org"); + goto UNDO_AND_ERROR; + } + // walkthrough case KX_PYATTRIBUTE_TYPE_INT: { int *var = reinterpret_cast(ptr); @@ -334,7 +366,14 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con if (PyInt_Check(item)) { long val = PyInt_AsLong(item); - if (val < attrdef->m_imin || val > attrdef->m_imax) + if (attrdef->m_clamp) + { + if (val < attrdef->m_imin) + val = attrdef->m_imin; + else if (val > attrdef->m_imax) + val = attrdef->m_imax; + } + else if (val < attrdef->m_imin || val > attrdef->m_imax) { PyErr_SetString(PyExc_ValueError, "item value out of range"); goto UNDO_AND_ERROR; @@ -352,21 +391,25 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con { float *var = reinterpret_cast(ptr); ptr += sizeof(float); - if (PyFloat_Check(item)) - { - double val = PyFloat_AsDouble(item); - if (val < attrdef->m_fmin || val > attrdef->m_fmax) - { - PyErr_SetString(PyExc_ValueError, "item value out of range"); - goto UNDO_AND_ERROR; - } - *var = (float)val; - } - else + double val = PyFloat_AsDouble(item); + if (val == -1.0 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected a float"); goto UNDO_AND_ERROR; } + else if (attrdef->m_clamp) + { + if (val < attrdef->m_fmin) + val = attrdef->m_fmin; + else if (val > attrdef->m_fmax) + val = attrdef->m_fmax; + } + else if (val < attrdef->m_fmin || val > attrdef->m_fmax) + { + PyErr_SetString(PyExc_ValueError, "item value out of range"); + goto UNDO_AND_ERROR; + } + *var = (float)val; break; } default: @@ -378,7 +421,7 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con // no error, call check function if any if (attrdef->m_function != NULL) { - if ((*attrdef->m_function)(self) != 0) + if ((*attrdef->m_function)(self, attrdef) != 0) { // post check returned an error, restore values UNDO_AND_ERROR: @@ -409,6 +452,7 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con case KX_PYATTRIBUTE_TYPE_SHORT: bufferSize = sizeof(short); break; + case KX_PYATTRIBUTE_TYPE_ENUM: case KX_PYATTRIBUTE_TYPE_INT: bufferSize = sizeof(int); break; @@ -460,7 +504,14 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con if (PyInt_Check(value)) { long val = PyInt_AsLong(value); - if (val < attrdef->m_imin || val > attrdef->m_imax) + if (attrdef->m_clamp) + { + if (val < attrdef->m_imin) + val = attrdef->m_imin; + else if (val > attrdef->m_imax) + val = attrdef->m_imax; + } + else if (val < attrdef->m_imin || val > attrdef->m_imax) { PyErr_SetString(PyExc_ValueError, "value out of range"); goto FREE_AND_ERROR; @@ -474,13 +525,28 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con } break; } + case KX_PYATTRIBUTE_TYPE_ENUM: + // enum are equivalent to int, just make sure that the field size matches: + if (sizeof(int) != attrdef->m_size) + { + PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org"); + goto FREE_AND_ERROR; + } + // walkthrough case KX_PYATTRIBUTE_TYPE_INT: { int *var = reinterpret_cast(ptr); if (PyInt_Check(value)) { long val = PyInt_AsLong(value); - if (val < attrdef->m_imin || val > attrdef->m_imax) + if (attrdef->m_clamp) + { + if (val < attrdef->m_imin) + val = attrdef->m_imin; + else if (val > attrdef->m_imax) + val = attrdef->m_imax; + } + else if (val < attrdef->m_imin || val > attrdef->m_imax) { PyErr_SetString(PyExc_ValueError, "value out of range"); goto FREE_AND_ERROR; @@ -497,21 +563,25 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con case KX_PYATTRIBUTE_TYPE_FLOAT: { float *var = reinterpret_cast(ptr); - if (PyFloat_Check(value)) - { - double val = PyFloat_AsDouble(value); - if (val < attrdef->m_fmin || val > attrdef->m_fmax) - { - PyErr_SetString(PyExc_ValueError, "value out of range"); - goto FREE_AND_ERROR; - } - *var = (float)val; - } - else + double val = PyFloat_AsDouble(value); + if (val == -1.0 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected a float"); goto FREE_AND_ERROR; } + else if (attrdef->m_clamp) + { + if (val < attrdef->m_fmin) + val = attrdef->m_fmin; + else if (val > attrdef->m_fmax) + val = attrdef->m_fmax; + } + else if (val < attrdef->m_fmin || val > attrdef->m_fmax) + { + PyErr_SetString(PyExc_ValueError, "value out of range"); + goto FREE_AND_ERROR; + } + *var = (float)val; break; } case KX_PYATTRIBUTE_TYPE_STRING: @@ -520,7 +590,24 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con if (PyString_Check(value)) { char *val = PyString_AsString(value); - if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax) + if (attrdef->m_clamp) + { + if (strlen(val) < attrdef->m_imin) + { + // can't increase the length of the string + PyErr_SetString(PyExc_ValueError, "string length too short"); + goto FREE_AND_ERROR; + } + else if (strlen(val) > attrdef->m_imax) + { + // trim the string + char c = val[attrdef->m_imax]; + val[attrdef->m_imax] = 0; + *var = val; + val[attrdef->m_imax] = c; + break; + } + } else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax) { PyErr_SetString(PyExc_ValueError, "string length out of range"); goto FREE_AND_ERROR; @@ -543,9 +630,10 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con // check if post processing is needed if (attrdef->m_function != NULL) { - if ((*attrdef->m_function)(self) != 0) + if ((*attrdef->m_function)(self, attrdef) != 0) { // restore value + RESTORE_AND_ERROR: if (undoBuffer) { if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING) diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 016fa293d73..e0e2213d984 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -216,6 +216,7 @@ PyObject* class_name::Py##method_name(PyObject*) */ enum KX_PYATTRIBUTE_TYPE { KX_PYATTRIBUTE_TYPE_BOOL, + KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_TYPE_FLOAT, @@ -228,17 +229,20 @@ enum KX_PYATTRIBUTE_ACCESS { KX_PYATTRIBUTE_RO }; -typedef int (*KX_PYATTRIBUTE_FUNCTION)(void *self); +struct KX_PYATTRIBUTE_DEF; +typedef int (*KX_PYATTRIBUTE_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); typedef struct KX_PYATTRIBUTE_DEF { const char *m_name; // name of the python attribute KX_PYATTRIBUTE_TYPE m_type; // type of value KX_PYATTRIBUTE_ACCESS m_access; // read/write access or read-only - int m_imin; // minimum value in case of integer attributes - int m_imax; // maximum value in case of integer attributes + int m_imin; // minimum value in case of integer attributes (for string: minimum string length) + int m_imax; // maximum value in case of integer attributes (for string: maximum string length) float m_fmin; // minimum value in case of float attributes float m_fmax; // maximum value in case of float attributes + bool m_clamp; // enforce min/max value by clamping size_t m_offset; // position of field in structure + size_t m_size; // size of field for runtime verification (enum only) size_t m_length; // length of array, 1=simple attribute KX_PYATTRIBUTE_FUNCTION m_function; // static function to check the assignment, returns 0 if no error // The following pointers are just used to have compile time check for attribute type. @@ -254,60 +258,70 @@ typedef struct KX_PYATTRIBUTE_DEF { } PyAttributeDef; #define KX_PYATTRIBUTE_DUMMY(name) \ - { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, 0, 1, NULL, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, {NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, offsetof(object,field), 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, offsetof(object,field), 1, &object::function, {&((object *)0)->field, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, {&((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, offsetof(object,field), 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } -#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } -#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +// enum field cannot be mapped to pointer (because we would need a pointer for each enum) +// use field size to verify mapping at runtime only, assuming enum size is equal to int size. +#define KX_PYATTRIBUTE_ENUM_RW(name,min,max,clamp,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, {NULL, NULL, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_ENUM_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, {NULL, NULL, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_ENUM_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, {NULL, NULL, NULL, NULL, NULL} } + +#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,clamp,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } -#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } -#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } -#define KX_PYATTRIBUTE_INT_RW(name,min,max,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } -#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_INT_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } -#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } -#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +// always clamp for float #define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), 1, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), length, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } -#define KX_PYATTRIBUTE_STRING_RW(name,min,max,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } -#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, NULL, NULL, NULL, &((object *)0)->field} } +#define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } +#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, NULL, NULL, &((object *)0)->field} } #define KX_PYATTRIBUTE_STRING_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1 , NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } /*------------------------------ * PyObjectPlus diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index 5ad28dbf329..fae8d2ba5a7 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -156,27 +156,34 @@ PyMethodDef SCA_ActuatorSensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_ActuatorSensor::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW_CHECK("actuator",0,100,false,SCA_ActuatorSensor,m_checkactname,CheckActuator), + { NULL } //Sentinel +}; + PyObject* SCA_ActuatorSensor::_getattr(const STR_String& attr) { - if (attr == "actuator") { - return PyString_FromString(m_checkactname); - } + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); /* implicit return! */ } -int SCA_ActuatorSensor::_setattr(const STR_String& attr, PyObject *value) { - if (PyString_Check(value)) { - char* sval = PyString_AsString(value); - if (attr == "actuator") { - SCA_IActuator* act = GetParent()->FindActuator(STR_String(sval)); - if (act) { - m_checkactname = sval; - m_actuator = act; - return 0; - } - PyErr_SetString(PyExc_AttributeError, "string does not correspond to an actuator"); - return 1; - } +int SCA_ActuatorSensor::CheckActuator(void *self, const PyAttributeDef*) +{ + SCA_ActuatorSensor* sensor = reinterpret_cast(self); + SCA_IActuator* act = sensor->GetParent()->FindActuator(sensor->m_checkactname); + if (act) { + sensor->m_actuator = act; + return 0; } + PyErr_SetString(PyExc_AttributeError, "string does not correspond to an actuator"); + return 1; +} + +int SCA_ActuatorSensor::_setattr(const STR_String& attr, PyObject *value) { + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; return SCA_ISensor::_setattr(attr, value); } diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index 4fe4700602c..3d64247461c 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -69,6 +69,7 @@ public: /* 4. getProperty */ KX_PYMETHOD_DOC_NOARGS(SCA_ActuatorSensor,GetActuator); + static int CheckActuator(void *self, const PyAttributeDef*); }; #endif diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index 362483b58a2..4c97ca98d72 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -171,43 +171,24 @@ PyMethodDef SCA_DelaySensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_DelaySensor::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("delay",0,100000,true,SCA_DelaySensor,m_delay), + KX_PYATTRIBUTE_INT_RW("duration",0,100000,true,SCA_DelaySensor,m_duration), + KX_PYATTRIBUTE_BOOL_RW("repeat",SCA_DelaySensor,m_repeat), + { NULL } //Sentinel +}; + PyObject* SCA_DelaySensor::_getattr(const STR_String& attr) { - if (attr == "delay") { - return PyInt_FromLong(m_delay); - } - if (attr == "duration") { - return PyInt_FromLong(m_duration); - } - if (attr == "repeat") { - return PyInt_FromLong(m_repeat); - } + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); } int SCA_DelaySensor::_setattr(const STR_String& attr, PyObject *value) { - if (PyInt_Check(value)) { - int ival = PyInt_AsLong(value); - if (attr == "delay") { - if (ival < 0) { - PyErr_SetString(PyExc_ValueError, "Delay cannot be negative"); - return 1; - } - m_delay = ival; - return 0; - } - if (attr == "duration") { - if (ival < 0) { - PyErr_SetString(PyExc_ValueError, "Duration cannot be negative"); - return 1; - } - m_duration = ival; - return 0; - } - if (attr == "repeat") { - m_repeat = (ival != 0); - return 0; - } - } + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; return SCA_ISensor::_setattr(attr, value); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 515b485061d..37658480c05 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -252,7 +252,23 @@ PyMethodDef SCA_ILogicBrick::Methods[] = { {NULL,NULL} //Sentinel }; - +int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) +{ + if (attrdef->m_type != KX_PYATTRIBUTE_TYPE_STRING || attrdef->m_length != 1) { + PyErr_SetString(PyExc_AttributeError, "inconsistent check function for attribute type, report to blender.org"); + return 1; + } + SCA_ILogicBrick* brick = reinterpret_cast(self); + STR_String* var = reinterpret_cast((char*)self+attrdef->m_offset); + CValue* prop = brick->GetParent()->FindIdentifier(*var); + bool error = prop->IsError(); + prop->Release(); + if (error) { + PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); + return 1; + } + return 0; +} PyObject* SCA_ILogicBrick::_getattr(const STR_String& attr) diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index c28711ac0f6..38ec80d4096 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -89,6 +89,9 @@ public: KX_PYMETHOD(SCA_ILogicBrick,SetExecutePriority); KX_PYMETHOD_NOARGS(SCA_ILogicBrick,GetExecutePriority); + // check that attribute is a property + static int CheckProperty(void *self, const PyAttributeDef *attrdef); + enum KX_BOOL_TYPE { KX_BOOL_NODEF = 0, KX_TRUE, diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 6e46c8504bb..68a3a93eab0 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -448,19 +448,24 @@ PyMethodDef SCA_ISensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_ISensor::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("usePosPulseMode",SCA_ISensor,m_pos_pulsemode), + KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), + KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), + KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), + KX_PYATTRIBUTE_BOOL_RW("level",SCA_ISensor,m_level), + // make these properties read-only in _setaddr, must still implement them in _getattr + KX_PYATTRIBUTE_DUMMY("triggered"), + KX_PYATTRIBUTE_DUMMY("positive"), + { NULL } //Sentinel +}; + PyObject* SCA_ISensor::_getattr(const STR_String& attr) { - if (attr == "usePosPulseMode") - return PyInt_FromLong(m_pos_pulsemode); - if (attr == "useNegPulseMode") - return PyInt_FromLong(m_neg_pulsemode); - if (attr == "frequency") - return PyInt_FromLong(m_pulse_frequency); - if (attr == "invert") - return PyInt_FromLong(m_invert); - if (attr == "level") - return PyInt_FromLong(m_level); + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; if (attr == "triggered") { int retval = 0; @@ -473,54 +478,14 @@ SCA_ISensor::_getattr(const STR_String& attr) int retval = IsPositiveTrigger(); return PyInt_FromLong(retval); } - - _getattr_up(SCA_ILogicBrick); + _getattr_up(SCA_ILogicBrick); } int SCA_ISensor::_setattr(const STR_String& attr, PyObject *value) { - if (attr == "triggered") - PyErr_SetString(PyExc_AttributeError, "attribute \"triggered\" is read only"); - if (attr == "positive") - PyErr_SetString(PyExc_AttributeError, "attribute \"positive\" is read only"); - - if (PyInt_Check(value)) - { - int val = PyInt_AsLong(value); - - if (attr == "usePosPulseMode") - { - m_pos_pulsemode = (val != 0); - return 0; - } - - if (attr == "useNegPulseMode") - { - m_neg_pulsemode = (val != 0); - return 0; - } - - if (attr == "invert") - { - m_invert = (val != 0); - return 0; - } - - if (attr == "level") - { - m_level = (val != 0); - return 0; - } - - if (attr == "frequency") - { - if (val < 0) - val = 0; - m_pulse_frequency = val; - return 0; - } - } - + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; return SCA_ILogicBrick::_setattr(attr, value); } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index ce9058448ac..694bca9bac5 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -328,11 +328,11 @@ PyMethodDef SCA_JoystickSensor::Methods[] = { }; PyAttributeDef SCA_JoystickSensor::Attributes[] = { - KX_PYATTRIBUTE_SHORT_RW("index",0,JOYINDEX_MAX-1,SCA_JoystickSensor,m_joyindex), - KX_PYATTRIBUTE_INT_RW("threshold",0,32768,SCA_JoystickSensor,m_precision), - KX_PYATTRIBUTE_INT_RW("button",0,100,SCA_JoystickSensor,m_button), - KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("axis",0,3,SCA_JoystickSensor,m_axis,2,CheckAxis), - KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("hat",0,12,SCA_JoystickSensor,m_hat,2,CheckHat), + KX_PYATTRIBUTE_SHORT_RW("index",0,JOYINDEX_MAX-1,true,SCA_JoystickSensor,m_joyindex), + KX_PYATTRIBUTE_INT_RW("threshold",0,32768,true,SCA_JoystickSensor,m_precision), + KX_PYATTRIBUTE_INT_RW("button",0,100,false,SCA_JoystickSensor,m_button), + KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("axis",0,3,true,SCA_JoystickSensor,m_axis,2,CheckAxis), + KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("hat",0,12,true,SCA_JoystickSensor,m_hat,2,CheckHat), // dummy attributes will just be read-only in _setattr // you still need to defined them in _getattr KX_PYATTRIBUTE_DUMMY("axisPosition"), diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index 25103b3c6bc..fa11f1cc3d0 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -149,24 +149,22 @@ public: KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected); /* attribute check */ - static int CheckAxis(void *self) + static int CheckAxis(void *self, const PyAttributeDef*) { SCA_JoystickSensor* sensor = reinterpret_cast(self); - if (sensor->m_axis < 1 || sensor->m_axis > 2) - { - PyErr_SetString(PyExc_ValueError, "axis number must be 1 or 2"); - return 1; - } + if (sensor->m_axis < 1) + sensor->m_axis = 1; + else if (sensor->m_axis > 2) + sensor->m_axis = 2; return 0; } - static int CheckHat(void *self) + static int CheckHat(void *self, const PyAttributeDef*) { SCA_JoystickSensor* sensor = reinterpret_cast(self); - if (sensor->m_hat < 1 || sensor->m_hat > 2) - { - PyErr_SetString(PyExc_ValueError, "hat number must be 1 or 2"); - return 1; - } + if (sensor->m_hat < 1) + sensor->m_hat = 1; + else if (sensor->m_hat > 2) + sensor->m_hat = 2; return 0; } diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index a05f9ae9879..981d165287b 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -822,11 +822,11 @@ PyMethodDef SCA_KeyboardSensor::Methods[] = { PyAttributeDef SCA_KeyboardSensor::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("useAllKeys",SCA_KeyboardSensor,m_bAllKeys), - KX_PYATTRIBUTE_INT_RW("key",0,1000,SCA_KeyboardSensor,m_hotkey), - KX_PYATTRIBUTE_SHORT_RW("hold1",0,1000,SCA_KeyboardSensor,m_qual), - KX_PYATTRIBUTE_SHORT_RW("hold2",0,1000,SCA_KeyboardSensor,m_qual2), - KX_PYATTRIBUTE_STRING_RW("toggleProperty",0,100,SCA_KeyboardSensor,m_toggleprop), - KX_PYATTRIBUTE_STRING_RW("targetProperty",0,100,SCA_KeyboardSensor,m_targetprop), + KX_PYATTRIBUTE_INT_RW("key",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_hotkey), + KX_PYATTRIBUTE_SHORT_RW("hold1",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual), + KX_PYATTRIBUTE_SHORT_RW("hold2",0,SCA_IInputDevice::KX_ENDKEY,true,SCA_KeyboardSensor,m_qual2), + KX_PYATTRIBUTE_STRING_RW("toggleProperty",0,100,false,SCA_KeyboardSensor,m_toggleprop), + KX_PYATTRIBUTE_STRING_RW("targetProperty",0,100,false,SCA_KeyboardSensor,m_targetprop), { NULL } //Sentinel }; diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 14d9c898980..09b46e6443e 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -59,7 +59,7 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, m_mousemode = mousemode; m_triggermode = true; - UpdateHotkey(this); + UpdateHotkey(this, NULL); Init(); } @@ -74,7 +74,7 @@ SCA_MouseSensor::~SCA_MouseSensor() /* Nothing to be done here. */ } -int SCA_MouseSensor::UpdateHotkey(void *self) +int SCA_MouseSensor::UpdateHotkey(void *self, const PyAttributeDef*) { // gosh, this function is so damn stupid // its here because of a design mistake in the mouse sensor, it should only @@ -336,7 +336,7 @@ PyMethodDef SCA_MouseSensor::Methods[] = { }; PyAttributeDef SCA_MouseSensor::Attributes[] = { - KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",KX_MOUSESENSORMODE_NODEF,KX_MOUSESENSORMODE_MAX-1,SCA_MouseSensor,m_mousemode,UpdateHotkey), + KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",KX_MOUSESENSORMODE_NODEF,KX_MOUSESENSORMODE_MAX-1,true,SCA_MouseSensor,m_mousemode,UpdateHotkey), KX_PYATTRIBUTE_SHORT_ARRAY_RO("position",SCA_MouseSensor,m_x,2), { NULL } //Sentinel }; diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 58ee96c8856..82af2ce9c04 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -87,7 +87,7 @@ class SCA_MouseSensor : public SCA_ISensor bool isValid(KX_MOUSESENSORMODE); - static int UpdateHotkey(void *self); + static int UpdateHotkey(void *self, const PyAttributeDef*); SCA_MouseSensor(class SCA_MouseManager* keybdmgr, int startx,int starty, diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index f8509fe380e..566d3b63487 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -254,36 +254,23 @@ PyMethodDef SCA_PropertyActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_PropertyActuator::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty), + KX_PYATTRIBUTE_STRING_RW("value",0,100,false,SCA_PropertyActuator,m_exprtxt), + { NULL } //Sentinel +}; + PyObject* SCA_PropertyActuator::_getattr(const STR_String& attr) { - if (attr == "property") { - return PyString_FromString(m_propname); - } - if (attr == "value") { - return PyString_FromString(m_exprtxt); - } + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_IActuator); } int SCA_PropertyActuator::_setattr(const STR_String& attr, PyObject *value) { - if (PyString_Check(value)) { - char* sval = PyString_AsString(value); - if (attr == "property") { - CValue* prop = GetParent()->FindIdentifier(sval); - bool error = prop->IsError(); - prop->Release(); - if (!prop->IsError()) { - m_propname = sval; - return 0; - } else { - PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); - return 1; - } - } - if (attr == "value") { - m_exprtxt = sval; - return 0; - } - } + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; return SCA_IActuator::_setattr(attr, value); } diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 19ee85207bb..a6f7a9cd82b 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -293,7 +293,7 @@ CValue* SCA_PropertySensor::FindIdentifier(const STR_String& identifiername) return GetParent()->FindIdentifier(identifiername); } -bool SCA_PropertySensor::validValueForProperty(char *val, STR_String &prop) +int SCA_PropertySensor::validValueForProperty(void *self, const PyAttributeDef*) { bool result = true; /* There is no type checking at this moment, unfortunately... */ @@ -344,51 +344,25 @@ PyMethodDef SCA_PropertySensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_PropertySensor::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("type",KX_PROPSENSOR_NODEF,KX_PROPSENSOR_MAX-1,false,SCA_PropertySensor,m_checktype), + KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertySensor,m_checkpropname,CheckProperty), + KX_PYATTRIBUTE_STRING_RW_CHECK("value",0,100,false,SCA_PropertySensor,m_checkpropval,validValueForProperty), + { NULL } //Sentinel +}; + + PyObject* SCA_PropertySensor::_getattr(const STR_String& attr) { - if (attr == "type") { - return PyInt_FromLong(m_checktype); - } - if (attr == "property") { - return PyString_FromString(m_checkpropname); - } - if (attr == "value") { - return PyString_FromString(m_checkpropval); - } + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); /* implicit return! */ } int SCA_PropertySensor::_setattr(const STR_String& attr, PyObject *value) { - if (PyInt_Check(value)) { - int ival = PyInt_AsLong(value); - if (attr == "type") { - if ((ival <= KX_PROPSENSOR_NODEF) || (ival >= KX_PROPSENSOR_MAX)) { - PyErr_SetString(PyExc_ValueError, "type out of range"); - return 1; - } - m_checktype = ival; - } - return 0; - } - if (PyString_Check(value)) { - char* sval = PyString_AsString(value); - if (attr == "property") { - CValue *prop = FindIdentifier(STR_String(sval)); - bool error = prop->IsError(); - prop->Release(); - if (error) { - PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); - return 1; - } - m_checkpropname = sval; - } else if (attr == "value") { - if (!validValueForProperty(sval, m_checkpropname)) { - PyErr_SetString(PyExc_ValueError, "string does not represent a suitable value for the property"); - return 1; - } - m_checkpropval = sval; - } - return 0; - } + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; return SCA_ISensor::_setattr(attr, value); } @@ -490,11 +464,12 @@ PyObject* SCA_PropertySensor::PySetValue(PyObject* self, PyObject* args, PyObjec if(!PyArg_ParseTuple(args, "s", &propValArg)) { return NULL; } - - if (validValueForProperty(propValArg, m_checkpropname)) { - m_checkpropval = propValArg; + STR_String oldval = m_checkpropval; + m_checkpropval = propValArg; + if (validValueForProperty(self, NULL)) { + m_checkpropval = oldval; + return NULL; } - Py_Return; } diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index 81203c78f9d..e625e84a36f 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -47,10 +47,6 @@ class SCA_PropertySensor : public SCA_ISensor bool m_recentresult; CExpression* m_range_expr; - /** - * Test whether this is a sensible value (type check) - */ - bool validValueForProperty(char *val, STR_String &prop); protected: public: @@ -104,7 +100,10 @@ public: KX_PYMETHOD_DOC(SCA_PropertySensor,GetValue); /* 6. setValue */ KX_PYMETHOD_DOC(SCA_PropertySensor,SetValue); - + /** + * Test whether this is a sensible value (type check) + */ + static int validValueForProperty(void* self, const PyAttributeDef*); }; #endif diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 8dd405c3d82..840b95d559a 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -361,57 +361,38 @@ PyMethodDef SCA_RandomActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_RandomActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RO("para1",SCA_RandomActuator,m_parameter1), + KX_PYATTRIBUTE_FLOAT_RO("para2",SCA_RandomActuator,m_parameter2), + KX_PYATTRIBUTE_ENUM_RO("distribution",SCA_RandomActuator,m_distribution), + KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_RandomActuator,m_propname,CheckProperty), + { NULL } //Sentinel +}; + PyObject* SCA_RandomActuator::_getattr(const STR_String& attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; if (attr == "seed") { return PyInt_FromLong(m_base->GetSeed()); } - if (attr == "para1") { - return PyFloat_FromDouble(m_parameter1); - } - if (attr == "para2") { - return PyFloat_FromDouble(m_parameter2); - } - if (attr == "distribution") { - return PyInt_FromLong(m_distribution); - } - if (attr == "property") { - return PyString_FromString(m_propname); - } _getattr_up(SCA_IActuator); } int SCA_RandomActuator::_setattr(const STR_String& attr, PyObject *value) { - if (attr == "para1") { - PyErr_SetString(PyExc_AttributeError, "para1 is read only"); - } - if (attr == "para2") { - PyErr_SetString(PyExc_AttributeError, "para2 is read only"); - } - if (attr == "distribution") { - PyErr_SetString(PyExc_AttributeError, "distribution is read only"); - } - if (PyInt_Check(value)) { - int ival = PyInt_AsLong(value); - if (attr == "seed") { + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + if (attr == "seed") { + if (PyInt_Check(value)) { + int ival = PyInt_AsLong(value); m_base->SetSeed(ival); + return 0; + } else { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; } - return 0; - } - if (PyString_Check(value)) { - char* sval = PyString_AsString(value); - if (attr == "property") { - CValue* prop = GetParent()->FindIdentifier(sval); - bool error = prop->IsError(); - prop->Release(); - if (!prop->IsError()) { - m_propname = sval; - return 0; - } else { - PyErr_SetString(PyExc_ValueError, "string does not correspond to a property"); - return 1; - } - } } return SCA_IActuator::_setattr(attr, value); } diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index 2fc14f9a0b7..de8faaf9c72 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -136,7 +136,6 @@ class SCA_RandomActuator : public SCA_IActuator KX_PYMETHOD_DOC(SCA_RandomActuator,SetFloatNormal); /* 20. setFloatNegativeExponential, */ KX_PYMETHOD_DOC(SCA_RandomActuator,SetFloatNegativeExponential); - }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ #endif From 10702bf93f14441066ceba3204f932a5ba099c2e Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Fri, 2 Jan 2009 22:09:57 +0000 Subject: [PATCH 102/252] BGE API cleanup: more bricks converted to attributes. --- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 19 +++++++++++ source/gameengine/GameLogic/SCA_ILogicBrick.h | 1 + .../gameengine/GameLogic/SCA_RandomSensor.cpp | 32 +++++++++++++++++++ .../gameengine/GameLogic/SCA_RandomSensor.h | 1 + 4 files changed, 53 insertions(+) diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 37658480c05..8286c0829a7 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -247,11 +247,18 @@ PyParentObject SCA_ILogicBrick::Parents[] = { PyMethodDef SCA_ILogicBrick::Methods[] = { {"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_NOARGS}, + // --> Deprecated {"getExecutePriority", (PyCFunction) SCA_ILogicBrick::sPyGetExecutePriority, METH_NOARGS}, {"setExecutePriority", (PyCFunction) SCA_ILogicBrick::sPySetExecutePriority, METH_VARARGS}, + // <-- Deprecated {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_ILogicBrick::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Ueber_Priority), + {NULL} //Sentinel +}; + int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) { if (attrdef->m_type != KX_PYATTRIBUTE_TYPE_STRING || attrdef->m_length != 1) { @@ -273,9 +280,19 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) PyObject* SCA_ILogicBrick::_getattr(const STR_String& attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(CValue); } +int SCA_ILogicBrick::_setattr(const STR_String& attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return CValue::_setattr(attr, value); +} PyObject* SCA_ILogicBrick::PyGetOwner(PyObject* self) @@ -297,6 +314,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setExecutePriority()", "the executePriority property"); int priority=0; @@ -313,6 +331,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* self, PyObject* SCA_ILogicBrick::PyGetExecutePriority(PyObject* self) { + ShowDeprecationWarning("getExecutePriority()", "the executePriority property"); return PyInt_FromLong(m_Execute_Ueber_Priority); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index 38ec80d4096..772bd65d577 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -79,6 +79,7 @@ public: virtual bool LessComparedTo(SCA_ILogicBrick* other); virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); static class SCA_LogicManager* m_sCurrentLogicManager; diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 202fd6382e6..8fae0bbeaba 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -160,10 +160,39 @@ PyMethodDef SCA_RandomSensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_RandomSensor::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RO("lastDraw",SCA_RandomSensor,m_lastdraw), + {NULL} //Sentinel +}; + PyObject* SCA_RandomSensor::_getattr(const STR_String& attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + if (attr == "seed") { + return PyInt_FromLong(m_basegenerator->GetSeed()); + } _getattr_up(SCA_ISensor); } +int SCA_RandomSensor::_setattr(const STR_String& attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + if (attr == "seed") { + if (PyInt_Check(value)) { + int ival = PyInt_AsLong(value); + m_basegenerator->SetSeed(ival); + return 0; + } else { + PyErr_SetString(PyExc_TypeError, "expected an integer"); + return 1; + } + } + return SCA_ISensor::_setattr(attr, value); +} + /* 1. setSeed */ const char SCA_RandomSensor::SetSeed_doc[] = "setSeed(seed)\n" @@ -172,6 +201,7 @@ const char SCA_RandomSensor::SetSeed_doc[] = "\tequal series. If the seed is 0, the generator will produce\n" "\tthe same value on every call.\n"; PyObject* SCA_RandomSensor::PySetSeed(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setSeed()", "the seed property"); long seedArg; if(!PyArg_ParseTuple(args, "i", &seedArg)) { return NULL; @@ -188,6 +218,7 @@ const char SCA_RandomSensor::GetSeed_doc[] = "\tReturns the initial seed of the generator. Equal seeds produce\n" "\tequal series.\n"; PyObject* SCA_RandomSensor::PyGetSeed(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getSeed()", "the seed property"); return PyInt_FromLong(m_basegenerator->GetSeed()); } @@ -196,6 +227,7 @@ const char SCA_RandomSensor::GetLastDraw_doc[] = "getLastDraw()\n" "\tReturn the last value that was drawn.\n"; PyObject* SCA_RandomSensor::PyGetLastDraw(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getLastDraw()", "the lastDraw property"); return PyInt_FromLong(m_lastdraw); } diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index d29bfb6837a..009efc32aac 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -61,6 +61,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject *value); /* 1. setSeed */ KX_PYMETHOD_DOC(SCA_RandomSensor,SetSeed); From 9ce30005debab6837d8f44443620c570391a0cb8 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Fri, 2 Jan 2009 22:15:05 +0000 Subject: [PATCH 103/252] BGE bug #18070 fixed: 2dFilter actuator is always pulsed. --- source/gameengine/GameLogic/SCA_2DFilterActuator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 9ec4ea00337..a70830193db 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -74,7 +74,8 @@ bool SCA_2DFilterActuator::Update() { m_rendertools->Update2DFilter(m_propNames, m_gameObj, m_type, m_int_arg, m_shaderText); } - return true; + // once the filter is in place, no need to update it again => disable the actuator + return false; } From 92ab0c0369040e5053ede0c10125376261129c58 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 3 Jan 2009 14:02:14 +0000 Subject: [PATCH 104/252] [#18142] Blender FBX export outputs broken vertex colors when using vertex paint from Kevin Hsu (caywen) use fix suggested in report --- release/scripts/export_fbx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/export_fbx.py b/release/scripts/export_fbx.py index ce17f78c5e2..6f964118964 100644 --- a/release/scripts/export_fbx.py +++ b/release/scripts/export_fbx.py @@ -1446,13 +1446,13 @@ def write(filename, batch_objects = None, \ for f in me.faces: for col in f.col: if i==-1: - file.write('%i,%i,%i' % (col[0], col[1], col[2])) + file.write('%i,%i,%i,255' % (col[0], col[1], col[2])) i=0 else: if i==7: file.write('\n\t\t\t\t') i=0 - file.write(',%i,%i,%i' % (col[0], col[1], col[2])) + file.write(',%i,%i,%i,255' % (col[0], col[1], col[2])) i+=1 ii+=1 # One more Color From e64b8599e1d15648db9419fe9a5b6de572e506ef Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 4 Jan 2009 07:56:51 +0000 Subject: [PATCH 105/252] C files reference "libredcode/format.h", which only exist in extern/libredcodec/format.h, so for now adding "extern/" as an include when redcode is enabled lets it compile, noticed there are some win32 ifdef's that don't do anything. should be fixed properly but this at least compiles for now. --- config/linux2-config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/linux2-config.py b/config/linux2-config.py index 56132aaf1de..a1f979d26da 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -163,7 +163,8 @@ BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib' WITH_BF_REDCODE = False BF_REDCODE = '#extern/libredcode' BF_REDCODE_LIB = '' -BF_REDCODE_INC = '${BF_REDCODE}/include' +# BF_REDCODE_INC = '${BF_REDCODE}/include' +BF_REDCODE_INC = '${BF_REDCODE}/../' #C files request "libredcode/format.h" which is in "#extern/libredcode/format.h", stupid but compiles for now. BF_REDCODE_LIBPATH='${BF_REDCODE}/lib' # Mesa Libs should go here if your using them as well.... From ee7a52b7feda5532fab4ca171e50d388f64f50c3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 5 Jan 2009 03:26:18 +0000 Subject: [PATCH 106/252] added static python option for mingw --- config/win32-mingw-config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py index 963f62a5f40..b94747637e9 100644 --- a/config/win32-mingw-config.py +++ b/config/win32-mingw-config.py @@ -6,10 +6,12 @@ BF_VERSE_INCLUDE = "#extern/verse/dist" BF_PYTHON = LIBDIR + '/python' BF_PYTHON_VERSION = '2.5' +WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' BF_PYTHON_LIB = 'python25' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/lib25_vs2005' +BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/lib25_vs2005/libpython25.a' WITH_BF_OPENAL = True WITH_BF_STATICOPENAL = False @@ -170,4 +172,4 @@ BF_PROFILE = False BF_BUILDDIR = '..\\build\\win32-mingw' BF_INSTALLDIR='..\\install\\win32-mingw' -BF_DOCDIR = '..\\install\\doc' \ No newline at end of file +BF_DOCDIR = '..\\install\\doc' From 49b5edddd4521d3bb5e6fe0e98cde026d69e27e4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 5 Jan 2009 10:54:26 +0000 Subject: [PATCH 107/252] left testing lines uncommitted by mistake --- release/scripts/import_web3d.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index 7542afcb5b9..6974edf8e07 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -918,7 +918,7 @@ class vrmlNode(object): lines.insert(0, 'root_node____') lines.append('}') ''' - ff = open('/root/test.txt', 'w') + ff = open('/tmp/test.txt', 'w') ff.writelines([l+'\n' for l in lines]) ''' @@ -1167,11 +1167,11 @@ def vrml_parse(path): lines.append('}') # Use for testing our parsed output, so we can check on line numbers. - - ff = open('/root/test.txt', 'w') + """ + ff = open('/tmp/test.txt', 'w') ff.writelines([l+'\n' for l in lines]) ff.close() - + """ # Now evaluate it node_type, new_i = is_nodeline(0, []) From 823aa30cba2d9e6d209ee9f5f5dbdbf2fd70264e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 6 Jan 2009 08:58:45 +0000 Subject: [PATCH 108/252] string extraction wasnt working + minor changes --- release/scripts/import_web3d.py | 49 +++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index 6974edf8e07..d73f05483bb 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -52,11 +52,11 @@ def dirName(path): def imageConvertCompat(path): - try: import os - except: - return path + try: import os + except: return path + if os.sep=='\\': return path # assime win32 has quicktime, dont convert - if path.endswith('.gif'): + if path.lower().endswith('.gif'): path_to = path[:-3] + 'png' ''' @@ -147,13 +147,12 @@ def vrmlFormat(data): data = data[:start] + data[end:] ok = True # keep looking - last_i = end - len(item) + 1 + last_i = (end - len(item)) + 1 # print last_i, item, '|' + data[last_i] + '|' # done with messy extracting strings part - # Bad, dont take strings into account ''' data = data.replace('#', '\n#') @@ -175,13 +174,14 @@ def vrmlFormat(data): while ok: ok = False i = data.find(search + '"', last_i) - + # print i if i != -1: start = i + len(search) # first char after end of search item = string_ls.pop(0) + # print item data = data[:start] + item + data[start:] - last_i = start + len(item) + last_i = start + len(item) + 1 ok = True @@ -918,7 +918,7 @@ class vrmlNode(object): lines.insert(0, 'root_node____') lines.append('}') ''' - ff = open('/tmp/test.txt', 'w') + ff = open('/root/test.txt', 'w') ff.writelines([l+'\n' for l in lines]) ''' @@ -1167,11 +1167,11 @@ def vrml_parse(path): lines.append('}') # Use for testing our parsed output, so we can check on line numbers. - """ + ff = open('/tmp/test.txt', 'w') ff.writelines([l+'\n' for l in lines]) ff.close() - """ + # Now evaluate it node_type, new_i = is_nodeline(0, []) @@ -1908,7 +1908,7 @@ def importShape(node, ancestry): ima_url = ima.getFieldAsString('url', None, ancestry) if ima_url==None: - try: ima_url = ima.getFieldAsStringArray('url', None, ancestry)[0] # in some cases we get a list of images. + try: ima_url = ima.getFieldAsStringArray('url', ancestry)[0] # in some cases we get a list of images. except: ima_url = None if ima_url==None: @@ -2137,6 +2137,10 @@ def importTransform(node, ancestry): bpyob = node.blendObject = bpy.data.scenes.active.objects.new('Empty', name) # , name) bpyob.setMatrix( getFinalMatrix(node, None, ancestry) ) + # so they are not too annoying + bpyob.emptyShape= Blender.Object.EmptyShapes.AXES + bpyob.drawSize= 0.2 + #def importTimeSensor(node): @@ -2332,8 +2336,12 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): prefix = node.getPrefix() if prefix=='PROTO': pass - el + else ''' + if HELPER_FUNC and HELPER_FUNC(node, ancestry): + # Note, include this function so the VRML/X3D importer can be extended + # by an external script. - gets first pick + pass if spec=='Shape': importShape(node, ancestry) elif spec in ('PointLight', 'DirectionalLight', 'SpotLight'): @@ -2350,15 +2358,9 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): ipo = bpy.data.ipos.new('web3d_ipo', 'Object') translatePositionInterpolator(node, ipo) ''' - - else: - # Note, include this function so the VRML/X3D importer can be extended - # by an external script. - if HELPER_FUNC: - HELPER_FUNC(node, ancestry) - - - + + + # After we import all nodes, route events - anim paths for node, ancestry in all_nodes: importRoute(node, ancestry) @@ -2503,4 +2505,5 @@ def test(): bpy.data.scenes.active = sce # Window. load_web3d(f, PREF_FLAT=True) - \ No newline at end of file + + From 70c5417ed688bad5024eb46cae867ce623accb2c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 6 Jan 2009 12:30:28 +0000 Subject: [PATCH 109/252] Added support for EXTERNPROTO's and fixed a bug where relative Inline URL's that included a path didn't load --- release/scripts/import_web3d.py | 99 +++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 11 deletions(-) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index d73f05483bb..5ea433ad484 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -258,6 +258,10 @@ def is_nodeline(i, words): if lines[i].startswith('PROTO'): words[:] = lines[i].split() return NODE_NORMAL, i+1 # TODO - assumes the next line is a '[\n', skip that + if lines[i].startswith('EXTERNPROTO'): + words[:] = lines[i].split() + return NODE_ARRAY, i+1 # TODO - assumes the next line is a '[\n', skip that + ''' proto_type, new_i = is_protoline(i, words, proto_field_defs) if new_i != -1: @@ -437,6 +441,17 @@ class vrmlNode(object): except: return None + def findSpecRecursive(self, spec): + self_real = self.getRealNode() + if spec == self_real.getSpec(): + return self + + for child in self_real.children: + if child.findSpecRecursive(spec): + return child + + return None + def getPrefix(self): if self.id: return self.id[0] @@ -453,6 +468,9 @@ class vrmlNode(object): def getProtoName(self): return self.getSpecialTypeName('PROTO') + + def getExternprotoName(self): + return self.getSpecialTypeName('EXTERNPROTO') def getChildrenBySpec(self, node_spec): # spec could be Transform, Shape, Appearance self_real = self.getRealNode() @@ -496,14 +514,19 @@ class vrmlNode(object): # where the parent of this object is not the real parent # - In this case we have added the proto as a child to a node instancing it. # This is a bit arbitary, but its how Proto's are done with this importer. - if child.getProtoName() == None: + if child.getProtoName() == None and child.getExternprotoName() == None: child.getSerialized(results, ancestry) else: - if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), self.getSpec() - if child.getProtoName()==self.getSpec(): + if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), child.getExternprotoName(), self.getSpec() + + self_spec = self.getSpec() + + if child.getProtoName() == self_spec or child.getExternprotoName() == self_spec: if DEBUG: "FoundProto!" child.getSerialized(results, ancestry) + + return results @@ -869,19 +892,52 @@ class vrmlNode(object): # print self.id, self.getFilename() - # If we were an inline then try load the file + # Check if this node was an inline or externproto + + url_ls = [] + if self.node_type == NODE_NORMAL and self.getSpec() == 'Inline': - - ancestry = [] # Warning! - PROTO's using this wont work at all. url = self.getFieldAsString('url', None, ancestry) + if url: + url_ls = [(url, None)] del ancestry + + elif self.getExternprotoName(): + # externproto + url_ls = [] + for f in self.fields: + + if type(f)==str: + f = [f] + + for ff in f: + for f_split in ff.split('"'): + # print f_split + # "someextern.vrml#SomeID" + if '#' in f_split: + + f_split, f_split_id = f_split.split('#') # there should only be 1 # anyway + + url_ls.append( (f_split, f_split_id) ) + else: + url_ls.append( (f_split, None) ) + + + # Was either an Inline or an EXTERNPROTO + if url_ls: - if url != None: + # print url_ls + + for url, extern_key in url_ls: + print url urls = [] urls.append( url ) urls.append( BPySys.caseInsensitivePath(urls[-1]) ) + urls.append( dirName(self.getFilename()) + url ) + urls.append( BPySys.caseInsensitivePath(urls[-1]) ) + urls.append( dirName(self.getFilename()) + baseName(url) ) urls.append( BPySys.caseInsensitivePath(urls[-1]) ) @@ -918,7 +974,7 @@ class vrmlNode(object): lines.insert(0, 'root_node____') lines.append('}') ''' - ff = open('/root/test.txt', 'w') + ff = open('/tmp/test.txt', 'w') ff.writelines([l+'\n' for l in lines]) ''' @@ -926,9 +982,28 @@ class vrmlNode(object): child.setRoot(url) # initialized dicts child.parse(0) + # if self.getExternprotoName(): + + if not extern_key: # if none is spesified - use the name + extern_key = self.getSpec() + + if extern_key: + + self.children.remove(child) + child.parent = None + + extern_child = child.findSpecRecursive(extern_key) + + if extern_child: + self.children.append(extern_child) + extern_child.parent = self + + if DEBUG: print "\tEXTERNPROTO ID found!:", extern_key + else: + print "\tEXTERNPROTO ID not found!:", extern_key + # Watch it! - restore lines lines[:] = lines_old - return new_i @@ -967,6 +1042,8 @@ class vrmlNode(object): self.getDefDict()[ key ] = self key = self.getProtoName() + if not key: key = self.getExternprotoName() + proto_dict = self.getProtoDict() if key != None: proto_dict[ key ] = self @@ -1167,11 +1244,11 @@ def vrml_parse(path): lines.append('}') # Use for testing our parsed output, so we can check on line numbers. - + ''' ff = open('/tmp/test.txt', 'w') ff.writelines([l+'\n' for l in lines]) ff.close() - + ''' # Now evaluate it node_type, new_i = is_nodeline(0, []) From f6f309d2d134e38041fd92da40d6dba879d2b263 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 6 Jan 2009 18:10:13 +0000 Subject: [PATCH 110/252] In the panel, next to the number of joints, display the name of the current bone while sketching joints. Displays "Bone offset" when the next bone is not connected. Displays "Done" when all joints have been draw (note: you can draw more joints then needed, the retargetting algo will use the most useful ones). Convert gesture is back. This time, it's a 3 straight line that cross itself once gesture (like drawing a triangle and recrossing the first line). --- source/blender/include/BIF_retarget.h | 1 + source/blender/include/BIF_sketch.h | 3 +- source/blender/include/reeb.h | 2 +- source/blender/src/drawview.c | 7 ++-- source/blender/src/editarmature_retarget.c | 30 +++++++++++++++++ source/blender/src/editarmature_sketch.c | 38 ++++++++++++++++++++++ 6 files changed, 77 insertions(+), 4 deletions(-) diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h index 9400b69e483..9de10fb2a38 100644 --- a/source/blender/include/BIF_retarget.h +++ b/source/blender/include/BIF_retarget.h @@ -148,6 +148,7 @@ typedef struct RigControl { void BIF_retargetArc(ReebArc *earc, RigGraph *template_rigg); RigGraph *RIG_graphFromArmature(struct Object *ob, struct bArmature *arm); int RIG_nbJoints(RigGraph *rg); +char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index); void RIG_freeRigGraph(BGraph *rg); #endif /* BIF_RETARGET_H */ diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h index 28b975487de..9cd7393633e 100644 --- a/source/blender/include/BIF_sketch.h +++ b/source/blender/include/BIF_sketch.h @@ -37,6 +37,7 @@ char *BIF_listTemplates(); int BIF_currentTemplate(); void BIF_freeTemplates(); void BIF_setTemplate(int); -int BIF_nbJointsTemplate(); +int BIF_nbJointsTemplate(); +char * BIF_nameBoneTemplate(); #endif /* BIF_SKETCH_H */ diff --git a/source/blender/include/reeb.h b/source/blender/include/reeb.h index 2f463d6194b..eab0e2a8601 100644 --- a/source/blender/include/reeb.h +++ b/source/blender/include/reeb.h @@ -28,7 +28,7 @@ #ifndef REEB_H_ #define REEB_H_ -//#define WITH_BF_REEB +#define WITH_BF_REEB #include "DNA_listBase.h" diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 3dfec925474..cbc3ea45b0b 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2291,9 +2291,10 @@ static void assign_template_sketch_armature(void *arg1, void *arg2) static void view3d_panel_bonesketch_spaces(short cntrl) { static int template_index; - static char joint_label[32]; + static char joint_label[128]; uiBlock *block; uiBut *but; + char *bone_name; int yco = 130, height = 140; int nb_joints; @@ -2379,7 +2380,9 @@ static void view3d_panel_bonesketch_spaces(short cntrl) nb_joints = G.totvertsel; } - BLI_snprintf(joint_label, 32, "%i joints", nb_joints); + bone_name = BIF_nameBoneTemplate(); + + BLI_snprintf(joint_label, 32, "%i joints: %s", nb_joints, bone_name); uiDefBut(block, LABEL, 1, joint_label, 10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, ""); yco -= 20; diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index 0d83ee846a0..fe1c394f326 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -2903,6 +2903,36 @@ static void retargetGraphs(RigGraph *rigg) editbones_to_armature(rigg->editbones, rigg->ob); } +char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index) +{ + RigArc *arc = BLI_findlink(&rg->arcs, arc_index); + RigEdge *iedge; + + if (arc == NULL) + { + return "None"; + } + + if (bone_index == BLI_countlist(&arc->edges)) + { + return "Last joint"; + } + + iedge = BLI_findlink(&arc->edges, bone_index); + + if (iedge == NULL) + { + return "Done"; + } + + if (iedge->bone == NULL) + { + return "Bone offset"; + } + + return iedge->bone->name; +} + int RIG_nbJoints(RigGraph *rg) { RigArc *arc; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index c63575c8b7a..93fa01c0794 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -189,6 +189,8 @@ int sk_detectMergeGesture(SK_Gesture *gest, SK_Sketch *sketch); void sk_applyMergeGesture(SK_Gesture *gest, SK_Sketch *sketch); int sk_detectReverseGesture(SK_Gesture *gest, SK_Sketch *sketch); void sk_applyReverseGesture(SK_Gesture *gest, SK_Sketch *sketch); +int sk_detectConvertGesture(SK_Gesture *gest, SK_Sketch *sketch); +void sk_applyConvertGesture(SK_Gesture *gest, SK_Sketch *sketch); /******************** GESTURE ACTIONS ******************************/ @@ -201,6 +203,7 @@ SK_GestureAction GESTURE_ACTIONS[] = {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture}, {"Merge", sk_detectMergeGesture, sk_applyMergeGesture}, {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture}, + {"Convert", sk_detectConvertGesture, sk_applyConvertGesture}, {"", NULL, NULL} }; @@ -340,6 +343,27 @@ int BIF_nbJointsTemplate() } } +char * BIF_nameBoneTemplate() +{ + SK_Sketch *stk = GLOBAL_sketch; + RigGraph *rg; + int index = 0; + + if (stk && stk->active_stroke != NULL) + { + index = stk->active_stroke->nb_points; + } + + rg = sk_makeTemplateGraph(G.scene->toolsettings->skgen_template); + + if (rg == NULL) + { + return ""; + } + + return RIG_nameBone(rg, 0, index); +} + void BIF_freeTemplates() { if (TEMPLATES_MENU != NULL) @@ -2450,6 +2474,20 @@ void sk_applyReverseGesture(SK_Gesture *gest, SK_Sketch *sketch) } } +int sk_detectConvertGesture(SK_Gesture *gest, SK_Sketch *sketch) +{ + if (gest->nb_segments == 3 && gest->nb_self_intersections == 1) + { + return 1; + } + return 0; +} + +void sk_applyConvertGesture(SK_Gesture *gest, SK_Sketch *sketch) +{ + sk_convert(sketch); +} + static void sk_initGesture(SK_Gesture *gest, SK_Sketch *sketch) { gest->intersections.first = gest->intersections.last = NULL; From 9b3727b5e094e2b23f72396bcf072baa410d3170 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 6 Jan 2009 19:00:22 +0000 Subject: [PATCH 111/252] Fix crasher on non-reset pointer. Mostly happened panning view while drawing. --- source/blender/src/editarmature_sketch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 93fa01c0794..05729f1c4fc 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1514,6 +1514,7 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D float vec[3]; float new_dist; + p2 = NULL; p1->flag = 1; /* if peeling objects, take the first and last from each object */ From 529692872813d86d59ac443c45ac3a385e432b8d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 7 Jan 2009 03:34:12 +0000 Subject: [PATCH 112/252] confusion between Inline and externproto nodes --- release/scripts/import_web3d.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index 5ea433ad484..efe30d9a9b8 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -983,24 +983,24 @@ class vrmlNode(object): child.parse(0) # if self.getExternprotoName(): - - if not extern_key: # if none is spesified - use the name - extern_key = self.getSpec() - - if extern_key: + if self.getExternprotoName(): + if not extern_key: # if none is spesified - use the name + extern_key = self.getSpec() - self.children.remove(child) - child.parent = None - - extern_child = child.findSpecRecursive(extern_key) - - if extern_child: - self.children.append(extern_child) - extern_child.parent = self + if extern_key: - if DEBUG: print "\tEXTERNPROTO ID found!:", extern_key - else: - print "\tEXTERNPROTO ID not found!:", extern_key + self.children.remove(child) + child.parent = None + + extern_child = child.findSpecRecursive(extern_key) + + if extern_child: + self.children.append(extern_child) + extern_child.parent = self + + if DEBUG: print "\tEXTERNPROTO ID found!:", extern_key + else: + print "\tEXTERNPROTO ID not found!:", extern_key # Watch it! - restore lines lines[:] = lines_old From fc12ec23171833d6b8a12f54c5e6148819c3e3b5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 7 Jan 2009 11:27:17 +0000 Subject: [PATCH 113/252] don't raise exceptions on some errors unless debugging --- release/scripts/import_web3d.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index efe30d9a9b8..28bc1a40ef0 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -1076,6 +1076,9 @@ class vrmlNode(object): # print self.id ok = True while ok: + if i>=len(lines): + return len(lines)-1 + l = lines[i] # print '\tDEBUG:', i, self.node_type, l if l=='': @@ -1085,13 +1088,15 @@ class vrmlNode(object): if l=='}': if self.node_type != NODE_NORMAL: # also ends proto nodes, we may want a type for these too. print 'wrong node ending, expected an } ' + str(i) + ' ' + str(self.node_type) - raise ValueError + if DEBUG: + raise ValueError ### print "returning", i return i+1 if l==']': if self.node_type != NODE_ARRAY: print 'wrong node ending, expected a ] ' + str(i) + ' ' + str(self.node_type) - raise ValueError + if DEBUG: + raise ValueError ### print "returning", i return i+1 @@ -2567,12 +2572,12 @@ def test(): files.sort() tot = len(files) for i, f in enumerate(files): - #if i < 126 or i > 1000000: - # continue - - if i != 1068: + if i < 124 or i > 1000000: continue + #if i != 1068: + # continue + #if i != 12686: # continue @@ -2583,4 +2588,4 @@ def test(): # Window. load_web3d(f, PREF_FLAT=True) - +# test() From 1240b0272d81fea988b2b92978179fb1bdfc3a7e Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 7 Jan 2009 21:46:10 +0000 Subject: [PATCH 114/252] adjust strokes by redrawing over them (has to be turned on in the panel because it can give unexpected results sometimes right now) http://vimeo.com/2753749 http://blenderartists.org/~theeth/bf/etch-a-ton/adjust.ogv --- source/blender/makesdna/DNA_scene_types.h | 1 + source/blender/src/drawview.c | 3 +- source/blender/src/editarmature_sketch.c | 175 ++++++++++++++++++++-- 3 files changed, 169 insertions(+), 10 deletions(-) diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index a5491578115..2d5097e7899 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -881,6 +881,7 @@ typedef struct Scene { /* toolsettings->bone_sketching */ #define BONE_SKETCHING 1 #define BONE_SKETCHING_QUICK 2 +#define BONE_SKETCHING_ADJUST 4 /* toolsettings->bone_sketching_convert */ #define SK_CONVERT_CUT_FIXED 1 diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index cbc3ea45b0b..0230974b509 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2312,7 +2312,8 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockBeginAlign(block); /* use real flag instead of 1 */ - uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 180, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 160, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones"); + uiDefButBitC(block, TOG, BONE_SKETCHING_ADJUST, B_REDR, "A", 170, yco, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Adjust strokes by drawing near them"); uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 190, yco, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end"); yco -= 20; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 05729f1c4fc..d66760dae80 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -92,6 +92,12 @@ typedef struct SK_Stroke int selected; } SK_Stroke; +typedef struct SK_Adjustment +{ + SK_Stroke *target; + int start, end; +} SK_Adjustment; + #define SK_Stroke_BUFFER_INIT_SIZE 20 typedef struct SK_DrawData @@ -118,6 +124,7 @@ typedef struct SK_Sketch SK_Stroke *active_stroke; SK_Stroke *gesture; SK_Point next_point; + SK_Adjustment adj; } SK_Sketch; typedef struct SK_StrokeIterator { @@ -836,6 +843,26 @@ void sk_growStrokeBuffer(SK_Stroke *stk) } } +void sk_growStrokeBufferN(SK_Stroke *stk, int n) +{ + if (stk->nb_points + n > stk->buf_size) + { + SK_Point *old_points = stk->points; + + while (stk->nb_points + n > stk->buf_size) + { + stk->buf_size *= 2; + } + + sk_allocStrokeBuffer(stk); + + memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); + + MEM_freeN(old_points); + } +} + + void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n) { memcpy(stk->points + n, pt, sizeof(SK_Point)); @@ -863,6 +890,24 @@ void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt) stk->nb_points++; } +void sk_inserStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end) +{ + int size = end - start + 1; + + sk_growStrokeBufferN(stk, len - size); + + if (len != size) + { + int tail_size = stk->nb_points - end + 1; + + memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point)); + } + + memcpy(stk->points + start, pts, len * sizeof(SK_Point)); + + stk->nb_points += len - size; +} + void sk_trimStroke(SK_Stroke *stk, int start, int end) { int size = end - start + 1; @@ -1221,14 +1266,14 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) } } -SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist) +SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist, int *index) { SK_Point *pt = NULL; int i; for (i = 0; i < stk->nb_points; i++) { - if (stk->points[i].type == PT_EXACT) + if (1) // stk->points[i].type == PT_EXACT) { short pval[2]; int pdist; @@ -1241,6 +1286,11 @@ SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist) { *dist = pdist; pt = stk->points + i; + + if (index != NULL) + { + *index = i; + } } } } @@ -1295,17 +1345,121 @@ SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int return pt; } +void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) +{ + if (sketch->adj.target == NULL) + { + SK_Stroke *target; + int closest_index = 0; + int dist = SNAP_MIN_DISTANCE * 2; + + for (target = sketch->strokes.first; target; target = target->next) + { + if (target != stk) + { + int index; + + SK_Point *spt = sk_snapPointStroke(target, dd->mval, &dist, &index); + + if (spt != NULL) + { + sketch->adj.target = target; + closest_index = index; + } + } + } + + if (sketch->adj.target != NULL) + { + if (stk->nb_points == 1) + { + sketch->adj.start = closest_index; + } + else + { + sketch->adj.end = closest_index; + } + sketch->adj.target->selected = 1; + } + } + else if (sketch->adj.target != NULL) + { + SK_Point *closest_pt = NULL; + int dist = SNAP_MIN_DISTANCE * 2; + int index; + + closest_pt = sk_snapPointStroke(sketch->adj.target, dd->mval, &dist, &index); + + if (closest_pt != NULL) + { + sketch->adj.end = index; + } + else + { + sketch->adj.end = 0; + } + } +} + +void sk_endAdjust(SK_Sketch *sketch) +{ + SK_Stroke *stk = sketch->active_stroke; + + if (sketch->adj.target) + { + int start = sketch->adj.start; + int end = sketch->adj.end; + + if (end == 0) + { + end = sketch->adj.target->nb_points - 1; + } + else + { + sk_lastStrokePoint(stk)->type = PT_CONTINUOUS; + } + + if (start != 0) + { + stk->points->type = PT_CONTINUOUS; + } + + if (end < start) + { + int tmp = start; + start = end; + end = tmp; + sk_reverseStroke(stk); + } + + sk_inserStrokePoints(sketch->adj.target, stk->points, stk->nb_points, start, end); + + sk_removeStroke(sketch, stk); + } +} + + void sk_startStroke(SK_Sketch *sketch) { SK_Stroke *stk = sk_createStroke(); BLI_addtail(&sketch->strokes, stk); sketch->active_stroke = stk; + + sketch->adj.target = NULL; + sketch->adj.start = 0; + sketch->adj.end = 0; } void sk_endStroke(SK_Sketch *sketch) { sk_shrinkStrokeBuffer(sketch->active_stroke); + + if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST) + { + sk_endAdjust(sketch); + } + sketch->active_stroke = NULL; } @@ -1412,7 +1566,7 @@ int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *source_stk for (stk = sketch->strokes.first; stk; stk = stk->next) { - SK_Point *spt = sk_snapPointStroke(stk, dd->mval, &dist); + SK_Point *spt = sk_snapPointStroke(stk, dd->mval, &dist, NULL); if (spt != NULL) { @@ -1648,7 +1802,12 @@ void sk_addStrokePoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short if (point_added == 0) { point_added = sk_addStrokeDrawPoint(sketch, stk, dd); - } + } + + if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST) + { + sk_updateAdjust(sketch, stk, dd); + } } void sk_getStrokePoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual) @@ -2749,6 +2908,9 @@ int sk_paint(SK_Sketch *sketch, short mbut) if (sketch->active_stroke == NULL) { sk_startStroke(sketch); + sk_selectAllSketch(sketch, -1); + + sketch->active_stroke->selected = 1; } sk_initDrawData(&dd); @@ -2806,11 +2968,6 @@ int sk_paint(SK_Sketch *sketch, short mbut) sk_removeStroke(sketch, stk); allqueue(REDRAWBUTSEDIT, 0); } - else - { - sk_selectAllSketch(sketch, -1); - stk->selected = 1; - } allqueue(REDRAWVIEW3D, 0); } From 133ddcff049182c30fd5fd2ea4c0c0a6f8626a1e Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 8 Jan 2009 18:23:48 +0000 Subject: [PATCH 115/252] display overdrawn stroke in gray, to easily see what is being replaced. --- source/blender/src/editarmature_sketch.c | 109 +++++++++++++++++------ 1 file changed, 82 insertions(+), 27 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index d66760dae80..2b5a9ae07c5 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -96,6 +96,7 @@ typedef struct SK_Adjustment { SK_Stroke *target; int start, end; + int count; } SK_Adjustment; #define SK_Stroke_BUFFER_INIT_SIZE 20 @@ -200,6 +201,9 @@ int sk_detectConvertGesture(SK_Gesture *gest, SK_Sketch *sketch); void sk_applyConvertGesture(SK_Gesture *gest, SK_Sketch *sketch); +void sk_resetAdjust(SK_Sketch *sketch); +int sk_hasAdjust(SK_Sketch *sketch, SK_Stroke *stk); + /******************** GESTURE ACTIONS ******************************/ SK_GestureAction GESTURE_ACTIONS[] = @@ -1013,6 +1017,7 @@ void sk_cancelStroke(SK_Sketch *sketch) { if (sketch->active_stroke != NULL) { + sk_resetAdjust(sketch); sk_removeStroke(sketch, sketch->active_stroke); } } @@ -1122,7 +1127,7 @@ SK_Point *sk_lastStrokePoint(SK_Stroke *stk) return pt; } -void sk_drawStroke(SK_Stroke *stk, int id, float color[3]) +void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end) { float rgb[3]; int i; @@ -1153,7 +1158,14 @@ void sk_drawStroke(SK_Stroke *stk, int id, float color[3]) for (i = 0; i < stk->nb_points; i++) { - glColor3fv(rgb); + if (i >= start && i <= end) + { + glColor3f(0.3, 0.3, 0.3); + } + else + { + glColor3fv(rgb); + } glVertex3fv(stk->points[i].p); VecAddf(rgb, rgb, d_rgb); } @@ -1345,12 +1357,25 @@ SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int return pt; } +void sk_resetAdjust(SK_Sketch *sketch) +{ + sketch->adj.target = NULL; + sketch->adj.start = 0; + sketch->adj.end = 0; + sketch->adj.count = 0; +} + +int sk_hasAdjust(SK_Sketch *sketch, SK_Stroke *stk) +{ + return sketch->adj.target && sketch->adj.count >= 3 && (sketch->adj.target == stk || stk == NULL); +} + void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { if (sketch->adj.target == NULL) { SK_Stroke *target; - int closest_index = 0; + int closest_index = -1; int dist = SNAP_MIN_DISTANCE * 2; for (target = sketch->strokes.first; target; target = target->next) @@ -1371,6 +1396,11 @@ void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) if (sketch->adj.target != NULL) { + if (closest_index > -1) + { + sketch->adj.count++; + } + if (stk->nb_points == 1) { sketch->adj.start = closest_index; @@ -1379,7 +1409,6 @@ void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { sketch->adj.end = closest_index; } - sketch->adj.target->selected = 1; } } else if (sketch->adj.target != NULL) @@ -1392,31 +1421,52 @@ void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) if (closest_pt != NULL) { + sketch->adj.count++; sketch->adj.end = index; } else { - sketch->adj.end = 0; + sketch->adj.end = -1; } } } +/* return 1 on reverse needed */ +int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end) +{ + int retval = 0; + + *start = sketch->adj.start; + *end = sketch->adj.end; + + if (*end == -1) + { + *end = sketch->adj.target->nb_points - 1; + } + + if (*end < *start) + { + int tmp = *start; + *start = *end; + *end = tmp; + retval = 1; + } + + return retval; +} + void sk_endAdjust(SK_Sketch *sketch) { SK_Stroke *stk = sketch->active_stroke; - if (sketch->adj.target) + if (sk_hasAdjust(sketch, NULL)) { - int start = sketch->adj.start; - int end = sketch->adj.end; + int start; + int end; - if (end == 0) + if (sk_adjustIndexes(sketch, &start, &end)) { - end = sketch->adj.target->nb_points - 1; - } - else - { - sk_lastStrokePoint(stk)->type = PT_CONTINUOUS; + sk_reverseStroke(stk); } if (start != 0) @@ -1424,17 +1474,16 @@ void sk_endAdjust(SK_Sketch *sketch) stk->points->type = PT_CONTINUOUS; } - if (end < start) + if (end != sketch->adj.target->nb_points - 1) { - int tmp = start; - start = end; - end = tmp; - sk_reverseStroke(stk); + sk_lastStrokePoint(stk)->type = PT_CONTINUOUS; } sk_inserStrokePoints(sketch->adj.target, stk->points, stk->nb_points, start, end); sk_removeStroke(sketch, stk); + + sk_resetAdjust(sketch); } } @@ -1445,10 +1494,8 @@ void sk_startStroke(SK_Sketch *sketch) BLI_addtail(&sketch->strokes, stk); sketch->active_stroke = stk; - - sketch->adj.target = NULL; - sketch->adj.start = 0; - sketch->adj.end = 0; + + sk_resetAdjust(sketch); } void sk_endStroke(SK_Sketch *sketch) @@ -2812,7 +2859,7 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) int id; for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next) { - sk_drawStroke(stk, id, NULL); + sk_drawStroke(stk, id, NULL, -1, -1); } glLoadName(-1); @@ -2824,7 +2871,15 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) for (stk = sketch->strokes.first; stk; stk = stk->next) { - sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb)); + int start = -1; + int end = -1; + + if (sk_hasAdjust(sketch, stk)) + { + sk_adjustIndexes(sketch, &start, &end); + } + + sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb), start, end); if (stk->selected == 1) { @@ -2836,7 +2891,7 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) if (sketch->gesture != NULL && area_is_active_area(G.vd->area)) { float gesture_rgb[3] = {0, 0.5, 1}; - sk_drawStroke(sketch->gesture, -1, gesture_rgb); + sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1); } if (sketch->active_stroke != NULL) @@ -2860,7 +2915,7 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) } glEnable(GL_LINE_STIPPLE); - glColor3f(1, 0.5, 0); + glColor3fv(selected_rgb); glBegin(GL_LINE_STRIP); glVertex3fv(last->p); From f1c4b4e7c5a574e91da2d0e7e6f6c778b5c445df Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 9 Jan 2009 19:25:10 +0000 Subject: [PATCH 116/252] Last version of overdraw didn't work great with polylines. Fix this and misc wrong initial values. --- source/blender/src/editarmature_sketch.c | 27 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 2b5a9ae07c5..fc0da1c397b 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -92,6 +92,8 @@ typedef struct SK_Stroke int selected; } SK_Stroke; +#define SK_ADJUST_LIMIT 5 + typedef struct SK_Adjustment { SK_Stroke *target; @@ -1360,14 +1362,14 @@ SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int void sk_resetAdjust(SK_Sketch *sketch) { sketch->adj.target = NULL; - sketch->adj.start = 0; - sketch->adj.end = 0; + sketch->adj.start = -1; + sketch->adj.end = -1; sketch->adj.count = 0; } int sk_hasAdjust(SK_Sketch *sketch, SK_Stroke *stk) { - return sketch->adj.target && sketch->adj.count >= 3 && (sketch->adj.target == stk || stk == NULL); + return sketch->adj.target && sketch->adj.count >= SK_ADJUST_LIMIT && (sketch->adj.target == stk || stk == NULL); } void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) @@ -1398,7 +1400,14 @@ void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { if (closest_index > -1) { - sketch->adj.count++; + if (sk_lastStrokePoint(stk)->type == PT_EXACT) + { + sketch->adj.count = SK_ADJUST_LIMIT; + } + else + { + sketch->adj.count++; + } } if (stk->nb_points == 1) @@ -1421,7 +1430,15 @@ void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) if (closest_pt != NULL) { - sketch->adj.count++; + if (sk_lastStrokePoint(stk)->type == PT_EXACT) + { + sketch->adj.count = SK_ADJUST_LIMIT; + } + else + { + sketch->adj.count++; + } + sketch->adj.end = index; } else From 7e76ce5d6775ca08f66e0c66f13caa2e09c575d6 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 9 Jan 2009 20:35:37 +0000 Subject: [PATCH 117/252] missing test for start of line caused crashes. --- source/blender/src/editarmature_sketch.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index fc0da1c397b..e65d4346df2 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1456,6 +1456,11 @@ int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end) *start = sketch->adj.start; *end = sketch->adj.end; + if (*start == -1) + { + *start = 0; + } + if (*end == -1) { *end = sketch->adj.target->nb_points - 1; From 07599ab3b28a3ca2a7204fae7d8c37fa64d888b3 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 9 Jan 2009 20:50:13 +0000 Subject: [PATCH 118/252] limit overdraw to at least start or end near another stroke (otherwise, all strokes that crossed others replace them entirely). --- source/blender/src/editarmature_sketch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index e65d4346df2..e4e841adde3 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1369,7 +1369,10 @@ void sk_resetAdjust(SK_Sketch *sketch) int sk_hasAdjust(SK_Sketch *sketch, SK_Stroke *stk) { - return sketch->adj.target && sketch->adj.count >= SK_ADJUST_LIMIT && (sketch->adj.target == stk || stk == NULL); + return sketch->adj.target && + sketch->adj.count >= SK_ADJUST_LIMIT && + (sketch->adj.target == stk || stk == NULL) && + (sketch->adj.start != -1 || sketch->adj.end != -1); } void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) From 9f742a0ba19796ce6f2b11950f1388538a3ba66d Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 9 Jan 2009 22:13:59 +0000 Subject: [PATCH 119/252] Don't change point type on overdrawn when there's only one. --- source/blender/src/editarmature_sketch.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index e4e841adde3..192718c058f 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1494,14 +1494,17 @@ void sk_endAdjust(SK_Sketch *sketch) sk_reverseStroke(stk); } - if (start != 0) + if (stk->nb_points > 1) { - stk->points->type = PT_CONTINUOUS; - } - - if (end != sketch->adj.target->nb_points - 1) - { - sk_lastStrokePoint(stk)->type = PT_CONTINUOUS; + if (start != 0) + { + stk->points->type = PT_CONTINUOUS; + } + + if (end != sketch->adj.target->nb_points - 1) + { + sk_lastStrokePoint(stk)->type = PT_CONTINUOUS; + } } sk_inserStrokePoints(sketch->adj.target, stk->points, stk->nb_points, start, end); From 278d6758ea3dc30a54b3f5ee437becca6003667b Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Sun, 11 Jan 2009 16:13:00 +0000 Subject: [PATCH 120/252] == Scripts == - Scripts Help Browser: Brendon Murphy requested and Kevin Morgan implemented a "run script" button. - AC3D importer: option to store emis color from .ac file in mirror color in Blender (the exporter has the option to export mirror color as emis). Patch by Francesco Brisa. Thanks for the contributions. --- release/scripts/ac3d_import.py | 30 +++++++++++++++++++++--------- release/scripts/help_browser.py | 22 +++++++++++++++++----- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/release/scripts/ac3d_import.py b/release/scripts/ac3d_import.py index 6a2b290e010..2f5512e7150 100644 --- a/release/scripts/ac3d_import.py +++ b/release/scripts/ac3d_import.py @@ -10,7 +10,7 @@ Tip: 'Import an AC3D (.ac) file.' __author__ = "Willian P. Germano" __url__ = ("blender", "blenderartists.org", "AC3D's homepage, http://www.ac3d.org", "PLib 3d gaming lib, http://plib.sf.net") -__version__ = "2.43.1 2007-02-21" +__version__ = "2.48.1 2009-01-11" __bpydoc__ = """\ This script imports AC3D models into Blender. @@ -31,6 +31,7 @@ Known issues:
Config Options:
- display transp (toggle): if "on", objects that have materials with alpha < 1.0 are shown with translucency (transparency) in the 3D View.
- subdiv (toggle): if "on", ac3d objects meant to be subdivided receive a SUBSURF modifier in Blender.
+ - emis as mircol: store the emissive rgb color from AC3D as mirror color in Blender -- this is a hack to preserve the values and be able to export them using the equivalent option in the exporter.
- textures dir (string): if non blank, when imported texture paths are wrong in the .ac file, Blender will also look for them at this dir. @@ -50,11 +51,12 @@ users can configure (see config options above). # -------------------------------------------------------------------------- # Thanks: Melchior Franz for extensive bug testing and reporting, making this # version cope much better with old or bad .ac files, among other improvements; -# Stewart Andreason for reporting a serious crash. +# Stewart Andreason for reporting a serious crash; Francesco Brisa for the +# emis as mircol functionality (w/ patch). # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # -# Copyright (C) 2004-2007: Willian P. Germano, wgermano _at_ ig.com.br +# Copyright (C) 2004-2009: Willian P. Germano, wgermano _at_ ig.com.br # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -89,15 +91,19 @@ DISPLAY_TRANSP = True SUBDIV = True +EMIS_AS_MIRCOL = False + + tooltips = { 'DISPLAY_TRANSP': 'Turn transparency on in the 3d View for objects using materials with alpha < 1.0.', 'SUBDIV': 'Apply a SUBSURF modifier to objects meant to appear subdivided.', - 'TEXTURES_DIR': 'Additional folder to look for missing textures.' + 'TEXTURES_DIR': 'Additional folder to look for missing textures.', + 'EMIS_AS_MIRCOL': 'Store emis color as mirror color in Blender.' } def update_registry(): - global TEXTURES_DIR, DISPLAY_TRANSP - rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV)]) + global TEXTURES_DIR, DISPLAY_TRANSP, EMIS_AS_MIRCOL + rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV), ('EMIS_AS_MIRCOL', EMIS_AS_MIRCOL)]) Registry.SetKey('ac3d_import', rd, True) rd = Registry.GetKey('ac3d_import', True) @@ -109,6 +115,7 @@ if rd: TEXTURES_DIR = rd['TEXTURES_DIR'] DISPLAY_TRANSP = rd['DISPLAY_TRANSP'] SUBDIV = rd['SUBDIV'] + EMIS_AS_MIRCOL = rd['EMIS_AS_MIRCOL'] except: update_registry() else: update_registry() @@ -299,7 +306,7 @@ class AC3DImport: lines = self.lines line = lines[i].split() mat_name = '' - mat_col = mat_amb = mat_emit = mat_spec_col = [0,0,0] + mat_col = mat_amb = mat_emit = mat_spec_col = mat_mir_col = [0,0,0] mat_alpha = 1 mat_spec = 1.0 @@ -310,11 +317,15 @@ class AC3DImport: mat_amb = (v[0]+v[1]+v[2]) / 3.0 v = map(float,[line[11],line[12],line[13]]) mat_emit = (v[0]+v[1]+v[2]) / 3.0 + if EMIS_AS_MIRCOL: + mat_emit = 0 + mat_mir_col = map(float,[line[11],line[12],line[13]]) + mat_spec_col = map(float,[line[15],line[16],line[17]]) mat_spec = float(line[19]) / 64.0 mat_alpha = float(line[-1]) mat_alpha = 1 - mat_alpha - self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_alpha]) + self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_mir_col, mat_alpha]) i += 1 line = lines[i].split() @@ -590,7 +601,8 @@ class AC3DImport: m.emit = mat[3] m.specCol = (mat[4][0], mat[4][1], mat[4][2]) m.spec = mat[5] - m.alpha = mat[6] + m.mirCol = (mat[6][0], mat[6][1], mat[6][2]) + m.alpha = mat[7] if m.alpha < 1.0: m.mode |= MAT_MODE_ZTRANSP has_transp_mats = True diff --git a/release/scripts/help_browser.py b/release/scripts/help_browser.py index b27e266f368..b5d747ee9c4 100644 --- a/release/scripts/help_browser.py +++ b/release/scripts/help_browser.py @@ -8,7 +8,7 @@ Tooltip: 'Show help information about a chosen installed script.' """ __author__ = "Willian P. Germano" -__version__ = "0.1 11/02/04" +__version__ = "0.2 01/11/09" __email__ = ('scripts', 'Author, wgermano:ig*com*br') __url__ = ('blender', 'blenderartists.org') @@ -47,8 +47,6 @@ Hotkeys:
# $Id$ # # -------------------------------------------------------------------------- -# sysinfo.py version 0.1 Jun 09, 2004 -# -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # # Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br @@ -69,6 +67,8 @@ Hotkeys:
# # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- +# Thanks: Brendon Murphy (suggestion) and Kevin Morgan (implementation) +# for the "run" button. import Blender from Blender import sys as bsys, Draw, Window, Registry @@ -543,6 +543,7 @@ BEVT_GMENU = range(100, len_gmenus + 100) BEVT_VIEWSOURCE = 1 BEVT_EXIT = 2 BEVT_BACK = 3 +BEVT_EXEC = 4 # Executes Script # gui callbacks: @@ -551,7 +552,7 @@ def gui(): # drawing the screen global SCREEN, START_SCREEN, SCRIPT_SCREEN global SCRIPT_INFO, AllGroups, GROUP_MENUS global BEVT_EMAIL, BEVT_LINK - global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU + global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU, BEVT_EXEC global PADDING, WIN_W, WIN_H, SCROLL_DOWN, COLUMNS, FMODE theme = Theme.Get()[0] @@ -674,8 +675,11 @@ def gui(): # drawing the screen 'View this script\'s source code in the Text Editor (hotkey: S)') Draw.PushButton('exit', BEVT_EXIT, x + 45, 17, 45, bh, 'Exit from Scripts Help Browser (hotkey: Q)') - if not FMODE: Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh, + if not FMODE: + Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh, 'Back to scripts selection screen (hotkey: ESC)') + Draw.PushButton('run script', BEVT_EXEC, x + 3*45, 17, 60, bh, 'Run this script') + BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2]) BGL.glRasterPos2i(x, 5) Draw.Text('use the arrow keys or the mouse wheel to scroll text', 'small') @@ -766,6 +770,14 @@ def button_event(evt): # gui button events SCRIPT_INFO = None SCROLL_DOWN = 0 Draw.Redraw() + elif evt == BEVT_EXEC: # Execute script + exec_line = '' + if SCRIPT_INFO.script.userdir: + exec_line = bsys.join(Blender.Get('uscriptsdir'), SCRIPT_INFO.script.fname) + else: + exec_line = bsys.join(Blender.Get('scriptsdir'), SCRIPT_INFO.script.fname) + + Blender.Run(exec_line) keepon = True FMODE = False # called by Blender.ShowHelp(name) API function ? From ae15fc5e46761b8b1130ff8298370af9ca2fba9f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 12 Jan 2009 04:07:06 +0000 Subject: [PATCH 121/252] [#18082] make uvcalc_follow_active_coords.py bypass the gui and accept arguments when called from another script from Bill N (slow67) Also made uvcalc_quad_clickproj.py and uvcalc_follow_active_coords.py add UV's if they didn't exist. --- .../scripts/uvcalc_follow_active_coords.py | 47 ++++++++++--------- release/scripts/uvcalc_quad_clickproj.py | 6 ++- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/release/scripts/uvcalc_follow_active_coords.py b/release/scripts/uvcalc_follow_active_coords.py index 79a445329cc..83df200991f 100644 --- a/release/scripts/uvcalc_follow_active_coords.py +++ b/release/scripts/uvcalc_follow_active_coords.py @@ -42,28 +42,15 @@ from Blender import * import bpy import BPyMesh -def extend(): - sce = bpy.data.scenes.active - ob = sce.objects.active - - # print ob, ob.type - if ob == None or ob.type != 'Mesh': - Draw.PupMenu('ERROR: No mesh object.') +def extend(EXTEND_MODE,ob): + if EXTEND_MODE == -1: return - - # Toggle Edit mode + me = ob.getData(mesh=1) + me_verts = me.verts + # Toggle Edit mode is_editmode = Window.EditMode() if is_editmode: Window.EditMode(0) - - me = ob.getData(mesh=1) - me_verts = me.verts - - # 0:normal extend, 1:edge length - EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0") - if EXTEND_MODE == -1: - return - Window.WaitCursor(1) t = sys.time() edge_average_lengths = {} @@ -153,8 +140,7 @@ def extend(): uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]]) if not me.faceUV: - Draw.PupMenu('ERROR: Mesh has no face UV coords.') - return + me.faceUV= True face_act = me.activeFace if face_act == -1: @@ -247,7 +233,22 @@ def extend(): Window.RedrawAll() Window.WaitCursor(0) -if __name__ == '__main__': - extend() + +def main(): + sce = bpy.data.scenes.active + ob = sce.objects.active - \ No newline at end of file + # print ob, ob.type + if ob == None or ob.type != 'Mesh': + Draw.PupMenu('ERROR: No mesh object.') + return + + + + # 0:normal extend, 1:edge length + EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0") + extend(EXTEND_MODE,ob) + +if __name__ == '__main__': + main() + diff --git a/release/scripts/uvcalc_quad_clickproj.py b/release/scripts/uvcalc_quad_clickproj.py index 0bba747e010..130a7e5af77 100644 --- a/release/scripts/uvcalc_quad_clickproj.py +++ b/release/scripts/uvcalc_quad_clickproj.py @@ -171,6 +171,9 @@ def main(): f_uv = f.uv return [(v.co-face_corner_main, f_uv[i]) for i,v in enumerate(f.v)] + if me.faceUV==False: + me.faceUV= True + coords = [ (co,uv) for f in me.faces if f.sel for co, uv in get_face_coords(f)] coords_orig = [uv.copy() for co, uv in coords] @@ -264,4 +267,5 @@ def main(): if __name__=='__main__': main() - Window.DrawProgressBar(1.0, '') \ No newline at end of file + Window.DrawProgressBar(1.0, '') + From d0b953d86079a00c71950603c80aff71dcca8362 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 12 Jan 2009 15:58:32 +0000 Subject: [PATCH 122/252] can now add sequencer effects with the python api also fixed crashes when incorrect args were used cross = 13; track= 5; frame = 1 # no effect constants scene.sequence.new((cross, seq1, seq2), frame, track) --- source/blender/python/api2_2x/sceneSequence.c | 186 ++++++++++++++++-- 1 file changed, 175 insertions(+), 11 deletions(-) diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index c7daea19fe7..be858b3020e 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -43,6 +43,7 @@ #include "BIF_editsound.h" // RFS: sound_open_hdaudio #include "BLI_blenlib.h" #include "BSE_sequence.h" +#include "BSE_seqeffects.h" #include "Ipo.h" #include "blendef.h" /* CLAMP */ #include "BKE_utildefines.h" @@ -116,12 +117,16 @@ static PyMethodDef BPy_SceneSeq_methods[] = { {NULL, NULL, 0, NULL} }; + /* use to add a sequence to a scene or its listbase */ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) { PyObject *py_data = NULL; Sequence *seq; + PyObject *pyob1= NULL, *pyob2= NULL, *pyob3= NULL; /* for effects */ + int type; + int a; Strip *strip; StripElem *se; @@ -130,17 +135,98 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) if( !PyArg_ParseTuple( args, "Oii", &py_data, &start, &machine ) ) return EXPP_ReturnPyObjError( PyExc_ValueError, "expect sequence data then 2 ints - (seqdata, start, track)" ); - + + if (machine < 1 || machine >= MAXSEQ) { + return EXPP_ReturnPyObjError( PyExc_ValueError, + "track out of range" ); + } + seq = alloc_sequence(seqbase, start, machine); /* warning, this sets last */ + + + if (PyArg_ParseTuple( py_data, "iO!|O!O!", &type, &Sequence_Type, &pyob1, &Sequence_Type, &pyob2, &Sequence_Type, &pyob3)) { - if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 2) { + struct SeqEffectHandle sh; + Sequence *seq1, *seq2= NULL, *seq3= NULL; /* for effects */ + + seq1= ((BPy_Sequence *)pyob1)->seq; + if(pyob2) seq2= ((BPy_Sequence *)pyob2)->seq; + if(pyob3) seq3= ((BPy_Sequence *)pyob3)->seq; + + if (type <= SEQ_EFFECT || type > SEQ_EFFECT_MAX || type==SEQ_PLUGIN){ + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "sequencer type out of range, expected a value from 9 to 29, plugins not supported"); + } + + + if (BLI_findindex(seqbase, seq1)==-1 || (seq2 && BLI_findindex(seqbase, seq2)==-1) || (seq3 && BLI_findindex(seqbase, seq3)==-1)) { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "one of the given effect sequences wasnt in accessible at the same level as the sequence being added"); + } + + if ((seq2 && seq2==seq1) || (seq3 && (seq3==seq1 || seq3==seq2))) { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "2 or more of the sequence arguments were the same"); + + } + + /* allocate and initialize */ + seq->type= type; + + sh = get_sequence_effect(seq); + + seq->seq1= seq1; + seq->seq2= seq2; + seq->seq3= seq3; + + sh.init(seq); + + if (!seq1) { + seq->len= 1; + seq->startstill= 25; + seq->endstill= 24; + } + + calc_sequence(seq); + + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strip->len= seq->len; + strip->us= 1; + if(seq->len>0) + strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + +#if 0 + /* initialize plugin */ + if(newseq->type == SEQ_PLUGIN) { + sh.init_plugin(seq, str); + + if(newseq->plugin==0) { + BLI_remlink(ed->seqbasep, seq); + free_sequence(seq); + return 0; + } + } +#endif + + update_changed_seq_and_deps(seq, 1, 1); + + } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 2) { /* Image */ PyObject *list; char *name; if (!PyArg_ParseTuple( py_data, "sO!", &name, &PyList_Type, &list)) { BLI_remlink(seqbase, seq); - MEM_freeN(seq); + free_sequence(seq); return EXPP_ReturnPyObjError( PyExc_ValueError, "images data needs to be a tuple of a string and a list of images - (path, [filenames...])" ); @@ -165,14 +251,15 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 3) { float r,g,b; SolidColorVars *colvars; - seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor"); - colvars = (SolidColorVars *)seq->effectdata; - + if (!PyArg_ParseTuple( py_data, "fff", &r, &g, &b)) { + BLI_remlink(seqbase, seq); + free_sequence(seq); return EXPP_ReturnPyObjError( PyExc_ValueError, "color needs to be a tuple of 3 floats - (r,g,b)" ); } - + + seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor"); seq->type= SEQ_COLOR; CLAMP(r,0,1); @@ -199,7 +286,7 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) if (!PyArg_ParseTuple( py_data, "ssss", &filename, &dir, &fullpath, &type )) { BLI_remlink(seqbase, seq); - MEM_freeN(seq); + free_sequence(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)" ); @@ -215,7 +302,7 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) struct anim * an = openanim(fullpath, IB_rect); if(an==0) { BLI_remlink(seqbase, seq); - MEM_freeN(seq); + free_sequence(seq); return EXPP_ReturnPyObjError( PyExc_ValueError, "invalid movie strip" ); @@ -254,7 +341,7 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) hdaudio = sound_open_hdaudio( fullpath ); if(hdaudio==0) { BLI_remlink(seqbase, seq); - MEM_freeN(seq); + free_sequence(seq); return EXPP_ReturnPyObjError( PyExc_ValueError, fullpath ); @@ -949,6 +1036,72 @@ static int setFlagAttr( BPy_Sequence *self, PyObject *value, void *type ) return 0; } +static PyObject *getEffectSeq( BPy_Sequence *self, void *type ) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= NULL; + switch(t) { + case 1: + seq= self->seq->seq1; + break; + case 2: + seq= self->seq->seq2; + break; + case 3: + seq= self->seq->seq3; + break; + } + + if (seq) { + return Sequence_CreatePyObject(seq, NULL, self->scene); + } else { + Py_RETURN_NONE; + } +} + + +/* + * set one of the effect sequences + */ + +static int setEffectSeq( BPy_Sequence *self, PyObject *value, void *type ) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence **seq; + if ((value==Py_None || BPy_Sequence_Check(value))==0) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected Sequence or None" ); + + switch(t) { + case 1: + seq= &self->seq->seq1; + break; + case 2: + seq= &self->seq->seq2; + break; + case 3: + seq= &self->seq->seq3; + break; + } + + if (value==Py_None) + *seq= NULL; + else { + Sequence *newseq= ((BPy_Sequence *)value)->seq; + if (newseq==self->seq) { + return EXPP_ReturnIntError( PyExc_TypeError, "cannot set a sequence as its own effect" ); + } + + *seq= ((BPy_Sequence *)value)->seq; + } + + + calc_sequence(self->seq); + update_changed_seq_and_deps(self->seq, 1, 1); + + return 0; +} + /*****************************************************************************/ /* Python attributes get/set structure: */ @@ -1070,7 +1223,18 @@ static PyGetSetDef BPy_Sequence_getseters[] = { (getter)getFlagAttr, (setter)setFlagAttr, "", (void *)SEQ_IPO_FRAME_LOCKED}, - + {"seq1", + (getter)getEffectSeq, (setter)setEffectSeq, + "", + (void *)1}, + {"seq2", + (getter)getEffectSeq, (setter)setEffectSeq, + "", + (void *)2}, + {"seq3", + (getter)getEffectSeq, (setter)setEffectSeq, + "", + (void *)3}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; From 0066b6a8aad2d054574c93a507a98f92692ad924 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 13 Jan 2009 05:55:48 +0000 Subject: [PATCH 123/252] fix for big in yesterdays commit, color values were not initialized --- source/blender/python/api2_2x/sceneSequence.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index be858b3020e..5be3a1479a6 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -144,11 +144,20 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) seq = alloc_sequence(seqbase, start, machine); /* warning, this sets last */ - if (PyArg_ParseTuple( py_data, "iO!|O!O!", &type, &Sequence_Type, &pyob1, &Sequence_Type, &pyob2, &Sequence_Type, &pyob3)) { + if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) >= 2 && BPy_Sequence_Check(PyTuple_GET_ITEM(py_data, 1))) { struct SeqEffectHandle sh; Sequence *seq1, *seq2= NULL, *seq3= NULL; /* for effects */ + if (!PyArg_ParseTuple( py_data, "iO!|O!O!", &type, &Sequence_Type, &pyob1, &Sequence_Type, &pyob2, &Sequence_Type, &pyob3)) { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "effect stripts expected an effect type int and 1 to 3 sequence strips"); + } + + seq1= ((BPy_Sequence *)pyob1)->seq; if(pyob2) seq2= ((BPy_Sequence *)pyob2)->seq; if(pyob3) seq3= ((BPy_Sequence *)pyob3)->seq; @@ -260,6 +269,8 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) } seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor"); + colvars= (SolidColorVars *)seq->effectdata; + seq->type= SEQ_COLOR; CLAMP(r,0,1); From b71bc3a2f31234583a78cbd0ee06ba084f158ed7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 13 Jan 2009 15:48:27 +0000 Subject: [PATCH 124/252] patch from Thomas Dinges, update URLs in help scripts --- release/scripts/help_bpy_api.py | 8 ++++---- release/scripts/help_getting_started.py | 9 ++++----- release/scripts/help_manual.py | 13 ++++++------- release/scripts/help_release_notes.py | 14 +++++++------- release/scripts/help_tutorials.py | 11 +++++------ release/scripts/help_web_blender.py | 8 ++++---- release/scripts/help_web_devcomm.py | 10 +++++----- release/scripts/help_web_eshop.py | 6 +++--- release/scripts/help_web_usercomm.py | 8 ++++---- 9 files changed, 42 insertions(+), 45 deletions(-) diff --git a/release/scripts/help_bpy_api.py b/release/scripts/help_bpy_api.py index 484663b32b3..9c3a24af288 100644 --- a/release/scripts/help_bpy_api.py +++ b/release/scripts/help_bpy_api.py @@ -1,17 +1,17 @@ #!BPY """ Name: 'Blender/Python Scripting API' -Blender: 244 +Blender: 248 Group: 'Help' Tooltip: 'The Blender Python API reference manual' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartist") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ This script opens the user's default web browser at http://www.blender.org's -"Blenders Python API" page. +"Blender Python API Reference" page. """ # -------------------------------------------------------------------------- @@ -38,4 +38,4 @@ This script opens the user's default web browser at http://www.blender.org's import Blender, webbrowser version = str(int(Blender.Get('version'))) -webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/index.html') +webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/') diff --git a/release/scripts/help_getting_started.py b/release/scripts/help_getting_started.py index 81b002da4e4..a4f6da5cc55 100644 --- a/release/scripts/help_getting_started.py +++ b/release/scripts/help_getting_started.py @@ -1,16 +1,16 @@ #!BPY """ Name: 'Getting Started' -Blender: 234 +Blender: 248 Group: 'Help' Tooltip: 'Help for new users' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's +This script opens the user's default web browser at www.blender.org's "Getting Started" page. """ @@ -39,5 +39,4 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import Blender, webbrowser -version = str(Blender.Get('version')) -webbrowser.open('http://www.blender3d.org/Help/?pg=GettingStarted&ver=' + version) +webbrowser.open('http://www.blender.org/education-help/tutorials/getting-started/') diff --git a/release/scripts/help_manual.py b/release/scripts/help_manual.py index cf293bf7c2c..b830975e593 100644 --- a/release/scripts/help_manual.py +++ b/release/scripts/help_manual.py @@ -1,17 +1,17 @@ #!BPY """ Name: 'Manual' -Blender: 234 +Blender: 248 Group: 'Help' -Tooltip: 'The Blender reference manual' +Tooltip: 'The Blender Wiki manual' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's -"Blender Manual" page. +This script opens the user's default web browser at www.blender.org's +"Manual" page. """ # -------------------------------------------------------------------------- @@ -37,5 +37,4 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import Blender, webbrowser -version = str(Blender.Get('version')) -webbrowser.open('http://www.blender3d.org/Help/?pg=Manual&ver=' + version) +webbrowser.open('http://wiki.blender.org/index.php/Manual') diff --git a/release/scripts/help_release_notes.py b/release/scripts/help_release_notes.py index af7a7042489..919ec72da3c 100644 --- a/release/scripts/help_release_notes.py +++ b/release/scripts/help_release_notes.py @@ -1,17 +1,17 @@ #!BPY """ -Name: 'Release Notes' -Blender: 234 +Name: 'Release Logs' +Blender: 248 Group: 'Help' Tooltip: 'Information about the changes in this version of Blender' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's -"Release Notes" page. +This script opens the user's default web browser at www.blender.org's +"Release Logs" page. """ # -------------------------------------------------------------------------- @@ -37,5 +37,5 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import Blender, webbrowser -version = str(Blender.Get('version')) -webbrowser.open('http://www.blender3d.org/Help/?pg=ReleaseNotes&ver=' + version) + +webbrowser.open('http://www.blender.org/development/release-logs/') diff --git a/release/scripts/help_tutorials.py b/release/scripts/help_tutorials.py index 04d6c799455..1fe466560f0 100644 --- a/release/scripts/help_tutorials.py +++ b/release/scripts/help_tutorials.py @@ -2,17 +2,17 @@ """ Name: 'Tutorials' -Blender: 234 +Blender: 248 Group: 'Help' Tooltip: 'Tutorials for learning to use Blender' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's -"Blender Tutorials" page. +This script opens the user's default web browser at www.blender.org's +"Tutorials" page. """ # -------------------------------------------------------------------------- @@ -38,5 +38,4 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import Blender, webbrowser -version = str(Blender.Get('version')) -webbrowser.open('http://www.blender3d.org/Help/?pg=Tutorials&ver=' + version) +webbrowser.open('http://www.blender.org/education-help/tutorials/') diff --git a/release/scripts/help_web_blender.py b/release/scripts/help_web_blender.py index 0f9e32dea0e..db0a78d90f7 100644 --- a/release/scripts/help_web_blender.py +++ b/release/scripts/help_web_blender.py @@ -2,17 +2,17 @@ """ Name: 'Blender Website' -Blender: 234 +Blender: 248 Group: 'HelpWebsites' Tooltip: 'The official Blender website' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ This script opens the user's default web browser at Blender's main site, -www.blender3d.org. +www.blender.org. """ @@ -39,4 +39,4 @@ www.blender3d.org. # -------------------------------------------------------------------------- import Blender, webbrowser -webbrowser.open('http://www.blender3d.org/') +webbrowser.open('http://www.blender.org/') diff --git a/release/scripts/help_web_devcomm.py b/release/scripts/help_web_devcomm.py index 344622cc113..e04a54501f7 100644 --- a/release/scripts/help_web_devcomm.py +++ b/release/scripts/help_web_devcomm.py @@ -2,17 +2,17 @@ """ Name: 'Developer Community' -Blender: 234 +Blender: 248 Group: 'HelpWebsites' Tooltip: 'Get involved with Blender development' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender.org, the -Blender development portal. +This script opens the user's default web browser at www.blender.org's +"Get Involved" page. """ # -------------------------------------------------------------------------- @@ -38,4 +38,4 @@ Blender development portal. # -------------------------------------------------------------------------- import webbrowser -webbrowser.open('http://www.blender.org') +webbrowser.open('http://www.blender.org/community/get-involved/') diff --git a/release/scripts/help_web_eshop.py b/release/scripts/help_web_eshop.py index 451fd735150..c33849ac419 100644 --- a/release/scripts/help_web_eshop.py +++ b/release/scripts/help_web_eshop.py @@ -2,16 +2,16 @@ """ Name: 'Blender E-Shop' -Blender: 234 +Blender: 248 Group: 'HelpWebsites' Tooltip: 'Buy official Blender resources and merchandise online' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's +This script opens the user's default web browser at www.blender.org's "E-Shop" section. """ diff --git a/release/scripts/help_web_usercomm.py b/release/scripts/help_web_usercomm.py index fbe19956eb7..a77a2bb9fef 100644 --- a/release/scripts/help_web_usercomm.py +++ b/release/scripts/help_web_usercomm.py @@ -2,16 +2,16 @@ """ Name: 'User Community' -Blender: 234 +Blender: 248 Group: 'HelpWebsites' Tooltip: 'Get involved with other Blender users' """ __author__ = "Matt Ebb" __url__ = ("blender", "blenderartists.org") -__version__ = "1.0" +__version__ = "1.0.1" __bpydoc__ = """\ -This script opens the user's default web browser at www.blender3d.org's +This script opens the user's default web browser at www.blender.org's "User Community" page. """ @@ -38,4 +38,4 @@ This script opens the user's default web browser at www.blender3d.org's # -------------------------------------------------------------------------- import webbrowser -webbrowser.open('http://www.blender3d.org/Community') +webbrowser.open('http://www.blender.org/community/user-community/') From 7f5073729f5fafe4118edb18ac10abbab66bf0c7 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 13 Jan 2009 22:21:04 +0000 Subject: [PATCH 125/252] Bullet bug fix: bad pointer in btCompoundShape::addChildShape() - patch submited to Bullet forum. This bug fix is needed in preparation of the setparent coumpound shape patch. --- .../src/BulletCollision/CollisionShapes/btCompoundShape.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index f08b810eadb..997361a5069 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -49,8 +49,6 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio child.m_childShapeType = shape->getShapeType(); child.m_childMargin = shape->getMargin(); - m_children.push_back(child); - //extend the local aabbMin/aabbMax btVector3 localAabbMin,localAabbMax; shape->getAabb(localTransform,localAabbMin,localAabbMax); @@ -69,10 +67,11 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio if (m_dynamicAabbTree) { const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); - int index = m_children.size()-1; + int index = m_children.size(); child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); } + m_children.push_back(child); } void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) From 00c12e09066c551e3ae8ee6da3cb85fb3bcf90f8 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 13 Jan 2009 22:59:18 +0000 Subject: [PATCH 126/252] BGE patch: dynamically update the coumpound parent shape when parenting to a compound object. This patch modifies the way the setParent actuator and KX_GameObject::setParent() function works when parenting to a compound object: the collision shape of the object being parented is dynamically added to the coumpound shape. Similarly, unparenting an object from a compound object will cause the child collision shape to be dynamically removed from the parent shape provided that is was previously added with setParent. Note: * This also works if the object is parented to a child of a compound object: the collision shape is added to the compound shape of the top parent. * The collision shape is added with the transformation (position, scale and orientation) it had at the time of the parenting. * The child shape is rigidly attached to the compound shape, the transformation is not affected by any further change in position/scale/orientation of the child object. * While the child shape is added to the compound shape, the child object is removed from the dynamic world to avoid superposition of shapes (one for the object itself and one for the compound child shape). This means that collision sensors on the child object are disabled while the child object is parent to a compound object. * There is no difference when setParent is used on a non-compound object: the child object is automatically changed to a static ghost object to avoid bad interaction with the parent shape; collision sensors on the child object continue to be active while the object is parented. * The child shape dynamically added to a compound shape modifies the inertia of the compound object but not the mass. It participates to collision detection as any other "static" child shape. --- .../Ketsji/KX_BulletPhysicsController.cpp | 135 +++++++++++++++++- .../Ketsji/KX_BulletPhysicsController.h | 5 +- .../Ketsji/KX_ConvertPhysicsObjects.cpp | 2 +- source/gameengine/Ketsji/KX_GameObject.cpp | 23 +++ .../Ketsji/KX_IPhysicsController.cpp | 3 +- .../gameengine/Ketsji/KX_IPhysicsController.h | 10 +- .../Ketsji/KX_OdePhysicsController.cpp | 2 +- .../Ketsji/KX_OdePhysicsController.h | 2 + .../Ketsji/KX_SumoPhysicsController.h | 5 +- .../Physics/Bullet/CcdPhysicsController.cpp | 22 ++- .../Physics/Bullet/CcdPhysicsController.h | 44 +++++- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 14 +- .../Physics/Bullet/CcdPhysicsEnvironment.h | 2 + .../Physics/common/PHY_DynamicTypes.h | 3 +- 14 files changed, 257 insertions(+), 15 deletions(-) diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 3a20bbfbb11..a67f4a54b3f 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -17,10 +17,11 @@ #include "BulletSoftBody/btSoftBody.h" -KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna) -: KX_IPhysicsController(dyna,(PHY_IPhysicsController*)this), +KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool compound) +: KX_IPhysicsController(dyna,compound,(PHY_IPhysicsController*)this), CcdPhysicsController(ci), -m_savedCollisionFlags(0) +m_savedCollisionFlags(0), +m_bulletChildShape(NULL) { } @@ -175,6 +176,133 @@ void KX_BulletPhysicsController::setRigidBody(bool rigid) { } +/* This function dynamically adds the collision shape of another controller to + the current controller shape provided it is a compound shape. + The idea is that dynamic parenting on a compound object will dynamically extend the shape +*/ +void KX_BulletPhysicsController::AddCompoundChild(KX_IPhysicsController* child) +{ + if (child == NULL || !IsCompound()) + return; + // other controller must be a bullet controller too + // verify that body and shape exist and match + KX_BulletPhysicsController* childCtrl = dynamic_cast(child); + btRigidBody* rootBody = GetRigidBody(); + btRigidBody* childBody = childCtrl->GetRigidBody(); + if (!rootBody || !childBody) + return; + const btCollisionShape* rootShape = rootBody->getCollisionShape(); + const btCollisionShape* childShape = childBody->getCollisionShape(); + if (!rootShape || + !childShape || + rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE || + childShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + return; + btCompoundShape* compoundShape = (btCompoundShape*)rootShape; + // compute relative transformation between parent and child + btTransform rootTrans; + btTransform childTrans; + rootBody->getMotionState()->getWorldTransform(rootTrans); + childBody->getMotionState()->getWorldTransform(childTrans); + btVector3 rootScale = rootShape->getLocalScaling(); + rootScale[0] = 1.0/rootScale[0]; + rootScale[1] = 1.0/rootScale[1]; + rootScale[2] = 1.0/rootScale[2]; + // relative scale = child_scale/parent_scale + btVector3 relativeScale = childShape->getLocalScaling()*rootScale; + btMatrix3x3 rootRotInverse = rootTrans.getBasis().transpose(); + // relative pos = parent_rot^-1 * ((parent_pos-child_pos)/parent_scale) + btVector3 relativePos = rootRotInverse*((childTrans.getOrigin()-rootTrans.getOrigin())*rootScale); + // relative rot = parent_rot^-1 * child_rot + btMatrix3x3 relativeRot = rootRotInverse*childTrans.getBasis(); + // create a proxy shape info to store the transformation + CcdShapeConstructionInfo* proxyShapeInfo = new CcdShapeConstructionInfo(); + // store the transformation to this object shapeinfo + proxyShapeInfo->m_childTrans.setOrigin(relativePos); + proxyShapeInfo->m_childTrans.setBasis(relativeRot); + proxyShapeInfo->m_childScale.setValue(relativeScale[0], relativeScale[1], relativeScale[2]); + // we will need this to make sure that we remove the right proxy later when unparenting + proxyShapeInfo->m_userData = childCtrl; + proxyShapeInfo->SetProxy(childCtrl->GetShapeInfo()->AddRef()); + // add to parent compound shapeinfo + GetShapeInfo()->AddShape(proxyShapeInfo); + // create new bullet collision shape from the object shapeinfo and set scaling + btCollisionShape* newChildShape = proxyShapeInfo->CreateBulletShape(); + newChildShape->setLocalScaling(relativeScale); + // add bullet collision shape to parent compound collision shape + compoundShape->addChildShape(proxyShapeInfo->m_childTrans,newChildShape); + // remember we created this shape + childCtrl->m_bulletChildShape = newChildShape; + // recompute inertia of parent + if (!rootBody->isStaticOrKinematicObject()) + { + btVector3 localInertia; + float mass = 1.f/rootBody->getInvMass(); + compoundShape->calculateLocalInertia(mass,localInertia); + rootBody->setMassProps(mass,localInertia); + } + // must update the broadphase cache, + GetPhysicsEnvironment()->refreshCcdPhysicsController(this); + // remove the children + GetPhysicsEnvironment()->disableCcdPhysicsController(childCtrl); +} + +/* Reverse function of the above, it will remove a shape from a compound shape + provided that the former was added to the later using AddCompoundChild() +*/ +void KX_BulletPhysicsController::RemoveCompoundChild(KX_IPhysicsController* child) +{ + if (child == NULL || !IsCompound()) + return; + // other controller must be a bullet controller too + // verify that body and shape exist and match + KX_BulletPhysicsController* childCtrl = dynamic_cast(child); + btRigidBody* rootBody = GetRigidBody(); + btRigidBody* childBody = childCtrl->GetRigidBody(); + if (!rootBody || !childBody) + return; + const btCollisionShape* rootShape = rootBody->getCollisionShape(); + if (!rootShape || + rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE) + return; + btCompoundShape* compoundShape = (btCompoundShape*)rootShape; + // retrieve the shapeInfo + CcdShapeConstructionInfo* childShapeInfo = childCtrl->GetShapeInfo(); + CcdShapeConstructionInfo* rootShapeInfo = GetShapeInfo(); + // and verify that the child is part of the parent + int i = rootShapeInfo->FindChildShape(childShapeInfo, childCtrl); + if (i < 0) + return; + rootShapeInfo->RemoveChildShape(i); + if (childCtrl->m_bulletChildShape) + { + int numChildren = compoundShape->getNumChildShapes(); + for (i=0; igetChildShape(i) == childCtrl->m_bulletChildShape) + { + compoundShape->removeChildShapeByIndex(i); + compoundShape->recalculateLocalAabb(); + break; + } + } + delete childCtrl->m_bulletChildShape; + childCtrl->m_bulletChildShape = NULL; + } + // recompute inertia of parent + if (!rootBody->isStaticOrKinematicObject()) + { + btVector3 localInertia; + float mass = 1.f/rootBody->getInvMass(); + compoundShape->calculateLocalInertia(mass,localInertia); + rootBody->setMassProps(mass,localInertia); + } + // must update the broadphase cache, + GetPhysicsEnvironment()->refreshCcdPhysicsController(this); + // reactivate the children + GetPhysicsEnvironment()->enableCcdPhysicsController(childCtrl); +} + void KX_BulletPhysicsController::SuspendDynamics(bool ghost) { btRigidBody *body = GetRigidBody(); @@ -251,6 +379,7 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode) physicsreplica->setParentCtrl(ccdParent); physicsreplica->PostProcessReplica(motionstate,parentctrl); physicsreplica->m_userdata = (PHY_IPhysicsController*)physicsreplica; + physicsreplica->m_bulletChildShape = NULL; return physicsreplica; } diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index d5fca4ec6d3..a50af2699bf 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -13,10 +13,11 @@ private: short int m_savedCollisionFilterGroup; short int m_savedCollisionFilterMask; MT_Scalar m_savedMass; + btCollisionShape* m_bulletChildShape; public: - KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna); + KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool compound); virtual ~KX_BulletPhysicsController (); /////////////////////////////////// @@ -42,6 +43,8 @@ public: virtual MT_Scalar GetMass(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); + virtual void AddCompoundChild(KX_IPhysicsController* child); + virtual void RemoveCompoundChild(KX_IPhysicsController* child); virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 0e7a6d92ec1..46e46b014b5 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -1084,7 +1084,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_bSoft = objprop->m_softbody; MT_Vector3 scaling = gameobj->NodeGetWorldScaling(); ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]); - KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna); + KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna,objprop->m_hasCompoundChildren); // shapeInfo is reference counted, decrement now as we don't use it anymore if (shapeInfo) shapeInfo->Release(); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index f2a554c6b2a..706b80a1fab 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -252,6 +252,20 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) if (rootlist->RemoveValue(this)) // the object was in parent list, decrement ref count as it's now removed Release(); + // if the new parent is a compound object, add this object shape to the compound shape. + // step 0: verify this object has physical controller + if (m_pPhysicsController1) + { + // step 1: find the top parent (not necessarily obj) + KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject(); + // step 2: verify it has a physical controller and compound shape + if (rootobj != NULL && + rootobj->m_pPhysicsController1 != NULL && + rootobj->m_pPhysicsController1->IsCompound()) + { + rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1); + } + } } } @@ -260,6 +274,8 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) // check on valid node in case a python controller holds a reference to a deleted object if (GetSGNode() && GetSGNode()->GetSGParent()) { + // get the root object to remove us from compound object if needed + KX_GameObject* rootobj = (KX_GameObject*)GetSGNode()->GetRootSGParent()->GetSGClientObject(); // Set us to the right spot GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling()); GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation()); @@ -275,6 +291,13 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) rootlist->Add(AddRef()); if (m_pPhysicsController1) { + // in case this controller was added as a child shape to the parent + if (rootobj != NULL && + rootobj->m_pPhysicsController1 != NULL && + rootobj->m_pPhysicsController1->IsCompound()) + { + rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1); + } m_pPhysicsController1->RestoreDynamics(); } } diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.cpp b/source/gameengine/Ketsji/KX_IPhysicsController.cpp index 5cd66efd965..a38222c5f7e 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_IPhysicsController.cpp @@ -35,9 +35,10 @@ #include "PHY_DynamicTypes.h" -KX_IPhysicsController::KX_IPhysicsController(bool dyna,void* userdata) +KX_IPhysicsController::KX_IPhysicsController(bool dyna, bool compound, void* userdata) : m_bDyna(dyna), + m_bCompound(compound), m_suspendDynamics(false), m_userdata(userdata) { diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index 4ea283e9f98..fed71735bec 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -32,6 +32,7 @@ #include "SG_Controller.h" #include "MT_Vector3.h" #include "MT_Point3.h" +#include "MT_Transform.h" #include "MT_Matrix3x3.h" struct KX_ClientObjectInfo; @@ -48,10 +49,11 @@ class KX_IPhysicsController : public SG_Controller { protected: bool m_bDyna; + bool m_bCompound; bool m_suspendDynamics; void* m_userdata; public: - KX_IPhysicsController(bool dyna,void* userdata); + KX_IPhysicsController(bool dyna,bool compound, void* userdata); virtual ~KX_IPhysicsController(); @@ -78,6 +80,8 @@ public: virtual MT_Scalar GetMass()=0; virtual MT_Vector3 getReactionForce()=0; virtual void setRigidBody(bool rigid)=0; + virtual void AddCompoundChild(KX_IPhysicsController* child) = 0; + virtual void RemoveCompoundChild(KX_IPhysicsController* child) = 0; virtual void SuspendDynamics(bool ghost=false)=0; virtual void RestoreDynamics()=0; @@ -92,6 +96,10 @@ public: return m_bDyna; } + bool IsCompound(void) { + return m_bCompound; + } + virtual MT_Scalar GetRadius()=0; virtual void SetSumoTransform(bool nondynaonly)=0; // todo: remove next line ! diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp index 6a701a5f25b..dc6990267d4 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp @@ -50,7 +50,7 @@ KX_OdePhysicsController::KX_OdePhysicsController( float extends[3], float radius ) -: KX_IPhysicsController(dyna,(PHY_IPhysicsController*)this), +: KX_IPhysicsController(dyna,false,(PHY_IPhysicsController*)this), ODEPhysicsController( dyna,fullRigidBody,phantom,motionstate, space,world,mass,friction,restitution, diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h index 53050f6ce3e..e3b5336c0b5 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.h +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h @@ -73,6 +73,8 @@ public: virtual MT_Scalar GetMass(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); + virtual void AddCompoundChild(KX_IPhysicsController* child) { } + virtual void RemoveCompoundChild(KX_IPhysicsController* child) { } virtual void SuspendDynamics(bool); virtual void RestoreDynamics(); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h index abe48d99043..a684b637894 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h @@ -53,7 +53,7 @@ public: class SM_Object* sumoObj, class PHY_IMotionState* motionstate ,bool dyna) - : KX_IPhysicsController(dyna,NULL) , + : KX_IPhysicsController(dyna,false,NULL) , SumoPhysicsController(sumoScene,/*solidscene,*/sumoObj,motionstate,dyna) { }; @@ -78,6 +78,9 @@ public: void SuspendDynamics(bool); void RestoreDynamics(); + virtual void AddCompoundChild(KX_IPhysicsController* child) { } + virtual void RemoveCompoundChild(KX_IPhysicsController* child) { } + virtual void getOrientation(MT_Quaternion& orn); virtual void setOrientation(const MT_Matrix3x3& orn); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index c9c30c1b450..fafce5cf5cc 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1276,7 +1276,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo // assume no shape information // no support for dynamic change of shape yet - assert(m_meshObject == NULL); + assert(IsUnused()); m_shapeType = PHY_SHAPE_NONE; m_vertexArray.clear(); m_polygonIndexArray.clear(); @@ -1398,6 +1398,17 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo return true; } +bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo) +{ + if (shapeInfo == NULL) + return false; + // no support for dynamic change + assert(IsUnused()); + m_shapeType = PHY_SHAPE_PROXY; + m_shapeProxy = shapeInfo; + return true; +} + btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() { btCollisionShape* collisionShape = 0; @@ -1406,9 +1417,12 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() btCompoundShape* compoundShape = 0; CcdShapeConstructionInfo* nextShapeInfo; + if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL) + return m_shapeProxy->CreateBulletShape(); + switch (m_shapeType) { - case PHY_SHAPE_NONE: + default: break; case PHY_SHAPE_BOX: @@ -1522,6 +1536,10 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() m_meshShapeMap.erase(mit); } } + if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL) + { + m_shapeProxy->Release(); + } } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 054ec91122a..c771aa2624b 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -67,11 +67,13 @@ public: m_height(1.0), m_halfExtend(0.f,0.f,0.f), m_childScale(1.0f,1.0f,1.0f), + m_userData(NULL), m_refCount(1), m_meshObject(NULL), m_unscaledShape(NULL), m_useGimpact(false), - m_weldingThreshold(0.f) + m_weldingThreshold(0.f), + m_shapeProxy(NULL) { m_childTrans.setIdentity(); } @@ -92,6 +94,11 @@ public: return 0; } + bool IsUnused(void) + { + return (m_meshObject==NULL && m_shapeArray.size() == 0 && m_shapeProxy == NULL); + } + void AddShape(CcdShapeConstructionInfo* shapeInfo); btTriangleMeshShape* GetMeshShape(void) @@ -105,6 +112,32 @@ public: return m_shapeArray.at(i); } + int FindChildShape(CcdShapeConstructionInfo* shapeInfo, void* userData) + { + if (shapeInfo == NULL) + return -1; + for (int i=0; im_userData) && + (childInfo == shapeInfo || + (childInfo->m_shapeType == PHY_SHAPE_PROXY && + childInfo->m_shapeProxy == shapeInfo))) + return i; + } + return -1; + } + + bool RemoveChildShape(int i) + { + if (i < 0 || i >= m_shapeArray.size()) + return false; + m_shapeArray.at(i)->Release(); + if (i < m_shapeArray.size()-1) + m_shapeArray[i] = m_shapeArray.back(); + m_shapeArray.pop_back(); + return true; + } bool SetMesh(RAS_MeshObject* mesh, bool polytope,bool useGimpact); RAS_MeshObject* GetMesh(void) @@ -112,6 +145,12 @@ public: return m_meshObject; } + bool SetProxy(CcdShapeConstructionInfo* shapeInfo); + CcdShapeConstructionInfo* GetProxy(void) + { + return m_shapeProxy; + } + btCollisionShape* CreateBulletShape(); // member variables @@ -121,6 +160,7 @@ public: btVector3 m_halfExtend; btTransform m_childTrans; btVector3 m_childScale; + void* m_userData; 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 @@ -146,7 +186,7 @@ protected: std::vector m_shapeArray; // for compound shapes bool m_useGimpact; //use gimpact for concave dynamic/moving collision detection float m_weldingThreshold; //welding closeby vertices together can improve softbody stability etc. - + CcdShapeConstructionInfo* m_shapeProxy; // only used for PHY_SHAPE_PROXY, pointer to actual shape info }; struct CcdConstructionInfo diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 4fe35630784..d2274c1e8d6 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -536,12 +536,24 @@ void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ct { } else { - m_dynamicsWorld->removeCollisionObject(body); + m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject()); } } } } +void CcdPhysicsEnvironment::refreshCcdPhysicsController(CcdPhysicsController* ctrl) +{ + btCollisionObject* obj = ctrl->GetCollisionObject(); + if (obj) + { + btBroadphaseProxy* proxy = obj->getBroadphaseHandle(); + if (proxy) + { + m_dynamicsWorld->getPairCache()->cleanProxyFromPairs(proxy,m_dynamicsWorld->getDispatcher()); + } + } +} void CcdPhysicsEnvironment::beginFrame() { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 74384dd8cf2..4b28d3fddfc 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -196,6 +196,8 @@ protected: void enableCcdPhysicsController(CcdPhysicsController* ctrl); + void refreshCcdPhysicsController(CcdPhysicsController* ctrl); + btBroadphaseInterface* getBroadphase(); btDispatcher* getDispatcher(); diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h index 3b3e42c38d2..09126264dcc 100644 --- a/source/gameengine/Physics/common/PHY_DynamicTypes.h +++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h @@ -95,7 +95,8 @@ typedef enum PHY_ShapeType { PHY_SHAPE_CONE, PHY_SHAPE_MESH, PHY_SHAPE_POLYTOPE, - PHY_SHAPE_COMPOUND + PHY_SHAPE_COMPOUND, + PHY_SHAPE_PROXY } PHY_ShapeType; From 509ca83ef1d10fab4903981714cfab3719280e04 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 14 Jan 2009 22:33:39 +0000 Subject: [PATCH 127/252] BGE patch 18065: gameobj mass writeable + setmass actuator. This patch allows to change the mass of a dynamic or rigid body object during the game. Two methods are available: in a Python script by setting the mass attribute of the game object; by logic brick with the Edit Object->Dynamics->Set Mass actuator. The mass can only be set on dynamic objects and must be a positive floating point value. --- source/blender/makesdna/DNA_actuator_types.h | 2 +- source/blender/src/buttons_logic.c | 9 ++++++-- .../Converter/KX_ConvertActuators.cpp | 3 ++- .../Ketsji/KX_BulletPhysicsController.cpp | 21 ++++++++++++++++++- .../Ketsji/KX_BulletPhysicsController.h | 1 + source/gameengine/Ketsji/KX_GameObject.cpp | 11 +++++----- .../gameengine/Ketsji/KX_IPhysicsController.h | 1 + .../Ketsji/KX_SCA_DynamicActuator.cpp | 7 ++++++- .../Ketsji/KX_SCA_DynamicActuator.h | 2 ++ .../Ketsji/KX_SumoPhysicsController.cpp | 4 ++++ .../Ketsji/KX_SumoPhysicsController.h | 1 + .../Physics/Bullet/CcdPhysicsController.cpp | 4 ++-- 12 files changed, 53 insertions(+), 13 deletions(-) diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 43dada97d0e..48432b8c6e2 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -82,7 +82,7 @@ typedef struct bEditObjectActuator { char name[32]; float linVelocity[3]; /* initial lin. velocity on creation */ float angVelocity[3]; /* initial ang. velocity on creation */ - float pad; + float mass; short localflag; /* flag for the lin & ang. vel: apply locally */ short dyn_operation; } bEditObjectActuator; diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 8aca111f41f..494dc05d8f9 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2136,12 +2136,17 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefButS(block, TOG, 0, "3D", xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking"); } else if(eoa->type==ACT_EDOB_DYNAMICS) { - ysize= 48; + ysize= 69; glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3"; + str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3|Set Mass %x4"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-44, (width-80), 19, &(eoa->dyn_operation), 0.0, 0.0, 0, 0, ""); + if(eoa->dyn_operation==4) { + uiDefButF(block, NUM, 0, "", xco+40, yco-63, width-80, 19, + &eoa->mass, 0.0, 10000.0, 10, 0, + "Mass for object."); + } } str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3|Dynamics %x4"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, ""); diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 4f152acc918..3a6122e6608 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -661,7 +661,8 @@ void BL_ConvertActuators(char* maggiename, { KX_SCA_DynamicActuator* tmpdynact = new KX_SCA_DynamicActuator(gameobj, - editobact->dyn_operation + editobact->dyn_operation, + editobact->mass ); baseact = tmpdynact; } diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index a67f4a54b3f..534c48661b7 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -303,6 +303,25 @@ void KX_BulletPhysicsController::RemoveCompoundChild(KX_IPhysicsController* c GetPhysicsEnvironment()->enableCcdPhysicsController(childCtrl); } +void KX_BulletPhysicsController::SetMass(MT_Scalar newmass) +{ + btRigidBody *body = GetRigidBody(); + if (body && body->getActivationState() != DISABLE_SIMULATION && + newmass>MT_EPSILON && GetMass()>MT_EPSILON) + { + btVector3 grav = body->getGravity(); + btVector3 accel = grav / GetMass(); + + btBroadphaseProxy* handle = body->getBroadphaseHandle(); + GetPhysicsEnvironment()->updateCcdPhysicsController(this, + newmass, + body->getCollisionFlags(), + handle->m_collisionFilterGroup, + handle->m_collisionFilterMask); + body->setGravity(accel); + } +} + void KX_BulletPhysicsController::SuspendDynamics(bool ghost) { btRigidBody *body = GetRigidBody(); @@ -333,7 +352,7 @@ void KX_BulletPhysicsController::RestoreDynamics() m_savedCollisionFlags, m_savedCollisionFilterGroup, m_savedCollisionFilterMask); - GetRigidBody()->forceActivationState(m_savedActivationState); + body->forceActivationState(m_savedActivationState); } } diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index a50af2699bf..44fbde7054e 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -41,6 +41,7 @@ public: virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); virtual MT_Scalar GetMass(); + virtual void SetMass(MT_Scalar newmass); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); virtual void AddCompoundChild(KX_IPhysicsController* child); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 706b80a1fab..42316c6c873 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1129,7 +1129,7 @@ PyObject* KX_GameObject::_getattr(const STR_String& attr) if (m_pPhysicsController1) { if (attr == "mass") - return PyFloat_FromDouble(GetPhysicsController()->GetMass()); + return PyFloat_FromDouble(m_pPhysicsController1->GetMass()); } if (attr == "parent") @@ -1171,10 +1171,6 @@ 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"); - return 1; - } if (attr == "parent") { PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()"); @@ -1203,6 +1199,11 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr return 0; } } + if (attr == "mass") { + if (m_pPhysicsController1) + m_pPhysicsController1->SetMass(val); + return 0; + } } if (PySequence_Check(value)) diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index fed71735bec..13501f1fbbd 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -78,6 +78,7 @@ public: virtual void setPosition(const MT_Point3& pos)=0; virtual void setScaling(const MT_Vector3& scaling)=0; virtual MT_Scalar GetMass()=0; + virtual void SetMass(MT_Scalar newmass)=0; virtual MT_Vector3 getReactionForce()=0; virtual void setRigidBody(bool rigid)=0; virtual void AddCompoundChild(KX_IPhysicsController* child) = 0; diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index d44ab477749..176ccf1a84a 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -133,10 +133,12 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, KX_SCA_DynamicActuator::KX_SCA_DynamicActuator(SCA_IObject *gameobj, short dyn_operation, + float setmass, PyTypeObject* T) : SCA_IActuator(gameobj, T), - m_dyn_operation(dyn_operation) + m_dyn_operation(dyn_operation), + m_setmass(setmass) { } /* End of constructor */ @@ -179,6 +181,9 @@ bool KX_SCA_DynamicActuator::Update() case 3: controller->setRigidBody(false); break; + case 4: + controller->SetMass(m_setmass); + break; } return false; diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h index b47c3a511d9..de2fab68d15 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h @@ -45,10 +45,12 @@ class KX_SCA_DynamicActuator : public SCA_IActuator // dynamics operation to apply to the game object short m_dyn_operation; + float m_setmass; public: KX_SCA_DynamicActuator( SCA_IObject* gameobj, short dyn_operation, + float setmass, PyTypeObject* T=&Type ); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp index c842ca1ee14..7631ee05b0b 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp @@ -205,6 +205,10 @@ MT_Scalar KX_SumoPhysicsController::GetMass() return SumoPhysicsController::getMass(); } +void KX_SumoPhysicsController::SetMass(MT_Scalar newmass) +{ +} + MT_Scalar KX_SumoPhysicsController::GetRadius() { return SumoPhysicsController::GetRadius(); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h index a684b637894..46c8ba6df45 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h @@ -87,6 +87,7 @@ public: virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); virtual MT_Scalar GetMass(); + virtual void SetMass(MT_Scalar newmass); virtual MT_Scalar GetRadius(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index fafce5cf5cc..d09ad58fe3b 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -74,10 +74,10 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) ///??? -#ifdef WIN32 +/*#ifdef WIN32 if (GetRigidBody() && !GetRigidBody()->isStaticObject()) GetRigidBody()->setLinearVelocity(startVel); -#endif +#endif*/ } From c0ecbfce0ec729164d93bc01d2ac8a485608770c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 15 Jan 2009 18:06:06 +0000 Subject: [PATCH 128/252] blender was crashing if no argument was given after '-t' mesh.faces.deltete(...) with an empty list no longer returns an error. --- source/blender/python/api2_2x/Mesh.c | 6 +++--- source/blender/render/intern/source/pipeline.c | 2 +- source/creator/creator.c | 10 +++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index 32ddb464c88..42c80728bab 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -5390,9 +5390,9 @@ static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args ) /* see how many args we need to parse */ len = PySequence_Size( args ); - if( len < 1 ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "sequence must contain at least one int or MFace" ); + if( len < 1 ) { + Py_RETURN_NONE; + } face_table = MEM_callocN( len*sizeof( unsigned int ), "face_table" ); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 9ef9c2f3859..5c3c954aa8e 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2710,7 +2710,7 @@ void RE_set_max_threads(int threads) } else if(threads>=1 && threads<=BLENDER_MAX_THREADS) { commandline_threads= threads; } else { - printf("Error, threads has to be in range 1-%d\n", BLENDER_MAX_THREADS); + printf("Error, threads has to be in range 0-%d\n", BLENDER_MAX_THREADS); } } diff --git a/source/creator/creator.c b/source/creator/creator.c index a6111210593..9d6841c3708 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -785,10 +785,14 @@ int main(int argc, char **argv) case 't': a++; - if(G.background) { - RE_set_max_threads(atoi(argv[a])); + if (a < argc) { + if(G.background) { + RE_set_max_threads(atoi(argv[a])); + } else { + printf("Warning: threads can only be set in background mode\n"); + } } else { - printf("Warning: threads can only be set in background mode\n"); + printf("\nError: you must specify a number of threads between 0 and 8 '-t '.\n"); } break; case 'x': /* extension */ From ce3dca24d1948874e9c2aab69ecc37009582e602 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 15 Jan 2009 22:16:29 +0000 Subject: [PATCH 129/252] have had few requests to use blender for performing background tasks - visualizing data, rendering scenes automatically and character rendering on a server. This example script shows how you can run blender in background mode, parse arguments from the command line to generate a simple scene and render/save it. --- .../scripts/scripttemplate_background_job.py | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 release/scripts/scripttemplate_background_job.py diff --git a/release/scripts/scripttemplate_background_job.py b/release/scripts/scripttemplate_background_job.py new file mode 100644 index 00000000000..713acbb56a8 --- /dev/null +++ b/release/scripts/scripttemplate_background_job.py @@ -0,0 +1,123 @@ +#!BPY +""" +Name: 'Background Job Example' +Blender: 248 +Group: 'ScriptTemplate' +Tooltip: 'Script template for automating tasks from the command line with blender' +""" + +from Blender import Window +import bpy + +script_data = \ +'''# This script is an example of how you can run blender from the command line (in background mode with no interface) +# to automate tasks, in this example it creates a text object, camera and light, then renders and/or saves it. +# This example also shows how you can parse command line options to python scripts. +# +# Example usage for this test. +# blender -b -P $HOME/.blender/scripts/scripttemplate_background_job.py -- --text="Hello World" --render="/tmp/hello" --save="/tmp/hello.blend" +# +# Notice all python args are after the '--' argument. + +import Blender +import bpy + +def example_function(body_text, save_path, render_path): + + sce= bpy.data.scenes.active + + txt_data= bpy.data.curves.new('MyText', 'Text3d') + + # Text Object + txt_ob = sce.objects.new(txt_data) # add the data to the scene as an object + txt_data.setText(body_text) # set the body text to the command line arg given + txt_data.setAlignment(Blender.Text3d.MIDDLE)# center text + + # Camera + cam_data= bpy.data.cameras.new('MyCam') # create new camera data + cam_ob= sce.objects.new(cam_data) # add the camera data to the scene (creating a new object) + sce.objects.camera= cam_ob # set the active camera + cam_ob.loc= 0,0,10 + + # Lamp + lamp_data= bpy.data.lamps.new('MyLamp') + lamp_ob= sce.objects.new(lamp_data) + lamp_ob.loc= 2,2,5 + + if save_path: + try: + f= open(save_path, 'w') + f.close() + ok= True + except: + print 'Cannot save to path "%s"' % save_path + ok= False + + if ok: + Blender.Save(save_path, 1) + + if render_path: + render= sce.render + render.extensions= True + render.renderPath = render_path + render.sFrame= 1 + render.eFrame= 1 + render.renderAnim() + + + +import sys # to get command line args +import optparse # to parse options for us and print a nice help message + +script_name= 'background_job.py' + +def main(): + + # get the args passed to blender after "--", all of which are ignored by blender specifically + # so python may receive its own arguments + argv= sys.argv + + if '--' not in argv: + argv = [] # as if no args are passed + else: + argv = argv[argv.index('--')+1: ] # get all args after "--" + + # When --help or no args are given, print this help + usage_text = 'Run blender in background mode with this script:\n' + usage_text += ' blender -b -P ' + script_name + ' -- [options]' + + parser = optparse.OptionParser(usage = usage_text) + + + # Example background utility, add some text and renders or saves it (with options) + parser.add_option('-t', '--text', dest='body_text', help='This text will be used to render an image') + + parser.add_option('-s', '--save', dest='save_path', help='Save the generated file to the specified path', metavar='FILE') + parser.add_option('-r', '--render', dest='render_path', help='Render an image to the specified path', metavar='FILE') + + options, args = parser.parse_args(argv) # In this example we wont use the args + + if not argv: + parser.print_help() + return + + if not hasattr(options, 'body_text'): + print 'Error: --text="some string" argument not given, aborting.\n' + parser.print_help() + return + + # Run the example function + example_function(options.body_text, options.save_path, options.render_path) + + print 'batch job finished, exiting' + + +if __name__ == '__main__': + main() +''' + +new_text = bpy.data.texts.new('background_job.py') +new_text.write(script_data) +bpy.data.texts.active = new_text +Window.RedrawAll() + From bae2de3f1a23205bc2a11a7065fee450c4a591a9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 16 Jan 2009 10:51:30 +0000 Subject: [PATCH 130/252] minor corrections --- release/scripts/scripttemplate_background_job.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/release/scripts/scripttemplate_background_job.py b/release/scripts/scripttemplate_background_job.py index 713acbb56a8..86b58991849 100644 --- a/release/scripts/scripttemplate_background_job.py +++ b/release/scripts/scripttemplate_background_job.py @@ -15,7 +15,7 @@ script_data = \ # This example also shows how you can parse command line options to python scripts. # # Example usage for this test. -# blender -b -P $HOME/.blender/scripts/scripttemplate_background_job.py -- --text="Hello World" --render="/tmp/hello" --save="/tmp/hello.blend" +# blender -b -P $HOME/background_job.py -- --text="Hello World" --render="/tmp/hello" --save="/tmp/hello.blend" # # Notice all python args are after the '--' argument. @@ -90,7 +90,8 @@ def main(): # Example background utility, add some text and renders or saves it (with options) - parser.add_option('-t', '--text', dest='body_text', help='This text will be used to render an image') + # Possible types are: string, int, long, choice, float and complex. + parser.add_option('-t', '--text', dest='body_text', help='This text will be used to render an image', type='string') parser.add_option('-s', '--save', dest='save_path', help='Save the generated file to the specified path', metavar='FILE') parser.add_option('-r', '--render', dest='render_path', help='Render an image to the specified path', metavar='FILE') @@ -101,7 +102,7 @@ def main(): parser.print_help() return - if not hasattr(options, 'body_text'): + if not options.body_text: print 'Error: --text="some string" argument not given, aborting.\n' parser.print_help() return From 16aa62e058e2d4e895e7548d5df49483243beeef Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 16 Jan 2009 20:24:31 +0000 Subject: [PATCH 131/252] Command Gesture - Polygonize New command option to turn continuous strokes into polylines. --- source/blender/src/editarmature_sketch.c | 51 +++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 192718c058f..16439b112e4 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -957,6 +957,52 @@ void sk_cutoutStroke(SK_Stroke *stk, int start, int end, float p_start[3], float } } +void sk_polygonizeStroke(SK_Stroke *stk, int start, int end) +{ + int offset; + int i; + + /* find first exact points outside of range */ + for (;start > 0; start--) + { + if (stk->points[start].type == PT_EXACT) + { + break; + } + } + + for (;end < stk->nb_points - 1; end++) + { + if (stk->points[end].type == PT_EXACT) + { + break; + } + } + + offset = start + 1; + + for (i = start + 1; i < end; i++) + { + if (stk->points[i].type == PT_EXACT) + { + if (offset != i) + { + memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point)); + } + + offset++; + } + } + + /* some points were removes, move end of array */ + if (offset < end) + { + int size = stk->nb_points - end; + memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point)); + stk->nb_points = offset + size; + } +} + void sk_flattenStroke(SK_Stroke *stk, int start, int end) { float normal[3], distance[3]; @@ -2509,7 +2555,7 @@ void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch) SK_Intersection *isect; int command; - command = pupmenu("Action %t|Flatten %x1|Cut Out %x2"); + command = pupmenu("Action %t|Flatten %x1|Cut Out %x2|Polygonize %x3"); if(command < 1) return; for (isect = gest->intersections.first; isect; isect = isect->next) @@ -2528,6 +2574,9 @@ void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch) case 2: sk_cutoutStroke(isect->stroke, isect->after, i2->before, isect->p, i2->p); break; + case 3: + sk_polygonizeStroke(isect->stroke, isect->before, i2->after); + break; } isect = i2; From ff52dcbf0dd4ab81e9aebcfff3702c987d05e98c Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 18 Jan 2009 22:09:29 +0000 Subject: [PATCH 132/252] Bugfix: Transform Snap Would crash if snapping from a mesh in edit mode to a group instance including that same mesh. Reported by UncleZeiv on IRC --- source/blender/src/transform_snap.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index e7937e72c2b..eeb5eaeec10 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -1186,10 +1186,21 @@ int snapObjects(int *dist, float *loc, float *no, int mode) { Object *ob = dupli_ob->ob; if (ob->type == OB_MESH) { - DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + DerivedMesh *dm; + int editmesh = 0; int val; - val = snapDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0); + if (ob == G.obedit) + { + dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); + editmesh = 1; + } + else + { + dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + } + + val = snapDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth, editmesh); retval = retval || val; From 8bd7aa0a01ee53172bb4fd1bd2de1b318c4ea80c Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 21 Jan 2009 13:54:53 +0000 Subject: [PATCH 133/252] BGE API cleanup: action actuator. --- .../Converter/BL_ActionActuator.cpp | 341 ++++++++++++------ .../gameengine/Converter/BL_ActionActuator.h | 48 ++- source/gameengine/PyDoc/BL_ActionActuator.py | 52 ++- 3 files changed, 309 insertions(+), 132 deletions(-) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 4d748948c27..c05f763cacb 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -52,6 +52,8 @@ #include "FloatValue.h" #include "PyObjectPlus.h" +#include "blendef.h" + #ifdef HAVE_CONFIG_H #include #endif @@ -418,67 +420,6 @@ bool BL_ActionActuator::Update(double curtime, bool frame) /* Python functions */ /* ------------------------------------------------------------------------- */ -/* Integration hooks ------------------------------------------------------- */ - -PyTypeObject BL_ActionActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, - "BL_ActionActuator", - sizeof(BL_ActionActuator), - 0, - PyDestructor, - 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, - 0, - 0, - 0, - 0 -}; - -PyParentObject BL_ActionActuator::Parents[] = { - &BL_ActionActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; - -PyMethodDef BL_ActionActuator::Methods[] = { - {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc}, - {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc}, - {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc}, - {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, (PY_METHODCHAR)SetBlendin_doc}, - {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, (PY_METHODCHAR)SetPriority_doc}, - {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, (PY_METHODCHAR)SetFrame_doc}, - {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, - {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, (PY_METHODCHAR)SetFrameProperty_doc}, - {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, (PY_METHODCHAR)SetBlendtime_doc}, - - {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, (PY_METHODCHAR)GetAction_doc}, - {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, (PY_METHODCHAR)GetStart_doc}, - {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, (PY_METHODCHAR)GetEnd_doc}, - {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, (PY_METHODCHAR)GetBlendin_doc}, - {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, (PY_METHODCHAR)GetPriority_doc}, - {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, (PY_METHODCHAR)GetFrame_doc}, - {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, - {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, (PY_METHODCHAR)GetFrameProperty_doc}, - {"setChannel", (PyCFunction) BL_ActionActuator::sPySetChannel, METH_VARARGS, (PY_METHODCHAR)SetChannel_doc}, -// {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS}, - {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc}, - {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc}, - {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0}, - {"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0}, - {NULL,NULL} //Sentinel -}; - -PyObject* BL_ActionActuator::_getattr(const STR_String& attr) { - _getattr_up(SCA_IActuator); -} - /* setStart */ const char BL_ActionActuator::GetAction_doc[] = "getAction()\n" @@ -487,6 +428,8 @@ const char BL_ActionActuator::GetAction_doc[] = PyObject* BL_ActionActuator::PyGetAction(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getAction()", "the action property"); + if (m_action){ return PyString_FromString(m_action->id.name+2); } @@ -501,6 +444,8 @@ const char BL_ActionActuator::GetProperty_doc[] = PyObject* BL_ActionActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getProperty()", "the property property"); + PyObject *result; result = Py_BuildValue("s", (const char *)m_propname); @@ -516,6 +461,8 @@ const char BL_ActionActuator::GetFrameProperty_doc[] = PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getFrameProperty()", "the frameProperty property"); + PyObject *result; result = Py_BuildValue("s", (const char *)m_framepropname); @@ -531,6 +478,8 @@ const char BL_ActionActuator::GetFrame_doc[] = PyObject* BL_ActionActuator::PyGetFrame(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getFrame()", "the frame property"); + PyObject *result; result = Py_BuildValue("f", m_localtime); @@ -546,6 +495,8 @@ const char BL_ActionActuator::GetEnd_doc[] = PyObject* BL_ActionActuator::PyGetEnd(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getEnd()", "the end property"); + PyObject *result; result = Py_BuildValue("f", m_endframe); @@ -561,6 +512,8 @@ const char BL_ActionActuator::GetStart_doc[] = PyObject* BL_ActionActuator::PyGetStart(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getStart()", "the start property"); + PyObject *result; result = Py_BuildValue("f", m_startframe); @@ -577,6 +530,8 @@ const char BL_ActionActuator::GetBlendin_doc[] = PyObject* BL_ActionActuator::PyGetBlendin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getBlendin()", "the blendin property"); + PyObject *result; result = Py_BuildValue("f", m_blendin); @@ -593,6 +548,8 @@ const char BL_ActionActuator::GetPriority_doc[] = PyObject* BL_ActionActuator::PyGetPriority(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getPriority()", "the priority property"); + PyObject *result; result = Py_BuildValue("i", m_priority); @@ -613,6 +570,8 @@ const char BL_ActionActuator::SetAction_doc[] = PyObject* BL_ActionActuator::PySetAction(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setAction()", "the action property"); + char *string; int reset = 1; @@ -647,6 +606,8 @@ const char BL_ActionActuator::SetStart_doc[] = PyObject* BL_ActionActuator::PySetStart(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setStart()", "the start property"); + float start; if (PyArg_ParseTuple(args,"f",&start)) @@ -668,6 +629,8 @@ const char BL_ActionActuator::SetEnd_doc[] = PyObject* BL_ActionActuator::PySetEnd(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setEnd()", "the end property"); + float end; if (PyArg_ParseTuple(args,"f",&end)) @@ -690,6 +653,8 @@ const char BL_ActionActuator::SetBlendin_doc[] = PyObject* BL_ActionActuator::PySetBlendin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBlendin()", "the blendin property"); + float blendin; if (PyArg_ParseTuple(args,"f",&blendin)) @@ -713,6 +678,8 @@ const char BL_ActionActuator::SetBlendtime_doc[] = PyObject* BL_ActionActuator::PySetBlendtime(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBlendtime()", "the blendtime property"); + float blendframe; if (PyArg_ParseTuple(args,"f",&blendframe)) @@ -740,6 +707,8 @@ const char BL_ActionActuator::SetPriority_doc[] = PyObject* BL_ActionActuator::PySetPriority(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setPriority()", "the priority property"); + int priority; if (PyArg_ParseTuple(args,"i",&priority)) @@ -761,6 +730,8 @@ const char BL_ActionActuator::SetFrame_doc[] = PyObject* BL_ActionActuator::PySetFrame(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrame()", "the frame property"); + float frame; if (PyArg_ParseTuple(args,"f",&frame)) @@ -787,6 +758,8 @@ const char BL_ActionActuator::SetProperty_doc[] = PyObject* BL_ActionActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the property property"); + char *string; if (PyArg_ParseTuple(args,"s",&string)) @@ -808,6 +781,8 @@ const char BL_ActionActuator::SetFrameProperty_doc[] = PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrameProperty()", "the frameProperty property"); + char *string; if (PyArg_ParseTuple(args,"s",&string)) @@ -839,16 +814,80 @@ PyObject* BL_ActionActuator::PyGetChannel(PyObject* self, } */ -/* setChannel */ -const char BL_ActionActuator::SetChannel_doc[] = +/* getType */ +const char BL_ActionActuator::GetType_doc[] = +"getType()\n" +"\tReturns the operation mode of the actuator.\n"; +PyObject* BL_ActionActuator::PyGetType(PyObject* self, + PyObject* args, + PyObject* kwds) { + ShowDeprecationWarning("getType()", "the type property"); + + return Py_BuildValue("h", m_playtype); +} + +/* setType */ +const char BL_ActionActuator::SetType_doc[] = +"setType(mode)\n" +"\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n" +"\tSet the operation mode of the actuator.\n"; +PyObject* BL_ActionActuator::PySetType(PyObject* self, + PyObject* args, + PyObject* kwds) { + ShowDeprecationWarning("setType()", "the type property"); + + short typeArg; + + if (!PyArg_ParseTuple(args, "h", &typeArg)) { + return NULL; + } + + switch (typeArg) { + case KX_ACT_ACTION_PLAY: + case KX_ACT_ACTION_FLIPPER: + case KX_ACT_ACTION_LOOPSTOP: + case KX_ACT_ACTION_LOOPEND: + case KX_ACT_ACTION_PROPERTY: + m_playtype = typeArg; + break; + default: + printf("Invalid type for action actuator: %d\n", typeArg); /* error */ + } + Py_RETURN_NONE; +} + +PyObject* BL_ActionActuator::PyGetContinue(PyObject* self) { + ShowDeprecationWarning("getContinue()", "the continue property"); + + return PyInt_FromLong((long)(m_end_reset==0)); +} + +PyObject* BL_ActionActuator::PySetContinue(PyObject* self, PyObject* value) { + ShowDeprecationWarning("setContinue()", "the continue property"); + + int param = PyObject_IsTrue( value ); + + if( param == -1 ) { + PyErr_SetString( PyExc_TypeError, "expected True/False or 0/1" ); + return NULL; + } + + if (param) { + m_end_reset = 0; + } else { + m_end_reset = 1; + } + Py_RETURN_NONE; +} + +//<-----Deprecated + +/* setChannel */ +KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel, "setChannel(channel, matrix)\n" "\t - channel : A string specifying the name of the bone channel.\n" "\t - matrix : A 4x4 matrix specifying the overriding transformation\n" -"\t as an offset from the bone's rest position.\n"; - -PyObject* BL_ActionActuator::PySetChannel(PyObject* self, - PyObject* args, - PyObject* kwds) +"\t as an offset from the bone's rest position.\n") { float matrix[4][4]; char *string; @@ -923,61 +962,123 @@ PyObject* BL_ActionActuator::PySetChannel(PyObject* self, Py_RETURN_NONE; } -/* getType */ -const char BL_ActionActuator::GetType_doc[] = -"getType()\n" -"\tReturns the operation mode of the actuator.\n"; -PyObject* BL_ActionActuator::PyGetType(PyObject* self, - PyObject* args, - PyObject* kwds) { - return Py_BuildValue("h", m_playtype); +/* ------------------------------------------------------------------------- */ +/* Python Integration Hooks */ +/* ------------------------------------------------------------------------- */ + +PyTypeObject BL_ActionActuator::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "BL_ActionActuator", + sizeof(BL_ActionActuator), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject BL_ActionActuator::Parents[] = { + &BL_ActionActuator::Type, + &SCA_IActuator::Type, + &SCA_ILogicBrick::Type, + &CValue::Type, + NULL +}; + +PyMethodDef BL_ActionActuator::Methods[] = { + //Deprecated -----> + {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc}, + {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc}, + {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc}, + {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, (PY_METHODCHAR)SetBlendin_doc}, + {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, (PY_METHODCHAR)SetPriority_doc}, + {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, (PY_METHODCHAR)SetFrame_doc}, + {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, + {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, (PY_METHODCHAR)SetFrameProperty_doc}, + {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, (PY_METHODCHAR)SetBlendtime_doc}, + + {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, (PY_METHODCHAR)GetAction_doc}, + {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, (PY_METHODCHAR)GetStart_doc}, + {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, (PY_METHODCHAR)GetEnd_doc}, + {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, (PY_METHODCHAR)GetBlendin_doc}, + {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, (PY_METHODCHAR)GetPriority_doc}, + {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, (PY_METHODCHAR)GetFrame_doc}, + {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, + {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, (PY_METHODCHAR)GetFrameProperty_doc}, +// {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS}, + {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc}, + {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc}, + {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0}, + {"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0}, + //<------ + KX_PYMETHODTABLE(BL_ActionActuator, setChannel), + {NULL,NULL} //Sentinel +}; + +PyAttributeDef BL_ActionActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ActionActuator, m_startframe), + KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ActionActuator, m_endframe), + KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ActionActuator, m_blendin), + KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame), + KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ActionActuator, m_propname), + KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ActionActuator, m_framepropname), + KX_PYATTRIBUTE_BOOL_RW("continue", BL_ActionActuator, m_end_reset), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime), + KX_PYATTRIBUTE_ENUM_RW_CHECK("type",0,100,false,BL_ActionActuator,m_playtype,CheckType), + { NULL } //Sentinel +}; + +PyObject* BL_ActionActuator::_getattr(const STR_String& attr) { + if (attr == "action") + return PyString_FromString(m_action->id.name+2); + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + _getattr_up(SCA_IActuator); } -/* setType */ -const char BL_ActionActuator::SetType_doc[] = -"setType(mode)\n" -"\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n" -"\tSet the operation mode of the actuator.\n"; -PyObject* BL_ActionActuator::PySetType(PyObject* self, - PyObject* args, - PyObject* kwds) { - short typeArg; - - if (!PyArg_ParseTuple(args, "h", &typeArg)) { - return NULL; - } +int BL_ActionActuator::_setattr(const STR_String& attr, PyObject* value) { + if (attr == "action") + { + if (!PyString_Check(value)) + { + PyErr_SetString(PyExc_ValueError, "expected a string"); + return 1; + } - switch (typeArg) { - case KX_ACT_ACTION_PLAY: - case KX_ACT_ACTION_FLIPPER: - case KX_ACT_ACTION_LOOPSTOP: - case KX_ACT_ACTION_LOOPEND: - case KX_ACT_ACTION_PROPERTY: - m_playtype = typeArg; - break; - default: - printf("Invalid type for action actuator: %d\n", typeArg); /* error */ - } - Py_RETURN_NONE; -} + STR_String val = PyString_AsString(value); + + if (val == "") + { + m_action = NULL; + return 0; + } -PyObject* BL_ActionActuator::PyGetContinue(PyObject* self) { - return PyInt_FromLong((long)(m_end_reset==0)); -} + bAction *action; + + action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val); + -PyObject* BL_ActionActuator::PySetContinue(PyObject* self, PyObject* value) { - int param = PyObject_IsTrue( value ); - - if( param == -1 ) { - PyErr_SetString( PyExc_TypeError, "expected True/False or 0/1" ); - return NULL; + if (!action) + { + PyErr_SetString(PyExc_ValueError, "action not found!"); + return 1; + } + + m_action = action; + return 0; } - - if (param) { - m_end_reset = 0; - } else { - m_end_reset = 1; - } - Py_RETURN_NONE; -} - + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_IActuator::_setattr(attr, value); +} \ No newline at end of file diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index a67b6d29b74..04bd9c803c5 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -81,6 +81,7 @@ public: void SetBlendTime (float newtime); + //Deprecated -----> KX_PYMETHOD_DOC(BL_ActionActuator,SetAction); KX_PYMETHOD_DOC(BL_ActionActuator,SetBlendin); KX_PYMETHOD_DOC(BL_ActionActuator,SetPriority); @@ -90,7 +91,6 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,SetProperty); KX_PYMETHOD_DOC(BL_ActionActuator,SetFrameProperty); KX_PYMETHOD_DOC(BL_ActionActuator,SetBlendtime); - KX_PYMETHOD_DOC(BL_ActionActuator,SetChannel); KX_PYMETHOD_DOC(BL_ActionActuator,GetAction); KX_PYMETHOD_DOC(BL_ActionActuator,GetBlendin); @@ -105,8 +105,12 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,SetType); KX_PYMETHOD_NOARGS(BL_ActionActuator,GetContinue); KX_PYMETHOD_O(BL_ActionActuator,SetContinue); + //<----- + + KX_PYMETHOD_DOC(BL_ActionActuator,setChannel); virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject* value); enum ActionActType { @@ -117,6 +121,46 @@ public: KX_ACT_ACTION_PROPERTY = 6 }; + /* attribute check */ + static int CheckFrame(void *self, const PyAttributeDef*) + { + BL_ActionActuator* act = reinterpret_cast(self); + + if (act->m_localtime < act->m_startframe) + act->m_localtime = act->m_startframe; + else if (act->m_localtime > act->m_endframe) + act->m_localtime = act->m_endframe; + + return 0; + } + + static int CheckBlendTime(void *self, const PyAttributeDef*) + { + BL_ActionActuator* act = reinterpret_cast(self); + + if (act->m_blendframe < act->m_blendin) + act->m_blendframe = act->m_blendin; + + return 0; + } + + static int CheckType(void *self, const PyAttributeDef*) + { + BL_ActionActuator* act = reinterpret_cast(self); + + switch (act->m_playtype) { + case KX_ACT_ACTION_PLAY: + case KX_ACT_ACTION_FLIPPER: + case KX_ACT_ACTION_LOOPSTOP: + case KX_ACT_ACTION_LOOPEND: + case KX_ACT_ACTION_PROPERTY: + return 0; + default: + PyErr_SetString(PyExc_ValueError, "invalid type supplied"); + return 1; + } + + } protected: void SetStartTime(float curtime); @@ -141,7 +185,7 @@ protected: float m_stridelength; short m_playtype; short m_priority; - short m_end_reset; + bool m_end_reset; struct bPose* m_pose; struct bPose* m_blendpose; struct bPose* m_userpose; diff --git a/source/gameengine/PyDoc/BL_ActionActuator.py b/source/gameengine/PyDoc/BL_ActionActuator.py index b68d3014115..5d6ea51060b 100644 --- a/source/gameengine/PyDoc/BL_ActionActuator.py +++ b/source/gameengine/PyDoc/BL_ActionActuator.py @@ -5,7 +5,49 @@ from SCA_IActuator import * class BL_ActionActuator(SCA_IActuator): """ Action Actuators apply an action to an actor. + + @ivar action: The name of the action to set as the current action. + @type action: string + @ivar start: Specifies the starting frame of the animation. + @type start: float + @type end: Specifies the ending frame of the animation. + @type end: float + @ivar blendin: Specifies the number of frames of animation to generate when making transitions between actions. + @type blendin: float + @ivar priority: Sets the priority of this actuator. Actuators will lower + priority numbers will override actuators with higher + numbers. + @type priority: integer + @ivar frame: Sets the current frame for the animation. + @type frame: float + @ivar property: Sets the property to be used in FromProp playback mode. + @type property: string + @ivar blendTime: Sets the internal frame timer. This property must be in + the range from 0.0 to 1.0. + @type blendTime: float + @ivar type: The operation mode of the actuator. + KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, + KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + @type type: integer + @ivar continue: The actions continue option, True or False. + When True, the action will always play from where last left off, + otherwise negative events to this actuator will reset it to its start frame. + @type: boolean + @ivar frameProperty: The name of the property that is set to the current frame number. + @type frameProperty: string """ + def setChannel(channel, matrix, mode = False): + """ + @param channel: A string specifying the name of the bone channel. + @type channel: string + @param matrix: A 4x4 matrix specifying the overriding transformation + as an offset from the bone's rest position. + @type matrix: list [[float]] + @param mode: True for armature/world space, False for bone space + @type mode: boolean + """ + + #--The following methods are deprecated-- def setAction(action, reset = True): """ Sets the current action. @@ -154,16 +196,6 @@ class BL_ActionActuator(SCA_IActuator): @rtype: string """ - def setChannel(channel, matrix, mode = False): - """ - @param channel: A string specifying the name of the bone channel. - @type channel: string - @param matrix: A 4x4 matrix specifying the overriding transformation - as an offset from the bone's rest position. - @type matrix: list [[float]] - @param mode: True for armature/world space, False for bone space - @type mode: boolean - """ def setFrameProperty(prop): """ @param prop: A string specifying the property of the object that will be updated with the action frame number. From 73cffd9aad43eeb3c1aa029c0e03564739a72800 Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Wed, 21 Jan 2009 15:45:31 +0000 Subject: [PATCH 134/252] == Scripts == - Scripts Help Browser: error parsing doc info wrapped in triple single quotes, like done in the 3ds importer. Thanks Jean-Michel (jms) for informing me about it. --- release/scripts/help_browser.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/release/scripts/help_browser.py b/release/scripts/help_browser.py index b5d747ee9c4..c207a12068f 100644 --- a/release/scripts/help_browser.py +++ b/release/scripts/help_browser.py @@ -8,7 +8,7 @@ Tooltip: 'Show help information about a chosen installed script.' """ __author__ = "Willian P. Germano" -__version__ = "0.2 01/11/09" +__version__ = "0.3 01/21/09" __email__ = ('scripts', 'Author, wgermano:ig*com*br') __url__ = ('blender', 'blenderartists.org') @@ -68,7 +68,8 @@ Hotkeys:
# ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- # Thanks: Brendon Murphy (suggestion) and Kevin Morgan (implementation) -# for the "run" button. +# for the "run" button; Jean-Michel Soler for pointing a parsing error +# with multilines using triple single quotes. import Blender from Blender import sys as bsys, Draw, Window, Registry @@ -355,7 +356,12 @@ def parse_pyobj(var, lines, i): l = "ERROR" elif l[0] == "'": - if l[-1] == '\\': + if l[1:3] == "''": # ''' + if l.find("'''", 3) < 0: # multiline + l2, i = parse_pyobj_close("'''", lines, i) + if l[-1] == '\\': l = l[:-1] + l = "%s%s" % (l, l2) + elif l[-1] == '\\': l2, i = parse_pyobj_close("'", lines, i) l = "%s%s" % (l, l2) elif l[-1] == "'" and l[-2] != '\\': # single line: '...' From c6715de1e93b65a878bfe39a0923a1f21969b899 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 21 Jan 2009 22:20:16 +0000 Subject: [PATCH 135/252] misc bug fixes and display adjustments --- source/blender/src/editarmature_retarget.c | 16 ++++++++++------ source/blender/src/editarmature_sketch.c | 4 +++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/source/blender/src/editarmature_retarget.c b/source/blender/src/editarmature_retarget.c index fe1c394f326..ad114868a69 100644 --- a/source/blender/src/editarmature_retarget.c +++ b/source/blender/src/editarmature_retarget.c @@ -816,16 +816,20 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* SET bone link to bone corresponding to pchan */ EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name); - /* for pole targets, link to parent bone instead, if possible */ - if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1) + /* Making sure bone is in this armature */ + if (link != NULL) { - if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name)) + /* for pole targets, link to parent bone instead, if possible */ + if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1) { - link = link->parent; + if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name)) + { + link = link->parent; + } } + + found = RIG_parentControl(ctrl, link); } - - found = RIG_parentControl(ctrl, link); } } diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 16439b112e4..5830b2286f6 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1258,7 +1258,8 @@ void drawSubdividedStrokeBy(BArcIterator *iter, NextSubdivisionFunc next_subdivi iter->head(iter); VECCOPY(head, iter->p); - glColor3f(0, 1, 1); + glColor3f(0, 1, 0); + glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE) * 2); glBegin(GL_POINTS); index = next_subdividion(iter, bone_start, end, head, tail); @@ -1273,6 +1274,7 @@ void drawSubdividedStrokeBy(BArcIterator *iter, NextSubdivisionFunc next_subdivi } glEnd(); + glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE)); } void sk_drawStrokeSubdivision(SK_Stroke *stk) From 8a95c67a50918a928f45fffd53e084428fcff9d8 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 22 Jan 2009 17:40:47 +0000 Subject: [PATCH 136/252] BGE API cleanup: shape action actuator. --- .../Converter/BL_ActionActuator.cpp | 16 ++-- .../gameengine/Converter/BL_ActionActuator.h | 22 ++--- .../Converter/BL_ShapeActionActuator.cpp | 80 ++++++++++++++++++- .../Converter/BL_ShapeActionActuator.h | 40 ++++++++++ source/gameengine/Ketsji/KX_PythonInit.cpp | 10 +-- source/gameengine/PyDoc/BL_ActionActuator.py | 23 +++++- .../PyDoc/BL_ShapeActionActuator.py | 63 +++++++++++---- 7 files changed, 205 insertions(+), 49 deletions(-) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index c05f763cacb..65d6892fa6d 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -39,10 +39,9 @@ #include "BL_SkinDeformer.h" #include "KX_GameObject.h" #include "STR_HashedString.h" -#include "DNA_action_types.h" #include "DNA_nla_types.h" -#include "DNA_actuator_types.h" #include "BKE_action.h" +#include "DNA_action_types.h" #include "DNA_armature_types.h" #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" @@ -51,7 +50,6 @@ #include "BKE_utildefines.h" #include "FloatValue.h" #include "PyObjectPlus.h" - #include "blendef.h" #ifdef HAVE_CONFIG_H @@ -843,11 +841,11 @@ PyObject* BL_ActionActuator::PySetType(PyObject* self, } switch (typeArg) { - case KX_ACT_ACTION_PLAY: - case KX_ACT_ACTION_FLIPPER: - case KX_ACT_ACTION_LOOPSTOP: - case KX_ACT_ACTION_LOOPEND: - case KX_ACT_ACTION_PROPERTY: + case ACT_ACTION_PLAY: + case ACT_ACTION_FLIPPER: + case ACT_ACTION_LOOP_STOP: + case ACT_ACTION_LOOP_END: + case ACT_ACTION_FROM_PROP: m_playtype = typeArg; break; default: @@ -1033,7 +1031,7 @@ PyAttributeDef BL_ActionActuator::Attributes[] = { KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ActionActuator, m_framepropname), KX_PYATTRIBUTE_BOOL_RW("continue", BL_ActionActuator, m_end_reset), KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime), - KX_PYATTRIBUTE_ENUM_RW_CHECK("type",0,100,false,BL_ActionActuator,m_playtype,CheckType), + KX_PYATTRIBUTE_SHORT_RW_CHECK("type",0,100,false,BL_ActionActuator,m_playtype,CheckType), { NULL } //Sentinel }; diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 04bd9c803c5..6e291106553 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -32,6 +32,7 @@ #include "GEN_HashedPtr.h" #include "SCA_IActuator.h" +#include "DNA_actuator_types.h" #include "MT_Point3.h" class BL_ActionActuator : public SCA_IActuator @@ -112,15 +113,6 @@ public: virtual PyObject* _getattr(const STR_String& attr); virtual int _setattr(const STR_String& attr, PyObject* value); - enum ActionActType - { - KX_ACT_ACTION_PLAY = 0, - KX_ACT_ACTION_FLIPPER = 2, - KX_ACT_ACTION_LOOPSTOP, - KX_ACT_ACTION_LOOPEND, - KX_ACT_ACTION_PROPERTY = 6 - }; - /* attribute check */ static int CheckFrame(void *self, const PyAttributeDef*) { @@ -138,7 +130,7 @@ public: { BL_ActionActuator* act = reinterpret_cast(self); - if (act->m_blendframe < act->m_blendin) + if (act->m_blendframe > act->m_blendin) act->m_blendframe = act->m_blendin; return 0; @@ -149,11 +141,11 @@ public: BL_ActionActuator* act = reinterpret_cast(self); switch (act->m_playtype) { - case KX_ACT_ACTION_PLAY: - case KX_ACT_ACTION_FLIPPER: - case KX_ACT_ACTION_LOOPSTOP: - case KX_ACT_ACTION_LOOPEND: - case KX_ACT_ACTION_PROPERTY: + case ACT_ACTION_PLAY: + case ACT_ACTION_FLIPPER: + case ACT_ACTION_LOOP_STOP: + case ACT_ACTION_LOOP_END: + case ACT_ACTION_FROM_PROP: return 0; default: PyErr_SetString(PyExc_ValueError, "invalid type supplied"); diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 46f3141be29..df0a8c4f25e 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -35,13 +35,11 @@ #include "SCA_LogicManager.h" #include "BL_ShapeActionActuator.h" -#include "BL_ActionActuator.h" #include "BL_ShapeDeformer.h" #include "KX_GameObject.h" #include "STR_HashedString.h" -#include "DNA_action_types.h" #include "DNA_nla_types.h" -#include "DNA_actuator_types.h" +#include "DNA_action_types.h" #include "BKE_action.h" #include "DNA_armature_types.h" #include "MEM_guardedalloc.h" @@ -51,6 +49,7 @@ #include "BKE_utildefines.h" #include "FloatValue.h" #include "PyObjectPlus.h" +#include "blendef.h" #ifdef HAVE_CONFIG_H #include @@ -471,16 +470,73 @@ PyMethodDef BL_ShapeActionActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef BL_ShapeActionActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ShapeActionActuator, m_startframe), + KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ShapeActionActuator, m_endframe), + KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendin), + KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ShapeActionActuator, m_priority), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ShapeActionActuator, m_localtime, CheckFrame), + KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ShapeActionActuator, m_propname), + KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ShapeActionActuator, m_framepropname), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendframe, CheckBlendTime), + KX_PYATTRIBUTE_SHORT_RW_CHECK("type",0,100,false,BL_ShapeActionActuator,m_playtype,CheckType), + { NULL } //Sentinel +}; + + PyObject* BL_ShapeActionActuator::_getattr(const STR_String& attr) { + if (attr == "action") + return PyString_FromString(m_action->id.name+2); + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_IActuator); } +int BL_ShapeActionActuator::_setattr(const STR_String& attr, PyObject* value) { + if (attr == "action") + { + if (!PyString_Check(value)) + { + PyErr_SetString(PyExc_ValueError, "expected a string"); + return 1; + } + + STR_String val = PyString_AsString(value); + + if (val == "") + { + m_action = NULL; + return 0; + } + + bAction *action; + + action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val); + + + if (!action) + { + PyErr_SetString(PyExc_ValueError, "action not found!"); + return 1; + } + + m_action = action; + return 0; + } + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_IActuator::_setattr(attr, value); +} + /* setStart */ const char BL_ShapeActionActuator::GetAction_doc[] = "getAction()\n" "\tReturns a string containing the name of the current action.\n"; PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self) { + ShowDeprecationWarning("getAction()", "the action property"); if (m_action){ return PyString_FromString(m_action->id.name+2); } @@ -493,6 +549,7 @@ const char BL_ShapeActionActuator::GetProperty_doc[] = "\tReturns the name of the property to be used in FromProp mode.\n"; PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self) { + ShowDeprecationWarning("getProperty()", "the property property"); PyObject *result; result = Py_BuildValue("s", (const char *)m_propname); @@ -506,6 +563,7 @@ const char BL_ShapeActionActuator::GetFrame_doc[] = "\tReturns the current frame number.\n"; PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self) { + ShowDeprecationWarning("getFrame()", "the frame property"); PyObject *result; result = Py_BuildValue("f", m_localtime); @@ -519,6 +577,7 @@ const char BL_ShapeActionActuator::GetEnd_doc[] = "\tReturns the last frame of the action.\n"; PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self) { + ShowDeprecationWarning("getEnd()", "the end property"); PyObject *result; result = Py_BuildValue("f", m_endframe); @@ -532,6 +591,7 @@ const char BL_ShapeActionActuator::GetStart_doc[] = "\tReturns the starting frame of the action.\n"; PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self) { + ShowDeprecationWarning("getStart()", "the start property"); PyObject *result; result = Py_BuildValue("f", m_startframe); @@ -546,6 +606,7 @@ const char BL_ShapeActionActuator::GetBlendin_doc[] = "\tgenerated when this actuator is triggered.\n"; PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self) { + ShowDeprecationWarning("getBlendin()", "the blendin property"); PyObject *result; result = Py_BuildValue("f", m_blendin); @@ -560,6 +621,7 @@ const char BL_ShapeActionActuator::GetPriority_doc[] = "\tPriority numbers will override actuators with higher numbers.\n"; PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self) { + ShowDeprecationWarning("getPriority()", "the priority property"); PyObject *result; result = Py_BuildValue("i", m_priority); @@ -581,6 +643,7 @@ const char BL_ShapeActionActuator::SetAction_doc[] = PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setAction()", "the action property"); char *string; int reset = 1; @@ -615,6 +678,7 @@ const char BL_ShapeActionActuator::SetStart_doc[] = PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setStart()", "the start property"); float start; if (PyArg_ParseTuple(args,"f",&start)) @@ -636,6 +700,7 @@ const char BL_ShapeActionActuator::SetEnd_doc[] = PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setEnd()", "the end property"); float end; if (PyArg_ParseTuple(args,"f",&end)) @@ -658,6 +723,7 @@ const char BL_ShapeActionActuator::SetBlendin_doc[] = PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBlendin()", "the blendin property"); float blendin; if (PyArg_ParseTuple(args,"f",&blendin)) @@ -681,6 +747,7 @@ const char BL_ShapeActionActuator::SetBlendtime_doc[] = PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBlendtime()", "the blendTime property"); float blendframe; if (PyArg_ParseTuple(args,"f",&blendframe)) @@ -708,6 +775,7 @@ const char BL_ShapeActionActuator::SetPriority_doc[] = PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setPriority()", "the priority property"); int priority; if (PyArg_ParseTuple(args,"i",&priority)) @@ -727,6 +795,7 @@ const char BL_ShapeActionActuator::GetFrameProperty_doc[] = "\tReturns the name of the property, that is set to the current frame number.\n"; PyObject* BL_ShapeActionActuator::PyGetFrameProperty(PyObject* self) { + ShowDeprecationWarning("getFrameProperty()", "the frameProperty property"); PyObject *result; result = Py_BuildValue("s", (const char *)m_framepropname); @@ -743,6 +812,7 @@ const char BL_ShapeActionActuator::SetFrame_doc[] = PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrame()", "the frame property"); float frame; if (PyArg_ParseTuple(args,"f",&frame)) @@ -769,6 +839,7 @@ const char BL_ShapeActionActuator::SetProperty_doc[] = PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setProperty()", "the property property"); char *string; if (PyArg_ParseTuple(args,"s",&string)) @@ -790,6 +861,7 @@ const char BL_ShapeActionActuator::SetFrameProperty_doc[] = PyObject* BL_ShapeActionActuator::PySetFrameProperty(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setFrameProperty()", "the frameProperty property"); char *string; if (PyArg_ParseTuple(args,"s",&string)) @@ -808,6 +880,7 @@ const char BL_ShapeActionActuator::GetType_doc[] = "getType()\n" "\tReturns the operation mode of the actuator.\n"; PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) { + ShowDeprecationWarning("getType()", "the type property"); return Py_BuildValue("h", m_playtype); } @@ -819,6 +892,7 @@ const char BL_ShapeActionActuator::SetType_doc[] = PyObject* BL_ShapeActionActuator::PySetType(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setType()", "the type property"); short typeArg; if (!PyArg_ParseTuple(args, "h", &typeArg)) { diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index 30b2d41fc67..b521c0d98a6 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -32,6 +32,7 @@ #include "GEN_HashedPtr.h" #include "SCA_IActuator.h" +#include "BL_ActionActuator.h" #include "MT_Point3.h" #include @@ -103,6 +104,45 @@ public: KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType); virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject* value); + + static int CheckBlendTime(void *self, const PyAttributeDef*) + { + BL_ShapeActionActuator* act = reinterpret_cast(self); + + if (act->m_blendframe > act->m_blendin) + act->m_blendframe = act->m_blendin; + + return 0; + } + static int CheckFrame(void *self, const PyAttributeDef*) + { + BL_ShapeActionActuator* act = reinterpret_cast(self); + + if (act->m_localtime < act->m_startframe) + act->m_localtime = act->m_startframe; + else if (act->m_localtime > act->m_endframe) + act->m_localtime = act->m_endframe; + + return 0; + } + static int CheckType(void *self, const PyAttributeDef*) + { + BL_ShapeActionActuator* act = reinterpret_cast(self); + + switch (act->m_playtype) { + case ACT_ACTION_PLAY: + case ACT_ACTION_FLIPPER: + case ACT_ACTION_LOOP_STOP: + case ACT_ACTION_LOOP_END: + case ACT_ACTION_FROM_PROP: + return 0; + default: + PyErr_SetString(PyExc_ValueError, "invalid type supplied"); + return 1; + } + + } protected: diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 0032d83c2ff..13f141dec13 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -963,11 +963,11 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP, KX_SoundActuator::KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP); /* 7. Action actuator */ - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_PLAY, BL_ActionActuator::KX_ACT_ACTION_PLAY); - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_FLIPPER, BL_ActionActuator::KX_ACT_ACTION_FLIPPER); - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_LOOPSTOP, BL_ActionActuator::KX_ACT_ACTION_LOOPSTOP); - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_LOOPEND, BL_ActionActuator::KX_ACT_ACTION_LOOPEND); - KX_MACRO_addTypesToDict(d, KX_ACTIONACT_PROPERTY, BL_ActionActuator::KX_ACT_ACTION_PROPERTY); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_PLAY, ACT_ACTION_PLAY); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_FLIPPER, ACT_ACTION_FLIPPER); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_LOOPSTOP, ACT_ACTION_LOOP_STOP); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_LOOPEND, ACT_ACTION_LOOP_END); + KX_MACRO_addTypesToDict(d, KX_ACTIONACT_PROPERTY, ACT_ACTION_FROM_PROP); /*8. GL_BlendFunc */ KX_MACRO_addTypesToDict(d, BL_ZERO, GL_ZERO); diff --git a/source/gameengine/PyDoc/BL_ActionActuator.py b/source/gameengine/PyDoc/BL_ActionActuator.py index 5d6ea51060b..3e95befe16b 100644 --- a/source/gameengine/PyDoc/BL_ActionActuator.py +++ b/source/gameengine/PyDoc/BL_ActionActuator.py @@ -23,7 +23,7 @@ class BL_ActionActuator(SCA_IActuator): @ivar property: Sets the property to be used in FromProp playback mode. @type property: string @ivar blendTime: Sets the internal frame timer. This property must be in - the range from 0.0 to 1.0. + the range from 0.0 to blendin. @type blendTime: float @ivar type: The operation mode of the actuator. KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, @@ -50,6 +50,7 @@ class BL_ActionActuator(SCA_IActuator): #--The following methods are deprecated-- def setAction(action, reset = True): """ + DEPRECATED: use the 'action' property Sets the current action. @param action: The name of the action to set as the current action. @@ -63,6 +64,7 @@ class BL_ActionActuator(SCA_IActuator): def setStart(start): """ + DEPRECATED: use the 'start' property Specifies the starting frame of the animation. @param start: the starting frame of the animation @@ -71,6 +73,7 @@ class BL_ActionActuator(SCA_IActuator): def setEnd(end): """ + DEPRECATED: use the 'end' property Specifies the ending frame of the animation. @param end: the ending frame of the animation @@ -78,6 +81,7 @@ class BL_ActionActuator(SCA_IActuator): """ def setBlendin(blendin): """ + DEPRECATED: use the 'blendin' property Specifies the number of frames of animation to generate when making transitions between actions. @@ -87,6 +91,7 @@ class BL_ActionActuator(SCA_IActuator): def setPriority(priority): """ + DEPRECATED: use the 'priority' property Sets the priority of this actuator. @param priority: Specifies the new priority. Actuators will lower @@ -96,6 +101,7 @@ class BL_ActionActuator(SCA_IActuator): """ def setFrame(frame): """ + DEPRECATED: use the 'frame' property Sets the current frame for the animation. @param frame: Specifies the new current frame for the animation @@ -104,6 +110,7 @@ class BL_ActionActuator(SCA_IActuator): def setProperty(prop): """ + DEPRECATED: use the 'property' property Sets the property to be used in FromProp playback mode. @param prop: the name of the property to use. @@ -112,6 +119,7 @@ class BL_ActionActuator(SCA_IActuator): def setBlendtime(blendtime): """ + DEPRECATED: use the 'blendTime' property Sets the internal frame timer. Allows the script to directly modify the internal timer @@ -123,6 +131,7 @@ class BL_ActionActuator(SCA_IActuator): def setType(mode): """ + DEPRECATED: use the 'type' property Sets the operation mode of the actuator @param mode: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND @@ -131,6 +140,7 @@ class BL_ActionActuator(SCA_IActuator): def setContinue(cont): """ + DEPRECATED: use the 'continue' property Set the actions continue option True or False. see getContinue. @param cont: The continue option. @@ -139,6 +149,7 @@ class BL_ActionActuator(SCA_IActuator): def getType(): """ + DEPRECATED: use the 'type' property Returns the operation mode of the actuator @rtype: integer @@ -147,6 +158,7 @@ class BL_ActionActuator(SCA_IActuator): def getContinue(): """ + DEPRECATED: use the 'continue' property When True, the action will always play from where last left off, otherwise negative events to this actuator will reset it to its start frame. @rtype: bool @@ -154,6 +166,7 @@ class BL_ActionActuator(SCA_IActuator): def getAction(): """ + DEPRECATED: use the 'action' property getAction() returns the name of the action associated with this actuator. @rtype: string @@ -161,24 +174,28 @@ class BL_ActionActuator(SCA_IActuator): def getStart(): """ + DEPRECATED: use the 'start' property Returns the starting frame of the action. @rtype: float """ def getEnd(): """ + DEPRECATED: use the 'end' property Returns the last frame of the action. @rtype: float """ def getBlendin(): """ + DEPRECATED: use the 'blendin' property Returns the number of interpolation animation frames to be generated when this actuator is triggered. @rtype: float """ def getPriority(): """ + DEPRECATED: use the 'priority' property Returns the priority for this actuator. Actuators with lower Priority numbers will override actuators with higher numbers. @@ -186,23 +203,27 @@ class BL_ActionActuator(SCA_IActuator): """ def getFrame(): """ + DEPRECATED: use the 'frame' property Returns the current frame number. @rtype: float """ def getProperty(): """ + DEPRECATED: use the 'property' property Returns the name of the property to be used in FromProp mode. @rtype: string """ def setFrameProperty(prop): """ + DEPRECATED: use the 'frameProperty' property @param prop: A string specifying the property of the object that will be updated with the action frame number. @type prop: string """ def getFrameProperty(): """ + DEPRECATED: use the 'frameProperty' property Returns the name of the property that is set to the current frame number. @rtype: string diff --git a/source/gameengine/PyDoc/BL_ShapeActionActuator.py b/source/gameengine/PyDoc/BL_ShapeActionActuator.py index a26b276a2da..209ff4e5580 100644 --- a/source/gameengine/PyDoc/BL_ShapeActionActuator.py +++ b/source/gameengine/PyDoc/BL_ShapeActionActuator.py @@ -4,10 +4,38 @@ from SCA_IActuator import * class BL_ShapeActionActuator(SCA_IActuator): """ - ShapeAction Actuators apply an shape action to an mesh object. + ShapeAction Actuators apply an shape action to an mesh object.\ + + @ivar action: The name of the action to set as the current shape action. + @type action: string + @ivar start: Specifies the starting frame of the shape animation. + @type start: float + @type end: Specifies the ending frame of the shape animation. + @type end: float + @ivar blendin: Specifies the number of frames of animation to generate when making transitions between actions. + @type blendin: float + @ivar priority: Sets the priority of this actuator. Actuators will lower + priority numbers will override actuators with higher + numbers. + @type priority: integer + @ivar frame: Sets the current frame for the animation. + @type frame: float + @ivar property: Sets the property to be used in FromProp playback mode. + @type property: string + @ivar blendTime: Sets the internal frame timer. This property must be in + the range from 0.0 to blendin. + @type blendTime: float + @ivar type: The operation mode of the actuator. + KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, + KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + @type type: integer + @ivar frameProperty: The name of the property that is set to the current frame number. + @type frameProperty: string + """ def setAction(action, reset = True): """ + DEPRECATED: use the 'action' property Sets the current action. @param action: The name of the action to set as the current action. @@ -21,6 +49,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setStart(start): """ + DEPRECATED: use the 'start' property Specifies the starting frame of the animation. @param start: the starting frame of the animation @@ -29,6 +58,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setEnd(end): """ + DEPRECATED: use the 'end' property Specifies the ending frame of the animation. @param end: the ending frame of the animation @@ -36,6 +66,7 @@ class BL_ShapeActionActuator(SCA_IActuator): """ def setBlendin(blendin): """ + DEPRECATED: use the 'blendin' property Specifies the number of frames of animation to generate when making transitions between actions. @@ -45,6 +76,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setPriority(priority): """ + DEPRECATED: use the 'priority' property Sets the priority of this actuator. @param priority: Specifies the new priority. Actuators will lower @@ -54,6 +86,7 @@ class BL_ShapeActionActuator(SCA_IActuator): """ def setFrame(frame): """ + DEPRECATED: use the 'frame' property Sets the current frame for the animation. @param frame: Specifies the new current frame for the animation @@ -62,6 +95,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setProperty(prop): """ + DEPRECATED: use the 'property' property Sets the property to be used in FromProp playback mode. @param prop: the name of the property to use. @@ -70,6 +104,7 @@ class BL_ShapeActionActuator(SCA_IActuator): def setBlendtime(blendtime): """ + DEPRECATED: use the 'blendTime' property Sets the internal frame timer. Allows the script to directly modify the internal timer @@ -81,37 +116,25 @@ class BL_ShapeActionActuator(SCA_IActuator): def setType(mode): """ + DEPRECATED: use the 'type' property Sets the operation mode of the actuator @param mode: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND @type mode: integer """ - def setContinue(cont): - """ - Set the actions continue option True or False. see getContinue. - - @param cont: The continue option. - @type cont: bool - """ - def getType(): """ + DEPRECATED: use the 'type' property Returns the operation mode of the actuator @rtype: integer @return: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND """ - def getContinue(): - """ - When True, the action will always play from where last left off, otherwise negative events to this actuator will reset it to its start frame. - - @rtype: bool - """ - def getAction(): """ + DEPRECATED: use the 'action' property getAction() returns the name of the action associated with this actuator. @rtype: string @@ -119,24 +142,28 @@ class BL_ShapeActionActuator(SCA_IActuator): def getStart(): """ + DEPRECATED: use the 'start' property Returns the starting frame of the action. @rtype: float """ def getEnd(): """ + DEPRECATED: use the 'end' property Returns the last frame of the action. @rtype: float """ def getBlendin(): """ + DEPRECATED: use the 'blendin' property Returns the number of interpolation animation frames to be generated when this actuator is triggered. @rtype: float """ def getPriority(): """ + DEPRECATED: use the 'priority' property Returns the priority for this actuator. Actuators with lower Priority numbers will override actuators with higher numbers. @@ -144,23 +171,27 @@ class BL_ShapeActionActuator(SCA_IActuator): """ def getFrame(): """ + DEPRECATED: use the 'frame' property Returns the current frame number. @rtype: float """ def getProperty(): """ + DEPRECATED: use the 'property' property Returns the name of the property to be used in FromProp mode. @rtype: string """ def setFrameProperty(prop): """ + DEPRECATED: use the 'frameProperty' property @param prop: A string specifying the property of the object that will be updated with the action frame number. @type prop: string """ def getFrameProperty(): """ + DEPRECATED: use the 'frameProperty' property Returns the name of the property that is set to the current frame number. @rtype: string From 55150edc925e7d74398f39d5bf46212200f53324 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 23 Jan 2009 21:08:01 +0000 Subject: [PATCH 137/252] [#18164] jpeg2000 patch, with some fixes from Peter too. Support for jpeg2000 and writing DCI Cinema standard files. Notes * 12 and 16bit channel depths are converted from/to blenders float buffer. * Grayscale/RGB with alpha supported. * Theres an option to save color channels as YCC rather then RGB. * Quality 100 saves lossless * The UI is a bit weired because of the DCI standards need to be given to the encoder. --- config/irix6-config.py | 2 +- config/linux2-config.py | 2 +- config/win32-vc-config.py | 4 ++ source/blender/blenkernel/SConscript | 3 ++ source/blender/blenkernel/intern/image.c | 36 +++++++++++++++ source/blender/blenpluginapi/iff.h | 5 +++ source/blender/imbuf/IMB_imbuf_types.h | 10 +++++ source/blender/imbuf/intern/readimage.c | 11 ++++- source/blender/imbuf/intern/util.c | 16 ++++++- source/blender/imbuf/intern/writeimage.c | 8 ++++ source/blender/makesdna/DNA_scene_types.h | 12 +++++ source/blender/src/SConscript | 3 ++ source/blender/src/buttons_scene.c | 53 ++++++++++++++++++++++- source/blender/src/filelist.c | 7 +++ source/blender/src/writeimage.c | 5 +++ source/creator/creator.c | 3 ++ 16 files changed, 175 insertions(+), 5 deletions(-) diff --git a/config/irix6-config.py b/config/irix6-config.py index 2485c02e095..81a301fbb03 100644 --- a/config/irix6-config.py +++ b/config/irix6-config.py @@ -159,7 +159,7 @@ BF_OGG_LIB = 'ogg vorbis theoraenc theoradec' WITH_BF_OPENJPEG = 'false' BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' -BF_OPENJPEG_INC = '${BF_OPENJPEG}/include' +BF_OPENJPEG_INC = '${BF_OPENJPEG}' BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib' WITH_BF_REDCODE = 'false' diff --git a/config/linux2-config.py b/config/linux2-config.py index a1f979d26da..6ba3052048d 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -157,7 +157,7 @@ BF_OGG_LIB = 'ogg vorbis theoraenc theoradec' WITH_BF_OPENJPEG = True BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' -BF_OPENJPEG_INC = '${BF_OPENJPEG}/include' +BF_OPENJPEG_INC = '${BF_OPENJPEG}' BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib' WITH_BF_REDCODE = False diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index d7165401705..d4e9fa9b30e 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -153,6 +153,10 @@ BF_QUICKTIME_LIB = 'qtmlClient' BF_QUICKTIME_LIBPATH = '${BF_QUICKTIME}/Libraries' WITH_BF_OPENJPEG = True +BF_OPENJPEG = '#extern/libopenjpeg' +BF_OPENJPEG_LIB = '' +BF_OPENJPEG_INC = '${BF_OPENJPEG}' +BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib' WITH_BF_REDCODE = False BF_REDCODE_INC = '#extern' diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 4ab7d4a6792..fb67c855b81 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -42,6 +42,9 @@ if env['WITH_BF_VERSE']: if env['WITH_BF_OPENEXR']: defs += ' WITH_OPENEXR' +if env['WITH_BF_OPENJPEG']: + defs += ' WITH_OPENJPEG' + if env['WITH_BF_DDS']: defs += ' WITH_DDS' diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d5166fc7a83..e817c38618f 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -767,6 +767,10 @@ int BKE_imtype_to_ftype(int imtype) return RAWTGA; else if(imtype==R_HAMX) return AN_hamx; +#ifdef WITH_OPENJPEG + else if(imtype==R_JP2) + return JP2; +#endif else return JPG|90; } @@ -801,6 +805,10 @@ int BKE_ftype_to_imtype(int ftype) return R_RAWTGA; else if(ftype == AN_hamx) return R_HAMX; +#ifdef WITH_OPENJPEG + else if(ftype & JP2) + return R_JP2; +#endif else return R_JPEG90; } @@ -877,6 +885,12 @@ void BKE_add_image_extension(char *string, int imtype) if(!BLI_testextensie(string, ".tga")) extension= ".tga"; } +#ifdef WITH_OPENJPEG + else if(imtype==R_JP2) { + if(!BLI_testextensie(string, ".jp2")) + extension= ".jp2"; + } +#endif else { // R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90, R_QUICKTIME etc if(!( BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg"))) extension= ".jpg"; @@ -1220,6 +1234,28 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali else if(imtype==R_HAMX) { ibuf->ftype= AN_hamx; } +#ifdef WITH_OPENJPEG + else if(imtype==R_JP2) { + if(quality < 10) quality= 90; + ibuf->ftype= JP2|quality; + + if (subimtype & R_JPEG2K_16BIT) { + ibuf->ftype |= JP2_16BIT; + } else if (subimtype & R_JPEG2K_12BIT) { + ibuf->ftype |= JP2_12BIT; + } + + if (subimtype & R_JPEG2K_YCC) { + ibuf->ftype |= JP2_YCC; + } + + if (subimtype & R_JPEG2K_CINE_PRESET) { + ibuf->ftype |= JP2_CINE; + if (subimtype & R_JPEG2K_CINE_48FPS) + ibuf->ftype |= JP2_CINE_48FPS; + } + } +#endif else { /* R_JPEG90, R_MOVIE, etc. default we save jpegs */ if(quality < 10) quality= 90; diff --git a/source/blender/blenpluginapi/iff.h b/source/blender/blenpluginapi/iff.h index 92cbd7dd093..e7f328d870f 100644 --- a/source/blender/blenpluginapi/iff.h +++ b/source/blender/blenpluginapi/iff.h @@ -56,6 +56,10 @@ #endif #define RADHDR (1<<24) +#ifdef WITH_OPENJPEG +#define JP2 (1 << 18) +#endif + #define RAWTGA (TGA | 1) #define JPG_STD (JPG | (0 << 8)) @@ -113,6 +117,7 @@ #define IS_tim(x) (x->ftype & TIM) #define IS_tiff(x) (x->ftype & TIFF) #define IS_openexr(x) (x->ftype & OPENEXR) +#define IS_jp2(x) (x->ftype & JP2) #define IMAGIC 0732 diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 73ef83393b0..eadd7affe6a 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -181,6 +181,15 @@ typedef enum { #define DDS (1 << 19) #endif +#ifdef WITH_OPENJPEG +#define JP2 (1 << 18) +#define JP2_12BIT (1 << 17) +#define JP2_16BIT (1 << 16) +#define JP2_YCC (1 << 15) +#define JP2_CINE (1 << 14) +#define JP2_CINE_48FPS (1 << 13) +#endif + #define RAWTGA (TGA | 1) #define JPG_STD (JPG | (0 << 8)) @@ -217,6 +226,7 @@ typedef enum { #define IS_tga(x) (x->ftype & TGA) #define IS_png(x) (x->ftype & PNG) #define IS_openexr(x) (x->ftype & OPENEXR) +#define IS_jp2(x) (x->ftype & JP2) #define IS_cineon(x) (x->ftype & CINEON) #define IS_dpx(x) (x->ftype & DPX) #define IS_bmp(x) (x->ftype & BMP) diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 05e7921665b..6df92f69fff 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -58,6 +58,10 @@ #include "IMB_dpxcineon.h" #include "BKE_global.h" +#ifdef WITH_OPENJPEG +#include "IMB_jp2.h" +#endif + #ifdef WITH_OPENEXR #include "openexr/openexr_api.h" #endif @@ -161,11 +165,16 @@ ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags) { if (ibuf) return (ibuf); #endif +#ifdef WITH_OPENJPEG + ibuf = imb_jp2_decode((uchar *)mem, size, flags); + if (ibuf) return (ibuf); +#endif + #ifdef WITH_DDS ibuf = imb_load_dds((uchar *)mem, size, flags); if (ibuf) return (ibuf); #endif - + #ifdef WITH_QUICKTIME #if defined(_WIN32) || defined (__APPLE__) if(G.have_quicktime) { diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index cf8c0978c66..15d1d031dbd 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -68,6 +68,10 @@ #include "quicktime_import.h" #endif +#ifdef WITH_OPENJPEG +#include "IMB_jp2.h" +#endif + #ifdef WITH_FFMPEG #include #include @@ -140,7 +144,11 @@ static int IMB_ispic_name(char *name) /* if (imb_is_a_bmp(buf)) return(BMP); */ - + +#ifdef WITH_OPENJPEG + if (imb_is_a_jp2(buf)) return(JP2); +#endif + #ifdef WITH_QUICKTIME #if defined(_WIN32) || defined(__APPLE__) if(G.have_quicktime) { @@ -190,6 +198,9 @@ int IMB_ispic(char *filename) || BLI_testextensie(filename, ".cin") #ifdef WITH_BF_OPENEXR || BLI_testextensie(filename, ".exr") +#endif +#ifdef WITH_BF_OPENJPEG + || BLI_testextensie(filename, ".jp2") #endif || BLI_testextensie(filename, ".sgi")) { return IMB_ispic_name(filename); @@ -210,6 +221,9 @@ int IMB_ispic(char *filename) #endif #ifdef WITH_BF_OPENEXR || BLI_testextensie(filename, ".exr") +#endif +#ifdef WITH_BF_OPENJPEG + || BLI_testextensie(filename, ".jp2") #endif || BLI_testextensie(filename, ".iff") || BLI_testextensie(filename, ".lbm") diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index 5a4f83a473b..5df0595d97f 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -55,6 +55,9 @@ #include "IMB_bmp.h" #include "IMB_tiff.h" #include "IMB_radiance_hdr.h" +#ifdef WITH_OPENJPEG +#include "IMB_jp2.h" +#endif #ifdef WITH_OPENEXR #include "openexr/openexr_api.h" #endif @@ -129,6 +132,11 @@ short IMB_saveiff(struct ImBuf *ibuf, char *name, int flags) if (IS_dpx(ibuf)) { return imb_save_dpx(ibuf, name, flags); } +#ifdef WITH_OPENJPEG + if (IS_jp2(ibuf)) { + return imb_savejp2(ibuf, name, flags); + } +#endif file = open(name, O_BINARY | O_RDWR | O_CREAT | O_TRUNC, 0666); if (file < 0) return (FALSE); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index f92311312fa..09c2344d53a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -310,6 +310,10 @@ typedef struct RenderData { /* cineon */ short cineonwhite, cineonblack; float cineongamma; + + /* jpeg2000 */ + short jp2_preset, jp2_depth; + int rpad3; } RenderData; /* control render convert and shading engine */ @@ -692,6 +696,7 @@ typedef struct Scene { #define R_DPX 27 #define R_MULTILAYER 28 #define R_DDS 29 +#define R_JP2 30 /* subimtype, flag options for imtype */ #define R_OPENEXR_HALF 1 @@ -700,6 +705,13 @@ typedef struct Scene { #define R_CINEON_LOG 8 #define R_TIFF_16BIT 16 +#define R_JPEG2K_12BIT 32 /* Jpeg2000 */ +#define R_JPEG2K_16BIT 64 +#define R_JPEG2K_YCC 128 /* when disabled use RGB */ +#define R_JPEG2K_CINE_PRESET 256 +#define R_JPEG2K_CINE_48FPS 512 + + /* bake_mode: same as RE_BAKE_xxx defines */ /* bake_flag: */ #define R_BAKE_CLEAR 1 diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index 451afc9b244..384ad1b1bf2 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -53,6 +53,9 @@ if env['WITH_BF_INTERNATIONAL']: if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') +if env['WITH_BF_OPENJPEG']: + defs.append('WITH_OPENJPEG') + if env['WITH_BF_DDS']: defs.append('WITH_DDS') diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index ea7411af621..376a57b11e9 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -1956,7 +1956,6 @@ static char *imagetype_pup(void) char appendstring[1024]; strcpy(formatstring, "Save image as: %%t|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d"); - #ifdef __sgi strcat(formatstring, "|%s %%x%d"); // add space for Movie #endif @@ -1967,6 +1966,10 @@ static char *imagetype_pup(void) strcat(formatstring, "|%s %%x%d"); // add space for DDS #endif */ +#ifdef WITH_OPENJPEG + strcat(formatstring, "|%s %%x%d"); // add space for JP2 +#endif + strcat(formatstring, "|%s %%x%d"); // add space for BMP strcat(formatstring, "|%s %%x%d"); // add space for Radiance HDR strcat(formatstring, "|%s %%x%d"); // add space for Cineon @@ -2008,6 +2011,9 @@ static char *imagetype_pup(void) "DDS", R_DDS, #endif */ +#ifdef WITH_OPENJPEG + "Jpeg 2000", R_JP2, +#endif "BMP", R_BMP, "Jpeg", R_JPEG90, "HamX", R_HAMX, @@ -2015,6 +2021,7 @@ static char *imagetype_pup(void) "Radiance HDR", R_RADHDR, "Cineon", R_CINEON, "DPX", R_DPX + #ifdef __sgi ,"Movie", R_MOVIE #endif @@ -2036,6 +2043,9 @@ static char *imagetype_pup(void) /*#ifdef WITH_DDS "DDS", R_DDS, #endif*/ +#ifdef WITH_OPENJPEG + "Jpeg 2000", R_JP2, +#endif "BMP", R_BMP, "Jpeg", R_JPEG90, "HamX", R_HAMX, @@ -2043,6 +2053,8 @@ static char *imagetype_pup(void) "Radiance HDR", R_RADHDR, "Cineon", R_CINEON, "DPX", R_DPX + + #ifdef __sgi ,"Movie", R_MOVIE #endif @@ -3152,6 +3164,45 @@ static void render_panel_format(void) uiDefButS(block, NUM,B_DIFF, "Q:", 892,yofs,74,20, &G.scene->r.quality, 10.0, 100.0, 0, 0, "Quality setting for JPEG images, AVI Jpeg and SGI movies"); } + +#ifdef WITH_OPENJPEG + if (G.scene->r.imtype == R_JP2) { + + uiDefButS(block, MENU,B_REDR, + "Preset %t|No Preset %x0|" + "Cinema 24fps 2048x1080%x1|" + "Cinema 48fps 2048x1080%x2|" + "Cinema 24fps 4096x2160%x3|" + "Cine-Scope 24fps 2048x858%x4|" + "Cine-Scope 48fps 2048x858%x5|" + "Cine-Flat 24fps 1998x1080%x6|" + "Cine-Flat 48fps 1998x1080%x7", + 892,yofs+44,G.scene->r.jp2_preset?227:110,20, &G.scene->r.jp2_preset, 0, 0, 0, 0, "Use a DCI Standard preset for saving jpeg2000"); + + if (G.scene->r.jp2_preset==0) { + uiBlockBeginAlign(block); + uiDefButS(block, ROW,B_REDR,"8", 1007,yofs+44,20,20, &G.scene->r.jp2_depth,1.0,8.0, 0, 0,""); + uiDefButS(block, ROW,B_REDR,"12",1007+20,yofs+44,25,20, &G.scene->r.jp2_depth,1.0,12.0, 0, 0,""); + uiDefButS(block, ROW,B_REDR,"16", 1007+45,yofs+44,25,20, &G.scene->r.jp2_depth,1.0,16.0, 0, 0,""); + uiDefButBitS(block, TOG, R_JPEG2K_YCC, B_REDR,"YCC",1007+70,yofs+44,42,20, &G.scene->r.subimtype, 0, 0, 0, 0, "Save luminance-chrominance-chrominance instead of RGB color channels "); + uiBlockEndAlign(block); + } + + G.scene->r.subimtype &= ~(R_JPEG2K_12BIT|R_JPEG2K_16BIT | R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS); + if (G.scene->r.jp2_depth==12) G.scene->r.subimtype |= R_JPEG2K_12BIT; + if (G.scene->r.jp2_depth==16) G.scene->r.subimtype |= R_JPEG2K_16BIT; + + if (G.scene->r.jp2_preset==1) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET; + if (G.scene->r.jp2_preset==2) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; + if (G.scene->r.jp2_preset==3) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET; + if (G.scene->r.jp2_preset==4) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET; + if (G.scene->r.jp2_preset==5) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; + if (G.scene->r.jp2_preset==6) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET; + if (G.scene->r.jp2_preset==7) G.scene->r.subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; + + } +#endif + uiDefButS(block, NUM,B_FRAMEMAP,"FPS:", 968,yofs,75,20, &G.scene->r.frs_sec, 1.0, 120.0, 100.0, 0, "Frames per second"); uiDefButF(block, NUM,B_FRAMEMAP,"/", 1043,yofs,75,20, &G.scene->r.frs_sec_base, 1.0, 120.0, 0.1, 3, "Frames per second base"); diff --git a/source/blender/src/filelist.c b/source/blender/src/filelist.c index c2c0f00885f..008bcbe147d 100644 --- a/source/blender/src/filelist.c +++ b/source/blender/src/filelist.c @@ -678,6 +678,9 @@ void BIF_filelist_setfiletypes(struct FileList* filelist, short has_quicktime) if( BLI_testextensie(file->relname, ".int") || BLI_testextensie(file->relname, ".inta") || BLI_testextensie(file->relname, ".jpg") +#ifdef WITH_OPENJPEG + || BLI_testextensie(file->relname, ".jp2") +#endif || BLI_testextensie(file->relname, ".jpeg") || BLI_testextensie(file->relname, ".tga") || BLI_testextensie(file->relname, ".rgb") @@ -721,6 +724,10 @@ void BIF_filelist_setfiletypes(struct FileList* filelist, short has_quicktime) if(BLI_testextensie(file->relname, ".int") || BLI_testextensie(file->relname, ".inta") || BLI_testextensie(file->relname, ".jpg") + || BLI_testextensie(file->relname, ".jpeg") +#ifdef WITH_OPENJPEG + || BLI_testextensie(file->relname, ".jp2") +#endif || BLI_testextensie(file->relname, ".tga") || BLI_testextensie(file->relname, ".rgb") || BLI_testextensie(file->relname, ".rgba") diff --git a/source/blender/src/writeimage.c b/source/blender/src/writeimage.c index b21c14bed35..a611353026e 100644 --- a/source/blender/src/writeimage.c +++ b/source/blender/src/writeimage.c @@ -190,6 +190,11 @@ void save_image_filesel_str(char *str) case R_MULTILAYER: strcpy(str, "Save Multi Layer EXR"); break; +#ifdef WITH_OPENJPEG + case R_JP2: + strcpy(str, "Save JPEG2000"); + break; +#endif /* default we save jpeg, also for all movie formats */ case R_JPEG90: case R_MOVIE: diff --git a/source/creator/creator.c b/source/creator/creator.c index 9d6841c3708..5c0ca9e07ff 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -776,6 +776,9 @@ int main(int argc, char **argv) else if (!strcmp(argv[a],"FRAMESERVER")) G.scene->r.imtype = R_FRAMESERVER; else if (!strcmp(argv[a],"CINEON")) G.scene->r.imtype = R_CINEON; else if (!strcmp(argv[a],"DPX")) G.scene->r.imtype = R_DPX; +#if WITH_OPENJPEG + else if (!strcmp(argv[a],"JP2")) G.scene->r.imtype = R_JP2; +#endif else printf("\nError: Format from '-F' not known or not compiled in this release.\n"); } } else { From fc7af897b79727d13f959dd9418aa196288785e9 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 23 Jan 2009 21:34:51 +0000 Subject: [PATCH 138/252] Prevent overdrawing to trigger when starting a stroke by snapping to an existing point. Overdrawing copies point type from start and end point (better for polyline) misc renaming some structs and vars (cleanup mostly) --- source/blender/src/editarmature_sketch.c | 101 +++++++++++------------ 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 5830b2286f6..b73e2f64879 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -92,14 +92,14 @@ typedef struct SK_Stroke int selected; } SK_Stroke; -#define SK_ADJUST_LIMIT 5 +#define SK_OVERDRAW_LIMIT 5 -typedef struct SK_Adjustment +typedef struct SK_Overdraw { SK_Stroke *target; int start, end; int count; -} SK_Adjustment; +} SK_Overdraw; #define SK_Stroke_BUFFER_INIT_SIZE 20 @@ -127,7 +127,7 @@ typedef struct SK_Sketch SK_Stroke *active_stroke; SK_Stroke *gesture; SK_Point next_point; - SK_Adjustment adj; + SK_Overdraw over; } SK_Sketch; typedef struct SK_StrokeIterator { @@ -203,8 +203,8 @@ int sk_detectConvertGesture(SK_Gesture *gest, SK_Sketch *sketch); void sk_applyConvertGesture(SK_Gesture *gest, SK_Sketch *sketch); -void sk_resetAdjust(SK_Sketch *sketch); -int sk_hasAdjust(SK_Sketch *sketch, SK_Stroke *stk); +void sk_resetOverdraw(SK_Sketch *sketch); +int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk); /******************** GESTURE ACTIONS ******************************/ @@ -1065,7 +1065,7 @@ void sk_cancelStroke(SK_Sketch *sketch) { if (sketch->active_stroke != NULL) { - sk_resetAdjust(sketch); + sk_resetOverdraw(sketch); sk_removeStroke(sketch, sketch->active_stroke); } } @@ -1407,30 +1407,36 @@ SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int return pt; } -void sk_resetAdjust(SK_Sketch *sketch) +void sk_resetOverdraw(SK_Sketch *sketch) { - sketch->adj.target = NULL; - sketch->adj.start = -1; - sketch->adj.end = -1; - sketch->adj.count = 0; + sketch->over.target = NULL; + sketch->over.start = -1; + sketch->over.end = -1; + sketch->over.count = 0; } -int sk_hasAdjust(SK_Sketch *sketch, SK_Stroke *stk) +int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk) { - return sketch->adj.target && - sketch->adj.count >= SK_ADJUST_LIMIT && - (sketch->adj.target == stk || stk == NULL) && - (sketch->adj.start != -1 || sketch->adj.end != -1); + return sketch->over.target && + sketch->over.count >= SK_OVERDRAW_LIMIT && + (sketch->over.target == stk || stk == NULL) && + (sketch->over.start != -1 || sketch->over.end != -1); } -void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) +void sk_updateOverdraw(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { - if (sketch->adj.target == NULL) + if (sketch->over.target == NULL) { SK_Stroke *target; int closest_index = -1; int dist = SNAP_MIN_DISTANCE * 2; + /* If snapping, don't start overdraw */ + if (sk_lastStrokePoint(stk)->mode == PT_SNAP) + { + return; + } + for (target = sketch->strokes.first; target; target = target->next) { if (target != stk) @@ -1441,60 +1447,60 @@ void sk_updateAdjust(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) if (spt != NULL) { - sketch->adj.target = target; + sketch->over.target = target; closest_index = index; } } } - if (sketch->adj.target != NULL) + if (sketch->over.target != NULL) { if (closest_index > -1) { if (sk_lastStrokePoint(stk)->type == PT_EXACT) { - sketch->adj.count = SK_ADJUST_LIMIT; + sketch->over.count = SK_OVERDRAW_LIMIT; } else { - sketch->adj.count++; + sketch->over.count++; } } if (stk->nb_points == 1) { - sketch->adj.start = closest_index; + sketch->over.start = closest_index; } else { - sketch->adj.end = closest_index; + sketch->over.end = closest_index; } } } - else if (sketch->adj.target != NULL) + else if (sketch->over.target != NULL) { SK_Point *closest_pt = NULL; int dist = SNAP_MIN_DISTANCE * 2; int index; - closest_pt = sk_snapPointStroke(sketch->adj.target, dd->mval, &dist, &index); + closest_pt = sk_snapPointStroke(sketch->over.target, dd->mval, &dist, &index); if (closest_pt != NULL) { if (sk_lastStrokePoint(stk)->type == PT_EXACT) { - sketch->adj.count = SK_ADJUST_LIMIT; + sketch->over.count = SK_OVERDRAW_LIMIT; } else { - sketch->adj.count++; + sketch->over.count++; } - sketch->adj.end = index; + sketch->over.end = index; } else { - sketch->adj.end = -1; + sketch->over.end = -1; } } } @@ -1504,8 +1510,8 @@ int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end) { int retval = 0; - *start = sketch->adj.start; - *end = sketch->adj.end; + *start = sketch->over.start; + *end = sketch->over.end; if (*start == -1) { @@ -1514,7 +1520,7 @@ int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end) if (*end == -1) { - *end = sketch->adj.target->nb_points - 1; + *end = sketch->over.target->nb_points - 1; } if (*end < *start) @@ -1528,11 +1534,11 @@ int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end) return retval; } -void sk_endAdjust(SK_Sketch *sketch) +void sk_endOverdraw(SK_Sketch *sketch) { SK_Stroke *stk = sketch->active_stroke; - if (sk_hasAdjust(sketch, NULL)) + if (sk_hasOverdraw(sketch, NULL)) { int start; int end; @@ -1544,22 +1550,15 @@ void sk_endAdjust(SK_Sketch *sketch) if (stk->nb_points > 1) { - if (start != 0) - { - stk->points->type = PT_CONTINUOUS; - } - - if (end != sketch->adj.target->nb_points - 1) - { - sk_lastStrokePoint(stk)->type = PT_CONTINUOUS; - } + stk->points->type = sketch->over.target->points[start].type; + sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type; } - sk_inserStrokePoints(sketch->adj.target, stk->points, stk->nb_points, start, end); + sk_inserStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end); sk_removeStroke(sketch, stk); - sk_resetAdjust(sketch); + sk_resetOverdraw(sketch); } } @@ -1571,7 +1570,7 @@ void sk_startStroke(SK_Sketch *sketch) BLI_addtail(&sketch->strokes, stk); sketch->active_stroke = stk; - sk_resetAdjust(sketch); + sk_resetOverdraw(sketch); } void sk_endStroke(SK_Sketch *sketch) @@ -1580,7 +1579,7 @@ void sk_endStroke(SK_Sketch *sketch) if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST) { - sk_endAdjust(sketch); + sk_endOverdraw(sketch); } sketch->active_stroke = NULL; @@ -1929,7 +1928,7 @@ void sk_addStrokePoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST) { - sk_updateAdjust(sketch, stk, dd); + sk_updateOverdraw(sketch, stk, dd); } } @@ -2953,7 +2952,7 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) int start = -1; int end = -1; - if (sk_hasAdjust(sketch, stk)) + if (sk_hasOverdraw(sketch, stk)) { sk_adjustIndexes(sketch, &start, &end); } From 10e39a23311d392e916b02ed9f551d8eee214047 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 24 Jan 2009 10:19:29 +0000 Subject: [PATCH 139/252] jpeg2000 commit missed the 2 most important files. --- source/blender/imbuf/intern/IMB_jp2.h | 49 ++ source/blender/imbuf/intern/jp2.c | 736 ++++++++++++++++++++++++++ 2 files changed, 785 insertions(+) create mode 100644 source/blender/imbuf/intern/IMB_jp2.h create mode 100644 source/blender/imbuf/intern/jp2.c diff --git a/source/blender/imbuf/intern/IMB_jp2.h b/source/blender/imbuf/intern/IMB_jp2.h new file mode 100644 index 00000000000..fcdd4589fca --- /dev/null +++ b/source/blender/imbuf/intern/IMB_jp2.h @@ -0,0 +1,49 @@ +/* + * IMB_jp2.h + * + * $Id: IMB_bmp.h 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) 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 ***** + */ +/** + * \file IMB_jp2.h + * \ingroup imbuf + * \brief Function declarations for jp2.c + */ + +#ifndef IMB_JP2_H +#define IMB_JP2_H + +#ifdef WITH_OPENJPEG +struct ImBuf; + +int imb_is_a_jp2(void *buf); +struct ImBuf *imb_jp2_decode(unsigned char *mem, int size, int flags); +short imb_savejp2(struct ImBuf *ibuf, char *name, int flags); +#endif /* WITH_OPENJPEG */ + +#endif + diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c new file mode 100644 index 00000000000..6217cd6bea2 --- /dev/null +++ b/source/blender/imbuf/intern/jp2.c @@ -0,0 +1,736 @@ +/** + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifdef WITH_OPENJPEG + +#include "BLI_blenlib.h" + +#include "imbuf.h" +#include "imbuf_patch.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_allocimbuf.h" +#include "IMB_jp2.h" + +#include "openjpeg.h" + +#define JP2_FILEHEADER_SIZE 14 + +static char JP2_HEAD[]= {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A}; + +/* We only need this because of how the presets are set */ +typedef struct img_folder{ + /** The directory path of the folder containing input images*/ + char *imgdirpath; + /** Output format*/ + char *out_format; + /** Enable option*/ + char set_imgdir; + /** Enable Cod Format for output*/ + char set_out_format; + /** User specified rate stored in case of cinema option*/ + float *rates; +}img_fol_t; + +static int checkj2p(unsigned char *mem) /* J2K_CFMT */ +{ + return memcmp(JP2_HEAD, mem, 12) ? 0 : 1; +} + +int imb_is_a_jp2(void *buf) +{ + return checkj2p(buf); +} + + +/** +sample error callback expecting a FILE* client object +*/ +void error_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[ERROR] %s", msg); +} +/** +sample warning callback expecting a FILE* client object +*/ +void warning_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[WARNING] %s", msg); +} +/** +sample debug callback expecting no client object +*/ +void info_callback(const char *msg, void *client_data) { + (void)client_data; + fprintf(stdout, "[INFO] %s", msg); +} + + + +struct ImBuf *imb_jp2_decode(unsigned char *mem, int size, int flags) +{ + struct ImBuf *ibuf = 0; + int use_float = 0; /* for precissions higher then 8 use float */ + unsigned char *rect= NULL; + float *rect_float= NULL; + + long signed_offsets[4] = {0,0,0,0}; + int float_divs[4]; + + int index; + + int w, h, depth; + + opj_dparameters_t parameters; /* decompression parameters */ + + opj_event_mgr_t event_mgr; /* event manager */ + opj_image_t *image = NULL; + + int i; + + opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ + opj_cio_t *cio = NULL; + + if (checkj2p(mem) == 0) return(0); + + /* configure the event callbacks (not required) */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + + /* set decoding parameters to default values */ + opj_set_default_decoder_parameters(¶meters); + + + /* JPEG 2000 compressed image data */ + + /* get a decoder handle */ + dinfo = opj_create_decompress(CODEC_JP2); + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); + + /* setup the decoder decoding parameters using the current image and user parameters */ + opj_setup_decoder(dinfo, ¶meters); + + /* open a byte stream */ + cio = opj_cio_open((opj_common_ptr)dinfo, mem, size); + + /* decode the stream and fill the image structure */ + image = opj_decode(dinfo, cio); + + if(!image) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); + opj_destroy_decompress(dinfo); + opj_cio_close(cio); + return NULL; + } + + /* close the byte stream */ + opj_cio_close(cio); + + + if((image->numcomps * image->x1 * image->y1) == 0) + { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + return NULL; + } + + w = image->comps[0].w; + h = image->comps[0].h; + + switch (image->numcomps) { + case 1: /* Greyscale */ + case 3: /* Color */ + depth= 24; + break; + default: /* 2 or 4 - Greyscale or Color + alpha */ + depth= 32; /* greyscale + alpha */ + break; + } + + + i = image->numcomps; + if (i>4) i= 4; + + while (i) { + i--; + + if (image->comps[i].prec > 8) + use_float = 1; + + if (image->comps[i].sgnd) + signed_offsets[i]= 1 << (image->comps[i].prec - 1); + + /* only needed for float images but dosnt hurt to calc this */ + float_divs[i]= (1<comps[i].prec)-1; + } + + if (use_float) { + ibuf= IMB_allocImBuf(w, h, depth, IB_rectfloat, 0); + rect_float = ibuf->rect_float; + } else { + ibuf= IMB_allocImBuf(w, h, depth, IB_rect, 0); + rect = (unsigned char *) ibuf->rect; + } + + if (ibuf==NULL) { + if(dinfo) + opj_destroy_decompress(dinfo); + return NULL; + } + + ibuf->ftype = JP2; + + if (use_float) { + rect_float = ibuf->rect_float; + + if (image->numcomps < 3) { + /* greyscale 12bits+ */ + for (i = 0; i < w * h; i++, rect_float+=4) { + index = w * h - ((i) / (w) + 1) * w + (i) % (w); + + rect_float[0]= rect_float[1]= rect_float[2]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0]; + + if (image->numcomps == 2) + rect_float[3]= (image->comps[1].data[index] + signed_offsets[1]) / float_divs[1]; + else + rect_float[3]= 1.0f; + } + } else { + /* rgb or rgba 12bits+ */ + for (i = 0; i < w * h; i++, rect_float+=4) { + index = w * h - ((i) / (w) + 1) * w + (i) % (w); + + rect_float[0]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0]; + rect_float[1]= (float)(image->comps[1].data[index] + signed_offsets[1]) / float_divs[1]; + rect_float[2]= (float)(image->comps[2].data[index] + signed_offsets[2]) / float_divs[2]; + + if (image->numcomps >= 4) + rect_float[3]= (float)(image->comps[2].data[index] + signed_offsets[3]) / float_divs[3]; + else + rect_float[3]= 1.0f; + } + } + + } else { + + if (image->numcomps < 3) { + /* greyscale */ + for (i = 0; i < w * h; i++, rect+=4) { + index = w * h - ((i) / (w) + 1) * w + (i) % (w); + + rect_float[0]= rect_float[1]= rect_float[2]= (image->comps[0].data[index] + signed_offsets[0]); + + if (image->numcomps == 2) + rect[3]= image->comps[1].data[index] + signed_offsets[1]; + else + rect[3]= 255; + } + } else { + /* 8bit rgb or rgba */ + for (i = 0; i < w * h; i++, rect+=4) { + int index = w * h - ((i) / (w) + 1) * w + (i) % (w); + + rect[0]= image->comps[0].data[index] + signed_offsets[0]; + rect[1]= image->comps[1].data[index] + signed_offsets[1]; + rect[2]= image->comps[2].data[index] + signed_offsets[2]; + + if (image->numcomps >= 4) + rect[3]= image->comps[2].data[index] + signed_offsets[3]; + else + rect[3]= 255; + } + } + } + + /* free remaining structures */ + if(dinfo) { + opj_destroy_decompress(dinfo); + } + + /* free image data structure */ + opj_image_destroy(image); + + if (flags & IB_rect) { + IMB_rect_from_float(ibuf); + } + + return(ibuf); +} + +//static opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp) { +/* prec can be 8, 12, 16 */ + +#define UPSAMPLE_8_TO_12(_val) ((_val<<4) | (_val & ((1<<4)-1))) +#define UPSAMPLE_8_TO_16(_val) ((_val<<8)+_val) + +#define DOWNSAMPLE_FLOAT_TO_8BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?255: (int)(255.0f*(_val))) +#define DOWNSAMPLE_FLOAT_TO_12BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?4095: (int)(4095.0f*(_val))) +#define DOWNSAMPLE_FLOAT_TO_16BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?65535: (int)(65535.0f*(_val))) + + +/* +2048x1080 (2K) at 24 fps or 48 fps, or 4096x2160 (4K) at 24 fps; 3×12 bits per pixel, XYZ color space + + * In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the imager is used + * In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the imager is used +*/ + +/* ****************************** COPIED FROM image_to_j2k.c */ + +/* ----------------------------------------------------------------------- */ +#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/ +#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/ +#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/ +#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/ + + +static int initialise_4K_poc(opj_poc_t *POC, int numres){ + POC[0].tile = 1; + POC[0].resno0 = 0; + POC[0].compno0 = 0; + POC[0].layno1 = 1; + POC[0].resno1 = numres-1; + POC[0].compno1 = 3; + POC[0].prg1 = CPRL; + POC[1].tile = 1; + POC[1].resno0 = numres-1; + POC[1].compno0 = 0; + POC[1].layno1 = 1; + POC[1].resno1 = numres; + POC[1].compno1 = 3; + POC[1].prg1 = CPRL; + return 2; +} + +void cinema_parameters(opj_cparameters_t *parameters){ + parameters->tile_size_on = false; + parameters->cp_tdx=1; + parameters->cp_tdy=1; + + /*Tile part*/ + parameters->tp_flag = 'C'; + parameters->tp_on = 1; + + /*Tile and Image shall be at (0,0)*/ + parameters->cp_tx0 = 0; + parameters->cp_ty0 = 0; + parameters->image_offset_x0 = 0; + parameters->image_offset_y0 = 0; + + /*Codeblock size= 32*32*/ + parameters->cblockw_init = 32; + parameters->cblockh_init = 32; + parameters->csty |= 0x01; + + /*The progression order shall be CPRL*/ + parameters->prog_order = CPRL; + + /* No ROI */ + parameters->roi_compno = -1; + + parameters->subsampling_dx = 1; parameters->subsampling_dy = 1; + + /* 9-7 transform */ + parameters->irreversible = 1; + +} + +void cinema_setup_encoder(opj_cparameters_t *parameters,opj_image_t *image, img_fol_t *img_fol){ + int i; + float temp_rate; + + switch (parameters->cp_cinema){ + case CINEMA2K_24: + case CINEMA2K_48: + if(parameters->numresolution > 6){ + parameters->numresolution = 6; + } + if (!((image->comps[0].w == 2048) || (image->comps[0].h == 1080))){ + fprintf(stdout,"Image coordinates %d x %d is not 2K compliant.\nJPEG Digital Cinema Profile-3 " + "(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n", + image->comps[0].w,image->comps[0].h); + parameters->cp_rsiz = STD_RSIZ; + } + break; + + case CINEMA4K_24: + if(parameters->numresolution < 1){ + parameters->numresolution = 1; + }else if(parameters->numresolution > 7){ + parameters->numresolution = 7; + } + if (!((image->comps[0].w == 4096) || (image->comps[0].h == 2160))){ + fprintf(stdout,"Image coordinates %d x %d is not 4K compliant.\nJPEG Digital Cinema Profile-4" + "(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n", + image->comps[0].w,image->comps[0].h); + parameters->cp_rsiz = STD_RSIZ; + } + parameters->numpocs = initialise_4K_poc(parameters->POC,parameters->numresolution); + break; + case OFF: + /* do nothing */ + break; + } + + switch (parameters->cp_cinema){ + case CINEMA2K_24: + case CINEMA4K_24: + for(i=0 ; itcp_numlayers ; i++){ + temp_rate = 0 ; + if (img_fol->rates[i]== 0){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > CINEMA_24_CS ){ + parameters->tcp_rates[i]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + parameters->tcp_rates[i]= img_fol->rates[i]; + } + } + } + parameters->max_comp_size = COMP_24_CS; + break; + + case CINEMA2K_48: + for(i=0 ; itcp_numlayers ; i++){ + temp_rate = 0 ; + if (img_fol->rates[i]== 0){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > CINEMA_48_CS ){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + parameters->tcp_rates[i]= img_fol->rates[i]; + } + } + } + parameters->max_comp_size = COMP_48_CS; + break; + case OFF: + /* do nothing */ + break; + } + parameters->cp_disto_alloc = 1; +} + + +static opj_image_t* ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) { + + unsigned char *rect; + float *rect_float; + + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + + + int i, numcomps, w, h, prec; + int x,y, y_row; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */ + opj_image_t * image = NULL; + + img_fol_t img_fol; /* only needed for cinema presets */ + memset(&img_fol,0,sizeof(img_fol_t)); + + if (ibuf->ftype & JP2_CINE) { + + if (ibuf->x==4096 || ibuf->y==2160) + parameters->cp_cinema= CINEMA4K_24; + else { + if (ibuf->ftype & JP2_CINE_48FPS) { + parameters->cp_cinema= CINEMA2K_48; + } + else { + parameters->cp_cinema= CINEMA2K_24; + } + } + if (parameters->cp_cinema){ + img_fol.rates = (float*)MEM_mallocN(parameters->tcp_numlayers * sizeof(float), "jp2_rates"); + for(i=0; i< parameters->tcp_numlayers; i++){ + img_fol.rates[i] = parameters->tcp_rates[i]; + } + cinema_parameters(parameters); + } + + color_space= CLRSPC_SYCC; + prec= 12; + numcomps= 3; + } + else { + /* Get settings from the imbuf */ + color_space = (ibuf->ftype & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB; + + if (ibuf->ftype & JP2_16BIT) prec= 16; + else if (ibuf->ftype & JP2_12BIT) prec= 12; + else prec= 8; + + /* 32bit images == alpha channel */ + /* grayscale not supported yet */ + numcomps= (ibuf->depth==32) ? 4 : 3; + } + + w= ibuf->x; + h= ibuf->y; + + + /* initialize image components */ + memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < numcomps; i++) { + cmptparm[i].prec = prec; + cmptparm[i].bpp = prec; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + printf("Error: opj_image_create() failed\n"); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1; + image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1; + + /* set image data */ + rect = (unsigned char*) ibuf->rect; + rect_float= ibuf->rect_float; + + if (rect_float && rect && prec==8) { + /* No need to use the floating point buffer, just write the 8 bits from the char buffer */ + rect_float= NULL; + } + + + if (rect_float) { + switch (prec) { + case 8: /* Convert blenders float color channels to 8,12 or 16bit ints */ + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; xcomps[0].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[0]); + image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[1]); + image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[2]); + if (numcomps>3) + image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]); + } + } + break; + + case 12: + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; xcomps[0].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[0]); + image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[1]); + image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[2]); + if (numcomps>3) + image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]); + } + } + break; + case 16: + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; xcomps[0].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[0]); + image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[1]); + image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[2]); + if (numcomps>3) + image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]); + } + } + break; + } + } else { + /* just use rect*/ + switch (prec) { + case 8: + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; xcomps[0].data[i] = rect[0]; + image->comps[1].data[i] = rect[1]; + image->comps[2].data[i] = rect[2]; + if (numcomps>3) + image->comps[3].data[i] = rect[3]; + } + } + break; + + case 12: /* Up Sampling, a bit pointless but best write the bit depth requested */ + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; xcomps[0].data[i]= UPSAMPLE_8_TO_12(rect[0]); + image->comps[1].data[i]= UPSAMPLE_8_TO_12(rect[1]); + image->comps[2].data[i]= UPSAMPLE_8_TO_12(rect[2]); + if (numcomps>3) + image->comps[3].data[i]= UPSAMPLE_8_TO_12(rect[3]); + } + } + break; + case 16: + for(y=h-1; y>=0; y--) { + y_row = y*w; + for(x=0; xcomps[0].data[i]= UPSAMPLE_8_TO_16(rect[0]); + image->comps[1].data[i]= UPSAMPLE_8_TO_16(rect[1]); + image->comps[2].data[i]= UPSAMPLE_8_TO_16(rect[2]); + if (numcomps>3) + image->comps[3].data[i]= UPSAMPLE_8_TO_16(rect[3]); + } + } + break; + } + } + + /* Decide if MCT should be used */ + parameters->tcp_mct = image->numcomps == 3 ? 1 : 0; + + if(parameters->cp_cinema){ + cinema_setup_encoder(parameters,image,&img_fol); + } + + if (img_fol.rates) + MEM_freeN(img_fol.rates); + + return image; +} + + +/* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */ +short imb_savejp2(struct ImBuf *ibuf, char *name, int flags) { + + int quality = ibuf->ftype & 0xff; + + int bSuccess; + opj_cparameters_t parameters; /* compression parameters */ + opj_event_mgr_t event_mgr; /* event manager */ + opj_image_t *image = NULL; + + /* + configure the event callbacks (not required) + setting of each callback is optionnal + */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + /* set encoding parameters to default values */ + opj_set_default_encoder_parameters(¶meters); + + /* compression ratio */ + /* invert range, from 10-100, 100-1 + * where jpeg see's 1 and highest quality (lossless) and 100 is very low quality*/ + parameters.tcp_rates[0]= ((100-quality)/90.0f*99.0f) + 1; + + + parameters.tcp_numlayers = 1; // only one resolution + parameters.cp_disto_alloc = 1; + + image= ibuftoimage(ibuf, ¶meters); + + + { /* JP2 format output */ + int codestream_length; + opj_cio_t *cio = NULL; + FILE *f = NULL; + + /* get a JP2 compressor handle */ + opj_cinfo_t* cinfo = opj_create_compress(CODEC_JP2); + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); + + /* setup the encoder parameters using the current image and using user parameters */ + opj_setup_encoder(cinfo, ¶meters, image); + + /* open a byte stream for writing */ + /* allocate memory for all tiles */ + cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); + + /* encode the image */ + bSuccess = opj_encode(cinfo, cio, image, NULL); /* last arg used to be parameters.index but this deprecated */ + + if (!bSuccess) { + opj_cio_close(cio); + fprintf(stderr, "failed to encode image\n"); + return 0; + } + codestream_length = cio_tell(cio); + + /* write the buffer to disk */ + f = fopen(name, "wb"); + + if (!f) { + fprintf(stderr, "failed to open %s for writing\n", name); + return 1; + } + fwrite(cio->buffer, 1, codestream_length, f); + fclose(f); + fprintf(stderr,"Generated outfile %s\n",name); + /* close and free the byte stream */ + opj_cio_close(cio); + + /* free remaining compression structures */ + opj_destroy_compress(cinfo); + } + + /* free image data */ + opj_image_destroy(image); + + return 1; +} + +#endif /* WITH_OPENJPEG */ From ca5fe954f4f26972ad4ff7a07417df7253ad7f6f Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sat, 24 Jan 2009 18:09:03 +0000 Subject: [PATCH 140/252] * make sure openjpeg stuff compiles and links properly. - since we use this only as statically linked, I took out some confusing #ifdefs. --- extern/libopenjpeg/SConscript | 7 +++++-- extern/libopenjpeg/openjpeg.h | 17 ----------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/extern/libopenjpeg/SConscript b/extern/libopenjpeg/SConscript index 837701eeae0..eb408c1e9c0 100644 --- a/extern/libopenjpeg/SConscript +++ b/extern/libopenjpeg/SConscript @@ -6,9 +6,12 @@ Import('env') sources = env.Glob('*.c') incs = '.' +flags = [] +defs = [] if env['OURPLATFORM'] == 'win32-vc': flags = [] + defs.append('OPJ_STATIC') else: flags = ['-Wall', '-O3', '-ffast-math', '-std=c99'] @@ -19,6 +22,6 @@ if not env['OURPLATFORM'] == 'win32-vc': oj_env.BlenderLib ( libname='extern_openjpeg', sources=sources, includes=Split(incs), - defines=[], + defines=defs, libtype=['core','intern','player'], - priority=[10, 10, 300], compileflags = flags) + priority=[300, 300, 300], compileflags = flags) diff --git a/extern/libopenjpeg/openjpeg.h b/extern/libopenjpeg/openjpeg.h index ffcaacaf6e5..ae7764eab2f 100644 --- a/extern/libopenjpeg/openjpeg.h +++ b/extern/libopenjpeg/openjpeg.h @@ -40,25 +40,8 @@ ========================================================== */ -#if defined(OPJ_STATIC) || !(defined(WIN32) || defined(__WIN32__)) #define OPJ_API #define OPJ_CALLCONV -#else -#define OPJ_CALLCONV __stdcall -/* -The following ifdef block is the standard way of creating macros which make exporting -from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS -symbol defined on the command line. this symbol should not be defined on any project -that uses this DLL. This way any other project whose source files include this file see -OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols -defined with this macro as being exported. -*/ -#ifdef OPJ_EXPORTS -#define OPJ_API __declspec(dllexport) -#else -#define OPJ_API __declspec(dllimport) -#endif /* OPJ_EXPORTS */ -#endif /* !OPJ_STATIC || !WIN32 */ #ifndef __cplusplus #if defined(HAVE_STDBOOL_H) From f1948b363d6cd01ec6cfcd2d69101fdb9407aff6 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 24 Jan 2009 21:19:35 +0000 Subject: [PATCH 141/252] BGE patch 18211: Bug Fix for: [#18175] error on anaglyph view of a splitted viewport. --- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 8bcda4479e1..1271474802c 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -732,6 +732,26 @@ void KX_KetsjiEngine::Render() // do the rendering //RenderFrame(scene); RenderFrame(scene, cam); + + list* cameras = scene->GetCameras(); + + // Draw the scene once for each camera with an enabled viewport + list::iterator it = cameras->begin(); + while(it != cameras->end()) + { + if((*it)->GetViewport()) + { + if (scene->IsClearingZBuffer()) + m_rasterizer->ClearDepthBuffer(); + + m_rendertools->SetAuxilaryClientInfo(scene); + + // do the rendering + RenderFrame(scene, (*it)); + } + + it++; + } } } // if(m_rasterizer->Stereo()) From 99e549480beae558e07f37f58265e96a7a5e87f0 Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Sun, 25 Jan 2009 17:49:39 +0000 Subject: [PATCH 142/252] == Python: Space Handler Scriptlinks == Bugfix (patch #18216) I made a mistake on my previous try to fix this. I fixed something, tested, decided I should move the call to run spacehandlers to a better place, but missed removing the old call (ugh). Thanks Steven Truppe (rocketmagnet) for emailing me about it and for the patch. --- source/blender/src/space.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/source/blender/src/space.c b/source/blender/src/space.c index bba58840566..a132a58cfbf 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1326,13 +1326,6 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } -#ifndef DISABLE_PYTHON - /* run any view3d event handler script links */ - if (event && sa->scriptlink.totscript) - if (BPY_do_spacehandlers(sa, event, val, SPACEHANDLER_VIEW3D_EVENT)) - return; /* return if event was processed (swallowed) by handler(s) */ -#endif - /* TEXTEDITING?? */ if((G.obedit) && G.obedit->type==OB_FONT) { switch(event) { From 9146687ffcc7ac78d0bd75339f351baf630b07e3 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 26 Jan 2009 06:31:06 +0000 Subject: [PATCH 143/252] let the game engine compile, if WITH_FFPEG is not defined (so we don't have video textures in that case) --- source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index f046942af75..67bec97ea32 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -368,7 +368,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, initGameKeys(); initPythonConstraintBinding(); initMathutils(); +#ifdef WITH_FFMPEG initVideoTexture(); +#endif if (sceneconverter) { @@ -660,7 +662,9 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, initGameKeys(); initPythonConstraintBinding(); initMathutils(); - initVideoTexture(); +#ifdef WITH_FFMPEG + initVideoTexture(); +#endif if (sceneconverter) { From a17eade6228ba9b361e31ef5564ebcbccda7686f Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 26 Jan 2009 22:43:12 +0000 Subject: [PATCH 144/252] - Made embbed point rely on last embbed preview (when holding down shift and moving mouse around) for finding the proper depth. This makes it much easier to do polylines on partially occluded areas: just shift-hover a visible section than move to where you want along the volume before clicking to place a point (this sounds complicated but it isn't). - Replace Cutout command by Straighten. Fonctionnality is the same except that it now keeps points in between cuts, just straightens them. --- source/blender/src/editarmature_sketch.c | 87 +++++++++++++++--------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index b73e2f64879..e44345e2451 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -173,6 +173,8 @@ typedef struct SK_GestureAction { SK_Sketch *GLOBAL_sketch = NULL; SK_Point boneSnap; +int LAST_SNAP_POINT_VALID = 0; +float LAST_SNAP_POINT[3]; #define SNAP_MIN_DISTANCE 12 @@ -896,7 +898,7 @@ void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt) stk->nb_points++; } -void sk_inserStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end) +void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end) { int size = end - start + 1; @@ -926,35 +928,42 @@ void sk_trimStroke(SK_Stroke *stk, int start, int end) stk->nb_points = size; } -void sk_cutoutStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3]) +void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3]) { - int size = end - start + 1; + SK_Point pt1, pt2; + SK_Point *prev, *next; + float delta_p[3]; + int i, total; - if (size == 1) + total = end - start + 1; + + VecSubf(delta_p, p_end, p_start); + + prev = stk->points + start; + next = stk->points + end; + + VECCOPY(pt1.p, p_start); + VECCOPY(pt1.no, prev->no); + pt1.mode = prev->mode; + pt1.type = prev->type; + + VECCOPY(pt2.p, p_end); + VECCOPY(pt2.no, next->no); + pt2.mode = next->mode; + pt2.type = next->type; + + sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */ + sk_insertStrokePoint(stk, &pt2, end); /* insert before end (since end was pushed back already) */ + + for (i = 1; i < total; i++) { - int move_size = stk->nb_points - end; - - sk_growStrokeBuffer(stk); - - memmove(stk->points + end + 1, stk->points + end, move_size * sizeof(SK_Point)); - end++; - size++; - stk->nb_points++; - } - - stk->points[start].type = PT_EXACT; - VECCOPY(stk->points[start].p, p_start); - stk->points[end].type = PT_EXACT; - VECCOPY(stk->points[end].p, p_end); - - if (size > 2) - { - int move_size = stk->nb_points - end; - - memmove(stk->points + start + 1, stk->points + end, move_size * sizeof(SK_Point)); - - stk->nb_points = stk->nb_points - (size - 2); - } + float delta = (float)i / (float)total; + float *p = stk->points[start + 1 + i].p; + + VECCOPY(p, delta_p); + VecMulf(p, delta); + VecAddf(p, p, p_start); + } } void sk_polygonizeStroke(SK_Stroke *stk, int start, int end) @@ -1554,7 +1563,7 @@ void sk_endOverdraw(SK_Sketch *sketch) sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type; } - sk_inserStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end); + sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end); sk_removeStroke(sketch, stk); @@ -1768,7 +1777,7 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D { ListBase depth_peels; SK_DepthPeel *p1, *p2; - SK_Point *last_pt = NULL; + float *last_p = NULL; float dist = FLT_MAX; float p[3]; int point_added = 0; @@ -1779,7 +1788,11 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) { - last_pt = stk->points + (stk->nb_points - 1); + last_p = stk->points[stk->nb_points - 1].p; + } + else if (LAST_SNAP_POINT_VALID) + { + last_p = LAST_SNAP_POINT; } @@ -1827,14 +1840,14 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D VECCOPY(vec, p1->p); } - if (last_pt == NULL) + if (last_p == NULL) { VECCOPY(p, vec); dist = 0; break; } - new_dist = VecLenf(last_pt->p, vec); + new_dist = VecLenf(last_p, vec); if (new_dist < dist) { @@ -1944,6 +1957,12 @@ void sk_getStrokePoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawD if (point_added == 0 && qual & LR_SHIFTKEY) { point_added = sk_getStrokeEmbedPoint(pt, sketch, stk, dd); + LAST_SNAP_POINT_VALID = 1; + VECCOPY(LAST_SNAP_POINT, pt->p); + } + else + { + LAST_SNAP_POINT_VALID = 0; } if (point_added == 0) @@ -2556,7 +2575,7 @@ void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch) SK_Intersection *isect; int command; - command = pupmenu("Action %t|Flatten %x1|Cut Out %x2|Polygonize %x3"); + command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3"); if(command < 1) return; for (isect = gest->intersections.first; isect; isect = isect->next) @@ -2573,7 +2592,7 @@ void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch) sk_flattenStroke(isect->stroke, isect->before, i2->after); break; case 2: - sk_cutoutStroke(isect->stroke, isect->after, i2->before, isect->p, i2->p); + sk_straightenStroke(isect->stroke, isect->after, i2->before, isect->p, i2->p); break; case 3: sk_polygonizeStroke(isect->stroke, isect->before, i2->after); From d95d110d8d72846ca6ac4ce3b58ff04274b1a17a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 27 Jan 2009 08:17:35 +0000 Subject: [PATCH 145/252] [#17850] Copying text from Eric4 to Blender crashes Blender The crash is caused by calling XGetWindowProperty when xevent.xselection.property is zero. Not a proper fix because clipboard can paste the data without trouble. --- intern/ghost/intern/GHOST_SystemX11.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 8073756e453..9950ef88879 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -1031,15 +1031,20 @@ getClipboard(int flag //This needs to change so we do not wait for ever or check owner first while(1) { XNextEvent(m_display, &xevent); - if(xevent.type == SelectionNotify) { - if(XGetWindowProperty(m_display, m_window, xevent.xselection.property, 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) { - if (data) { - tmp_data = (unsigned char*) malloc(strlen((char*)data)+1); - strcpy((char*)tmp_data, (char*)data); - XFree(data); - return (GHOST_TUns8*)tmp_data; + if(xevent.type == SelectionNotify) { + if (xevent.xselection.property ) { /* eric4 on linux gives zero Atom xevent.xselection.property value, closes blender instantly */ + if(XGetWindowProperty(m_display, m_window, xevent.xselection.property , 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) { + if (data) { + tmp_data = (unsigned char*) malloc(strlen((char*)data)+1); + strcpy((char*)tmp_data, (char*)data); + XFree(data); + return (GHOST_TUns8*)tmp_data; + } } } + else { + fprintf(stderr, "error: cut buffer had a zero xevent.xselection.property, FIXME\n"); // XXX fix this problem! + } return NULL; } } From 4977609832e897aeb864f8642c3ff0983422d6d6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 27 Jan 2009 19:59:12 +0000 Subject: [PATCH 146/252] Fix for bug #18066: made UV Unwrap > Reset same as the default UV coordinates when creating a new layer. --- source/blender/src/editface.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index 53fb6dbffb1..9872469030a 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -631,15 +631,15 @@ void default_uv(float uv[][2], float size) dy= 1.0-size; uv[0][0]= 0; - uv[0][1]= size+dy; + uv[0][1]= dy; - uv[1][0]= 0; + uv[1][0]= size; uv[1][1]= dy; uv[2][0]= size; - uv[2][1]= dy; - - uv[3][0]= size; + uv[2][1]= size+dy; + + uv[3][0]= 0; uv[3][1]= size+dy; } From 2e610b3fb27991992ee29063a5a1c7b5eb7e9018 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 27 Jan 2009 20:17:32 +0000 Subject: [PATCH 147/252] Fix for bug #17961: crash with material copy/past and GLSL. --- source/blender/src/header_buttonswin.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/src/header_buttonswin.c b/source/blender/src/header_buttonswin.c index 1e2890f4f2b..857fec16a64 100644 --- a/source/blender/src/header_buttonswin.c +++ b/source/blender/src/header_buttonswin.c @@ -77,6 +77,8 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "GPU_material.h" + #include "blendef.h" #include "mydevice.h" #include "butspace.h" @@ -168,6 +170,7 @@ void do_buts_buttons(short event) } matcopybuf.nodetree= ntreeCopyTree(ma->nodetree, 0); matcopybuf.preview= NULL; + matcopybuf.gpumaterial.first= matcopybuf.gpumaterial.last= NULL; matcopied= 1; } break; @@ -188,6 +191,8 @@ void do_buts_buttons(short event) ntreeFreeTree(ma->nodetree); MEM_freeN(ma->nodetree); } + + GPU_materials_free(ma); id= (ma->id); memcpy(ma, &matcopybuf, sizeof(Material)); From a21cdd9369243596c632314eea94b67a6744eb1f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 27 Jan 2009 21:19:19 +0000 Subject: [PATCH 148/252] Fix for bug #18183: crash when using "Bake Constraints" script. The constraint remove function was not working correct, this code uses a pretty bad hack, did not clean it up, but at least it should work now. --- source/blender/python/api2_2x/Constraint.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index b0b9aa04a08..1845ce6f0de 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -2291,6 +2291,7 @@ static PyObject *ConstraintSeq_remove( BPy_ConstraintSeq *self, BPy_Constraint * { bConstraint *con = locate_constr(self, value); bPoseChannel *active= NULL; + int tmpflag= 0; /* if we can't locate the constraint, return (exception already set) */ if (!con) @@ -2304,6 +2305,11 @@ static PyObject *ConstraintSeq_remove( BPy_ConstraintSeq *self, BPy_Constraint * if (active) active->bone->flag &= ~BONE_ACTIVE; self->pchan->bone->flag |= BONE_ACTIVE; } + + if(!(self->obj->flag & OB_POSEMODE)) { + self->obj->flag |= OB_POSEMODE; + tmpflag= 1; + } } /* del_constr_func() frees constraint + its data */ @@ -2314,6 +2320,8 @@ static PyObject *ConstraintSeq_remove( BPy_ConstraintSeq *self, BPy_Constraint * if (active) active->bone->flag |= BONE_ACTIVE; self->pchan->bone->flag &= ~BONE_ACTIVE; } + if(tmpflag) + self->obj->flag &= ~OB_POSEMODE; /* erase the link to the constraint */ value->con = NULL; From 5542f25331c483cf48341d7c37fd01989e3ea173 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 27 Jan 2009 21:26:31 +0000 Subject: [PATCH 149/252] Fix for bug #18167: setting Constraint.Settings.SCRIPT checked for type Object rather than Text so did not work when assigning a text to it. --- source/blender/python/api2_2x/Constraint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index 1845ce6f0de..9ecec8eb973 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -1560,7 +1560,7 @@ static int script_setter( BPy_Constraint *self, int type, PyObject *value ) break; case EXPP_CONSTR_SCRIPT: { Text *text = (( BPy_Text * )value)->text; - if( !BPy_Object_Check( value ) ) + if( !BPy_Text_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected BPy text argument" ); con->text = text; From 7eae2080f23446054d0a7a3f30f8dd6c4969d1fa Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 27 Jan 2009 22:09:23 +0000 Subject: [PATCH 150/252] Fix for bug #18087: Editing of object name and modifiers did not work in editing buttons if the object data was linked. --- source/blender/src/buttons_editing.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 7ba6f122d39..953519416e1 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1944,13 +1944,14 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiButSetFunc(but, modifiers_applyModifier, ob, md); } + uiClearButLock(); + uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); + if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) { but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack"); uiButSetFunc(but, modifiers_copyModifier, ob, md); } uiBlockEndAlign(block); - - uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); } lx = x + 10; @@ -5525,7 +5526,6 @@ static void editing_panel_links(Object *ob) uiBlockSetCol(block, TH_AUTO); } if(ob) { - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); but = uiDefBut(block, TEX, B_IDNAME, "OB:", xco, 180, 454-xco, YIC, ob->id.name+2, 0.0, 21.0, 0, 0, "Active Object name."); #ifdef WITH_VERSE if(ob->vnode) uiButSetFunc(but, test_and_send_idbutton_cb, ob, ob->id.name); @@ -5534,6 +5534,7 @@ static void editing_panel_links(Object *ob) uiButSetFunc(but, test_idbutton_cb, ob->id.name, NULL); #endif + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); } /* empty display handling, note it returns! */ From 56d2dc7e7f3f029fab442ea0cc9673583328fb46 Mon Sep 17 00:00:00 2001 From: Jens Ole Wund Date: Wed, 28 Jan 2009 12:34:22 +0000 Subject: [PATCH 151/252] bug fix softbody wind -compensating factor 1000 that comes from pdDoEffectors() since Aug 2008 -give particles and soft body vertices the same polarity on force fields. --- source/blender/blenkernel/intern/softbody.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 5d93f10526a..f63f6edf4b3 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1562,7 +1562,7 @@ static void _scan_for_ext_spring_forces(Object *ob,float timenow,int ifirst,int /* note we don't use sb->mediafrict but use sb->aeroedge for magnitude of effect*/ if(sb->aeroedge){ float vel[3],sp[3],pr[3],force[3]; - float f,windfactor = 250.0f; + float f,windfactor = 0.25f; /*see if we have wind*/ if(do_effector) { float speed[3]={0.0f,0.0f,0.0f}; @@ -2392,7 +2392,7 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i BodyPoint *bproot; ListBase *do_effector; float iks, gravity; - float fieldfactor = 1000.0f, windfactor = 250.0f; + float fieldfactor = -1.0f, windfactor = 0.25; int do_deflector,do_selfcollision,do_springcollision,do_aero; gravity = sb->grav * sb_grav_force_scale(ob); @@ -2454,7 +2454,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int BodySpring *bs; ListBase *do_effector; float iks, ks, kd, gravity; - float fieldfactor = 1000.0f, windfactor = 250.0f; + float fieldfactor = -1.0f, windfactor = 0.25f; float tune = sb->ballstiff; int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero; From 1cec028c911c65883401eda374015cfa0d987d13 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 29 Jan 2009 22:45:59 +0000 Subject: [PATCH 152/252] fix remaining bug in straighten command restrict snapping to exact (poly) points when snapping to the currently drawn stroke. --- source/blender/src/editarmature_sketch.c | 26 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index e44345e2451..73d952b9cbd 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -935,7 +935,7 @@ void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], f float delta_p[3]; int i, total; - total = end - start + 1; + total = end - start; VecSubf(delta_p, p_end, p_start); @@ -953,7 +953,7 @@ void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], f pt2.type = next->type; sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */ - sk_insertStrokePoint(stk, &pt2, end); /* insert before end (since end was pushed back already) */ + sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */ for (i = 1; i < total; i++) { @@ -1337,14 +1337,14 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) } } -SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist, int *index) +SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist, int *index, int all_pts) { SK_Point *pt = NULL; int i; for (i = 0; i < stk->nb_points; i++) { - if (1) // stk->points[i].type == PT_EXACT) + if (all_pts || stk->points[i].type == PT_EXACT) { short pval[2]; int pdist; @@ -1452,7 +1452,7 @@ void sk_updateOverdraw(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { int index; - SK_Point *spt = sk_snapPointStroke(target, dd->mval, &dist, &index); + SK_Point *spt = sk_snapPointStroke(target, dd->mval, &dist, &index, 1); if (spt != NULL) { @@ -1492,7 +1492,7 @@ void sk_updateOverdraw(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) int dist = SNAP_MIN_DISTANCE * 2; int index; - closest_pt = sk_snapPointStroke(sketch->over.target, dd->mval, &dist, &index); + closest_pt = sk_snapPointStroke(sketch->over.target, dd->mval, &dist, &index, 1); if (closest_pt != NULL) { @@ -1697,8 +1697,16 @@ int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *source_stk for (stk = sketch->strokes.first; stk; stk = stk->next) { - SK_Point *spt = sk_snapPointStroke(stk, dd->mval, &dist, NULL); - + SK_Point *spt = NULL; + if (stk == source_stk) + { + spt = sk_snapPointStroke(stk, dd->mval, &dist, NULL, 0); + } + else + { + spt = sk_snapPointStroke(stk, dd->mval, &dist, NULL, 1); + } + if (spt != NULL) { VECCOPY(pt->p, spt->p); @@ -2592,7 +2600,7 @@ void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch) sk_flattenStroke(isect->stroke, isect->before, i2->after); break; case 2: - sk_straightenStroke(isect->stroke, isect->after, i2->before, isect->p, i2->p); + sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p); break; case 3: sk_polygonizeStroke(isect->stroke, isect->before, i2->after); From 0409977aa8b91a88095a74f4fbfcc40fab0cbad7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 30 Jan 2009 02:01:16 +0000 Subject: [PATCH 153/252] =?UTF-8?q?[#18241]=20Very=20minor=20bugfix=20and?= =?UTF-8?q?=20typo=20correction=20for=20wavefront=20obj=20exporter=20and?= =?UTF-8?q?=20importer=20python=20scripts=20from=20=EF=BB=BFMichael=20Judd?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also removed .keys() for a loop in impor_obj.py since its the default dictionary iterator. --- release/scripts/export_obj.py | 2 +- release/scripts/import_obj.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/release/scripts/export_obj.py b/release/scripts/export_obj.py index 9feb02638c3..28e1443e953 100644 --- a/release/scripts/export_obj.py +++ b/release/scripts/export_obj.py @@ -120,7 +120,7 @@ def write_mtl(filename): if img: # We have an image on the face! file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image - elif not mat: # No face image. if we havea material search for MTex image. + elif mat: # No face image. if we havea material search for MTex image. for mtex in mat.getTextures(): if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE: try: diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py index 3aad0800cf7..42cdac4dc35 100644 --- a/release/scripts/import_obj.py +++ b/release/scripts/import_obj.py @@ -424,8 +424,8 @@ def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_l sharp_edges[key]= None - # mat the material names to an index - material_mapping= dict([(name, i) for i, name in enumerate(unique_materials.keys())]) + # map the material names to an index + material_mapping= dict([(name, i) for i, name in enumerate(unique_materials)]) # enumerate over unique_materials keys() materials= [None] * len(unique_materials) From c63fcd27994875e31878619875ad3324232bf90d Mon Sep 17 00:00:00 2001 From: Diego Borghetti Date: Fri, 30 Jan 2009 21:01:18 +0000 Subject: [PATCH 154/252] Fix revision: 18690, bug #17850 The problem was that Qt convert the text to the type STRING or UTF8, that is why Blender can't get the text, now should be work fine. --- intern/ghost/intern/GHOST_SystemX11.cpp | 45 +++++++++++++++++++------ 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 9950ef88879..02dfdc2e25c 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -981,11 +981,11 @@ getClipboard(int flag ) const { //Flag //0 = Regular clipboard 1 = selection - static Atom Primary_atom, clip_String, compound_text; + static Atom Primary_atom, clip_String, compound_text, a_text, a_string; Atom rtype; Window m_window, owner; unsigned char *data, *tmp_data; - int bits; + int bits, count; unsigned long len, bytes; XEvent xevent; @@ -996,6 +996,8 @@ getClipboard(int flag clip_String = XInternAtom(m_display, "_BLENDER_STRING", False); compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False); + a_text= XInternAtom(m_display, "TEXT", False); + a_string= XInternAtom(m_display, "STRING", False); //lets check the owner and if it is us then return the static buffer if(flag == 0) { @@ -1029,23 +1031,46 @@ getClipboard(int flag XFlush(m_display); //This needs to change so we do not wait for ever or check owner first + count= 1; while(1) { XNextEvent(m_display, &xevent); - if(xevent.type == SelectionNotify) { - if (xevent.xselection.property ) { /* eric4 on linux gives zero Atom xevent.xselection.property value, closes blender instantly */ + if(xevent.type == SelectionNotify) { + if (xevent.xselection.property == None) { + /* Ok, the client can't convert the property + * to some that we can handle, try other types.. + */ + if (count == 1) { + XConvertSelection(m_display, Primary_atom, a_text, clip_String, m_window, CurrentTime); + count++; + } + else if (count == 2) { + XConvertSelection(m_display, Primary_atom, a_string, clip_String, m_window, CurrentTime); + count++; + } + else { + /* Ok, the owner of the selection can't + * convert the data to something that we can + * handle. + */ + return(NULL); + } + } + else { if(XGetWindowProperty(m_display, m_window, xevent.xselection.property , 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) { if (data) { - tmp_data = (unsigned char*) malloc(strlen((char*)data)+1); - strcpy((char*)tmp_data, (char*)data); + if (bits == 8 && (rtype == compound_text || rtype == a_text || rtype == a_string)) { + tmp_data = (unsigned char*) malloc(strlen((char*)data)+1); + strcpy((char*)tmp_data, (char*)data); + } + else + tmp_data= NULL; + XFree(data); return (GHOST_TUns8*)tmp_data; } } + return(NULL); } - else { - fprintf(stderr, "error: cut buffer had a zero xevent.xselection.property, FIXME\n"); // XXX fix this problem! - } - return NULL; } } } From 7c48f1994a716b2c52ceddb83bdd7d540bd5d79d Mon Sep 17 00:00:00 2001 From: Remigiusz Fiedler Date: Mon, 2 Feb 2009 00:31:46 +0000 Subject: [PATCH 155/252] patch for paths_svg2obj.py by author jms: This patch solves some major problems of the svg script : - reading of the inkscape svg format - parsing of the scientific numbers - redundant arc data in the same path for only one command "a" - blending of curves after several files import and at the end a more correct management of the current point. --- release/scripts/bpymodules/paths_svg2obj.py | 178 ++++++++++++-------- 1 file changed, 110 insertions(+), 68 deletions(-) diff --git a/release/scripts/bpymodules/paths_svg2obj.py b/release/scripts/bpymodules/paths_svg2obj.py index de40bea3191..d51fe74190d 100644 --- a/release/scripts/bpymodules/paths_svg2obj.py +++ b/release/scripts/bpymodules/paths_svg2obj.py @@ -1,7 +1,7 @@ # -*- coding: latin-1 -*- """ -SVG 2 OBJ translater, 0.5.9h -Copyright (c) jm soler juillet/novembre 2004-april 2007, +SVG 2 OBJ translater, 0.5.9n +Copyright (c) jm soler juillet/novembre 2004-february 2009, # --------------------------------------------------------------- released under GNU Licence for the Blender 2.42 Python Scripts Bundle. @@ -20,7 +20,6 @@ en m Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, États-Unis. - 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 @@ -35,7 +34,7 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # --------------------------------------------------------------- - +# #--------------------------------------------------------------------------- # Page officielle : # http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm @@ -253,15 +252,27 @@ Changelog: 0.5.9h : - 2007/5/2 - script was updated with the modifs by cambo - - removed all debug statements + - removed all debug statements - correction of a zero division error in the calc_arc function. + 0.5.9f: - 2007/15/7 + - Correction de plusieurs bugs sur l'attributions des couleurs et le nommage + des courbes + + 0.5.9i : - ??/??/?? + - Patch externe réalisé sur blender.org project. + + 0.5.9j : - 08/11/2008 + 0.5.9k : - 14/01/2009 + 0.5.9l : - 31/01/2009 + 0.5.9n : - 01/02/2009 + ================================================================================== ==================================================================================""" SHARP_IMPORT=0 SCALE=1 scale_=1 -DEBUG = 0#print +DEBUG = 0 DEVELOPPEMENT=0 TESTCOLOR=0 @@ -533,7 +544,7 @@ def createCURVES(curves, name): scene.objects.selected = [] if not SEPARATE_CURVES: - c = Curve.New() + c = Curve.New() c.setResolu(24) MATNAME=[] @@ -709,7 +720,6 @@ def circle(prp): else : cx =float(prp['cx']) if 'cy' not in prp: cy=0.0 else : cy =float(prp['cy']) - #print prp.keys() r = float(prp['r']) D=['M',str(cx),str(cy+r), 'C',str(cx-r), str(cy+r*0.552),str(cx-0.552*r),str(cy+r), str(cx),str(cy+r), @@ -852,7 +862,7 @@ def calc_arc (cpx,cpy, rx, ry, ang, fa , fs , x, y) : #-------------------- # 0.3.9 #-------------------- -def curve_to_a(c,D,n0,CP): #A,a +def curve_to_a(curves, c,D,n0,CP): #A,a global SCALE l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]), int(D[c[1]+4]),int(D[c[1]+5]),float(D[c[1]+6]),float(D[c[1]+7])] @@ -866,8 +876,7 @@ def curve_to_a(c,D,n0,CP): #A,a POINTS= calc_arc (CP[0],CP[1], l[0], l[1], l[2]*(PI / 180.0), l[3], l[4], - l[5], l[6] ) - #if DEBUG == 1 : print POINTS + l[5], l[6] ) for p in POINTS : B=Bez() B.co=[ p[2][0],p[2][1], p[0][0],p[0][1], p[1][0],p[1][1]] @@ -881,16 +890,23 @@ def curve_to_a(c,D,n0,CP): #A,a BP.co[2]=BP.co[0] BP.co[3]=BP.co[1] CP=[l[5], l[6]] + #---------- 059m------------ + if len(D)>c[1]+7 and D[c[1]+8] not in TAGcourbe : + c[1]+=7 + curves,n0,CP=curve_to_a(curves, c, D, n0,CP) + #---------- 059m------------ return curves,n0,CP -def move_to(c, D, n0,CP, proprietes): +def move_to(curves, c, D, n0,CP, proprietes): global DEBUG,TAGcourbe, LAST_ID global USE_COLORS l=[float(D[c[1]+1]),float(D[c[1]+2])] + if c[0]=='m': l=[l[0]+CP[0], l[1] + CP[1]] + if n0 in curves.ITEM: n0+=1 CP=[l[0],l[1]] @@ -917,14 +933,12 @@ def move_to(c, D, n0,CP, proprietes): B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]] B.ha=['L','C'] B.tag=c[0] - curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print curves.ITEM[n0], CP + curves.ITEM[n0].beziers_knot.append(B) return curves,n0,CP -def close_z(c,D,n0,CP): #Z,z +def close_z(curves, c,D,n0,CP): #Z,z curves.ITEM[n0].flagUV[0]=1 if len(curves.ITEM[n0].beziers_knot)>1: - #print len(curves.ITEM[n0].beziers_knot) BP=curves.ITEM[n0].beziers_knot[-1] BP0=curves.ITEM[n0].beziers_knot[0] if BP.tag in ['c','C','s','S',]: @@ -936,7 +950,7 @@ def close_z(c,D,n0,CP): #Z,z n0-=1 return curves,n0,CP -def curve_to_q(c,D,n0,CP): #Q,q +def curve_to_q(curves, c,D,n0,CP): #Q,q l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),float(D[c[1]+4])] if c[0]=='q': l=[l[0]+CP[0], l[1]+CP[1], l[2]+CP[0], l[3]+CP[1]] @@ -948,15 +962,14 @@ def curve_to_q(c,D,n0,CP): #Q,q BP.co[2]=BP.co[0] BP.co[3]=BP.co[1] curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print B.co,BP.co CP=[l[2],l[3]] #if DEBUG==1: pass if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe : c[1]+=4 - curve_to_q(c, D, n0,CP) + curves,n0,CP=curve_to_q(curves, c, D, n0,CP) return curves,n0,CP -def curve_to_t(c,D,n0,CP): #T,t +def curve_to_t(curves, c,D,n0,CP): #T,t l=[float(D[c[1]+1]),float(D[c[1]+2])] if c[0]=='t': l=[l[0]+CP[0], l[1]+CP[1]] @@ -970,11 +983,10 @@ def curve_to_t(c,D,n0,CP): #T,t BP.co[2]=l0[2] BP.co[3]=l0[3] curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print B.co,BP.co CP=[l[0],l[1]] if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe : c[1]+=4 - curve_to_t(c, D, n0,CP) + curves,n0,CP=curve_to_t(curves, c, D, n0,CP) return curves,n0,CP #-------------------- @@ -985,7 +997,7 @@ def build_SYMETRIC(l): Y=l[3]-(l[1]-l[3]) return X,Y -def curve_to_s(c,D,n0,CP): #S,s +def curve_to_s(curves, c,D,n0,CP): #S,s l=[float(D[c[1]+1]), float(D[c[1]+2]), float(D[c[1]+3]), @@ -1003,17 +1015,16 @@ def curve_to_s(c,D,n0,CP): #S,s #-------------------- BP.co[2],BP.co[3]=build_SYMETRIC([BP.co[4],BP.co[5],BP.co[0],BP.co[1]]) curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print B.co,BP.co #-------------------- # 0.4.3 #-------------------- CP=[l[2],l[3]] if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe : c[1]+=4 - curve_to_c(c, D, n0,CP) + curves,n0,CP=curve_to_c(curves, c, D, n0,CP) return curves,n0,CP -def curve_to_c(c, D, n0,CP): #c,C +def curve_to_c(curves, c, D, n0,CP): #c,C l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]), float(D[c[1]+4]),float(D[c[1]+5]),float(D[c[1]+6])] if c[0]=='c': @@ -1030,6 +1041,8 @@ def curve_to_c(c, D, n0,CP): #c,C l[5], l[2], l[3]] #plus toucher au 2-3 + + B.ha=['C','C'] B.tag=c[0] BP=curves.ITEM[n0].beziers_knot[-1] @@ -1037,32 +1050,38 @@ def curve_to_c(c, D, n0,CP): #c,C BP.co[3]=l[1] BP.ha[1]='C' curves.ITEM[n0].beziers_knot.append(B) - #if DEBUG==1: print B.co,BP.co CP=[l[4],l[5]] if len(D)>c[1]+7 and D[c[1]+7] not in TAGcourbe : - c[1]+=6 - curve_to_c(c, D, n0,CP) + c[1]+=6 + curves,n0,CP=curve_to_c(curves, c, D, n0,CP) return curves,n0,CP -def draw_line_l(c, D, n0,CP): #L,l - l=[float(D[c[1]+1]),float(D[c[1]+2])] +def draw_line_l(curves, c, D, n0,CP): #L,l + + l=[float(D[c[1]+1]),float(D[c[1]+2])] if c[0]=='l': l=[l[0]+CP[0], - l[1]+CP[1]] + l[1]+CP[1]] B=Bez() - B.co=[l[0],l[1],l[0],l[1],l[0],l[1]] + B.co=[l[0],l[1], + l[0],l[1], + l[0],l[1]] + B.ha=['L','L'] B.tag=c[0] BP=curves.ITEM[n0].beziers_knot[-1] BP.ha[1]='L' + curves.ITEM[n0].beziers_knot.append(B) - CP=[B.co[0],B.co[1]] + CP=[B.co[4],B.co[5]] + if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe : c[1]+=2 - draw_line_l(c, D, n0,CP) #L + curves,n0,CP=draw_line_l(curves, c, D, n0,CP) #L + return curves,n0,CP -def draw_line_h(c,D,n0,CP): #H,h +def draw_line_h(curves, c,D,n0,CP): #H,h if c[0]=='h': l=[float(D[c[1]+1])+float(CP[0]),CP[1]] else: @@ -1077,7 +1096,7 @@ def draw_line_h(c,D,n0,CP): #H,h CP=[l[0],l[1]] return curves,n0,CP -def draw_line_v(c,D,n0,CP): #V, v +def draw_line_v(curves, c,D,n0,CP): #V, v if c[0]=='v': l=[CP[0], float(D[c[1]+1])+CP[1]] else: @@ -1121,17 +1140,31 @@ TAGtransform=['M','L','C','S','H','V','T','Q'] tagTRANSFORM=0 def wash_DATA(ndata): - if ndata: - #if DEBUG==1: print ndata + if ndata: ndata = ndata.strip() + if ndata[0]==',':ndata=ndata[1:] if ndata[-1]==',':ndata=ndata[:-1] + #-------------------- # 0.4.0 : 'e' #-------------------- - i = ndata.find('-') - if i != -1 and ndata[i-1] not in ' ,e': - ndata=ndata.replace('-',',-') + ni=0 + i = ndata.find('-',ni) + if i != -1: + while i>-1 : + i = ndata.find('-',ni) + # 059l ------ + if i>0 : + if ndata[i-1] not in [' ',',','e']: + ndata=ndata[:i]+','+ndata[i:] + ni=i+2 + else: + ni=i+1 + elif i>-1: + ni=1 + # 059l ------ + ndata=ndata.replace(',,',',') ndata=ndata.replace(' ',',') ndata=ndata.split(',') @@ -1153,7 +1186,7 @@ def list_DATA(DATA): # borner les differents segments qui devront etre # traites # pour cela construire une liste avec chaque - # la position de chaqe emplacement tag de type + # position de chaque emplacement tag de type # commande path... # ---------------------------------------- tagplace=[] @@ -1169,8 +1202,10 @@ def list_DATA(DATA): # d'apparition des tags #------------------------------------------ tagplace.sort() - + tpn=range(len(tagplace)) + + #-------------------- # 0.3.5 :: short data, only one tag #-------------------- @@ -1179,14 +1214,18 @@ def list_DATA(DATA): for t in tpn[:-1]: DATA2.append(DATA[tagplace[t]:tagplace[t]+1]) ndata=DATA[tagplace[t]+1:tagplace[t+1]] + if DATA2[-1] not in ['z','Z'] : ndata=wash_DATA(ndata) DATA2.extend(ndata) + DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1]) + if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1: ndata=DATA[tagplace[t+1]+1:] ndata=wash_DATA(ndata) DATA2.extend(ndata) #059a + else: #-------------------- # 0.3.5 : short data,only one tag @@ -1276,15 +1315,13 @@ def control_CONTAINT(txt): nt0=txt[t0:t1+1] t2=nt0[nt0.find('(')+1:-1] val=nt0[:nt0.find('(')] + while t2.find(' ')!=-1: t2=t2.replace(' ',' ') - t2=t2.replace(' ',',') + while t2.find(', ')!=-1: #059l + t2=t2.replace(', ',',') #059l - """ - t2=t2.split(',') - for index, t in enumerate(t2): - t2[index]=float(t) - """ + t2=t2.replace(' ',',') t2=[float(t) for t in t2.split(',')] if val=='rotate' : @@ -1314,12 +1351,24 @@ def curve_FILL(Courbe,proprietes): i= i+6 Courbe[n].color=[int(pr[i:i+2],16),int(pr[i+2:i+4],16),int(pr[i+4:i+6],16)] Courbe[n].mat=1 - elif ';fill-opacity' in pr: - i= pr.find('fill:')+5 - i2= pr.find(';',i) - COLORNAME= pr[i:i2] - Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] - Courbe[n].mat=1 + elif ';fill-opacity' in pr: + if pr.find('fill:url')==-1: + i= pr.find('fill:')+5 + i2= pr.find(';',i) + COLORNAME= pr[i:i2] + Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] + Courbe[n].mat=1 + elif 'color:' in pr: + i= pr.find('color:')+6 + i2= pr.find(';',i) + COLORNAME= pr[i:i2] + Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] + Courbe[n].mat=1 + else : + COLORNAME= 'white' + Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] + Courbe[n].mat=1 + #---------------------------------------------- # 0.4.1 : apply transform stack #---------------------------------------------- @@ -1367,9 +1416,8 @@ def filter(d): def get_BOUNDBOX(BOUNDINGBOX,SVG): if 'viewbox' not in SVG: h=float(filter(SVG['height'])) - #if DEBUG==1 : print 'h : ',h + w=float(filter(SVG['width'])) - #if DEBUG==1 : print 'w :',w BOUNDINGBOX['rec']=[0.0,0.0,w,h] r=BOUNDINGBOX['rec'] BOUNDINGBOX['coef']=w/h @@ -1444,7 +1492,6 @@ def build_HIERARCHY(t): b=balisetype.index(t[t0+1]) if t[t0+2]=='-': b=balisetype.index(t[t0+1])+1 - #print t[t0:t1] balise=BALISES[b] if b==2: parent=STACK.pop(-1) @@ -1465,12 +1512,8 @@ def build_HIERARCHY(t): if balise=='E' or balise=='O': proprietes=collect_ATTRIBUTS(t[t0:t1+ouvrante]) - #print proprietes if 'id' in proprietes: LAST_ID=proprietes['id'] - #print LAST_ID - - if balise=='O' and 'transform' in proprietes: STACK.append(proprietes['transform']) @@ -1489,20 +1532,20 @@ def build_HIERARCHY(t): # 0.5.8, to remove exec #-------------------- D=OTHERSSHAPES[proprietes['TYPE']](proprietes) - + CP=[0.0,0.0] if len(D)>0: cursor=0 proprietes['n']=[] for cell in D: - #if DEBUG==2 : print 'cell : ',cell ,' --' + if len(cell)>=1 and cell[0] in TAGcourbe: #-------------------- # 0.5.8, to remove exec #-------------------- if cell[0] in ['m','M']: - curves,n0,CP=Actions[cell]([cell,cursor], D, n0,CP,proprietes) + curves,n0,CP=Actions[cell](curves, [cell,cursor], D, n0,CP,proprietes) else: - curves,n0,CP=Actions[cell]([cell,cursor], D, n0,CP) + curves,n0,CP=Actions[cell](curves, [cell,cursor], D, n0,CP) cursor+=1 if TRANSFORM>0 or 'transform' in proprietes : @@ -1513,7 +1556,6 @@ def build_HIERARCHY(t): elif proprietes['TYPE'] == 'svg': - #print 'proprietes.keys()',proprietes.keys() BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,proprietes) else: #-------------------- From 08b1d587382a072f1da317c3f3c8ac6b50db78e9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 3 Feb 2009 12:31:40 +0000 Subject: [PATCH 156/252] Allow enter/exit editmode in background mode. (asking for trouble doing this but the checks are simple) --- source/blender/src/editobject.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 4a70e89dd07..2a1d508bf59 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1740,7 +1740,8 @@ void enter_editmode(int wc) if(wc) waitcursor(0); - scrarea_queue_headredraw(curarea); + if (G.background==0) + scrarea_queue_headredraw(curarea); } void exit_editmode(int flag) /* freedata==0 at render, 1= freedata, 2= do undo buffer too */ @@ -1817,8 +1818,9 @@ void exit_editmode(int flag) /* freedata==0 at render, 1= freedata, 2= do undo b allqueue(REDRAWNLA, 0); allqueue(REDRAWIPO, 0); allqueue(REDRAWOOPS, 0); - - scrarea_queue_headredraw(curarea); + + if (G.background==0) + scrarea_queue_headredraw(curarea); if(G.obedit==NULL && (flag & EM_FREEUNDO)) BIF_undo_push("Editmode"); From 4286730d34ba4d36b994b73b3017bacf4552e1f4 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 4 Feb 2009 02:55:24 +0000 Subject: [PATCH 157/252] dropdown for bone creation method and swap params in panel instead of having all of them visible all the time. --- source/blender/src/drawview.c | 127 +++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 56 deletions(-) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 0230974b509..c8701d2aa98 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2301,6 +2301,14 @@ static void view3d_panel_bonesketch_spaces(short cntrl) /* replace with check call to sketching lib */ if (G.obedit && G.obedit->type == OB_ARMATURE) { + static char subdiv_tooltip[4][64] = { + "Subdivide arcs based on a fixed number of bones", + "Subdivide arcs in bones of equal length", + "Subdivide arcs based on correlation", + "Retarget template to stroke" + }; + + block= uiNewBlock(&curarea->uiblocks, "view3d_panel_bonesketch_spaces", UI_EMBOSS, UI_HELV, curarea->win); uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); uiSetPanelHandler(VIEW3D_HANDLER_BONESKETCH); // for close and esc @@ -2327,66 +2335,73 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockEndAlign(block); uiBlockBeginAlign(block); - - uiDefButC(block, ROW, B_REDR, "Length", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_LENGTH, 0, 0, "Subdivide arcs in bones of equal length"); - uiDefButF(block, NUM, B_REDR, "Lim:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the subdivided bones"); - yco -= 20; - - uiDefButC(block, ROW, B_REDR, "Correlation", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_CORRELATION, 0, 0, "Subdivide arcs based on correlation"); - uiDefButF(block, NUM, B_REDR, "Thres:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Correlation threshold for subdivision"); - yco -= 20; - - uiDefButC(block, ROW, B_REDR, "Fixed", 10, yco, 60, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_CUT_FIXED, 0, 0, "Subdivide arcs based on a fixed number of bones"); - uiDefButC(block, NUM, B_REDR, "Num:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Number of subdivided bones"); - yco -= 20; - - uiDefButC(block, ROW, B_REDR, "Retarget", 10, yco,80, 19, &G.scene->toolsettings->bone_sketching_convert, 0, SK_CONVERT_RETARGET, 0, 0, "Retarget selected bones to stroke"); - uiDefButC(block, ROW, B_DIFF, "No", 90, yco, 40,19, &G.scene->toolsettings->skgen_retarget_roll, 0, 0, 0, 0, "No special roll treatment"); - uiDefButC(block, ROW, B_DIFF, "View", 130, yco, 40,19, &G.scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_VIEW, 0, 0, "Roll bones perpendicular to view"); - uiDefButC(block, ROW, B_DIFF, "Joint", 170, yco, 40,19, &G.scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_JOINT, 0, 0, "Roll bones relative to joint bend"); - yco -= 20; - - uiBlockEndAlign(block); - - yco -= 10; - uiBlockBeginAlign(block); - /* button here to select what to do (copy or not), template, ...*/ + uiDefButC(block, MENU, B_REDR, "Subdivision Method%t|Length%x2|Correlation%x3|Fixed%x1|Template%x4", 10,yco,60,19, &G.scene->toolsettings->bone_sketching_convert, 0, 0, 0, 0, subdiv_tooltip[(unsigned char)G.scene->toolsettings->bone_sketching_convert]); - BIF_makeListTemplates(); - template_index = BIF_currentTemplate(); - - but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(), 10,yco,200,19, &template_index, 0, 0, 0, 0, "Template"); - uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL); - - yco -= 20; - - uiDefButF(block, NUM, B_DIFF, "A:", 10, yco, 66,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); - uiDefButF(block, NUM, B_DIFF, "L:", 76, yco, 67,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); - uiDefButF(block, NUM, B_DIFF, "D:", 143,yco, 67,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); - yco -= 20; - - uiDefBut(block, TEX,B_DIFF,"S:", 10, yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with"); - uiDefBut(block, TEX,B_DIFF,"N:", 100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with"); - uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,190,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming"); - yco -= 20; - - /* auto renaming magic */ - uiBlockEndAlign(block); - - nb_joints = BIF_nbJointsTemplate(); - - if (nb_joints == -1) + switch(G.scene->toolsettings->bone_sketching_convert) { - nb_joints = G.totvertsel; + case SK_CONVERT_CUT_LENGTH: + uiDefButF(block, NUM, B_REDR, "Lim:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the subdivided bones"); + yco -= 20; + break; + case SK_CONVERT_CUT_CORRELATION: + uiDefButF(block, NUM, B_REDR, "Thres:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Correlation threshold for subdivision"); + yco -= 20; + break; + default: + case SK_CONVERT_CUT_FIXED: + uiDefButC(block, NUM, B_REDR, "Num:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5, "Number of subdivided bones"); + yco -= 20; + break; + case SK_CONVERT_RETARGET: + uiDefButC(block, ROW, B_DIFF, "No", 70, yco, 40,19, &G.scene->toolsettings->skgen_retarget_roll, 0, 0, 0, 0, "No special roll treatment"); + uiDefButC(block, ROW, B_DIFF, "View", 110, yco, 50,19, &G.scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_VIEW, 0, 0, "Roll bones perpendicular to view"); + uiDefButC(block, ROW, B_DIFF, "Joint", 160, yco, 50,19, &G.scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_JOINT, 0, 0, "Roll bones relative to joint bend"); + yco -= 30; + + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + /* button here to select what to do (copy or not), template, ...*/ + + BIF_makeListTemplates(); + template_index = BIF_currentTemplate(); + + but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(), 10,yco,200,19, &template_index, 0, 0, 0, 0, "Template"); + uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL); + + yco -= 20; + + uiDefButF(block, NUM, B_DIFF, "A:", 10, yco, 66,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0, "Angle Weight"); + uiDefButF(block, NUM, B_DIFF, "L:", 76, yco, 67,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0, "Length Weight"); + uiDefButF(block, NUM, B_DIFF, "D:", 143,yco, 67,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0, "Distance Weight"); + yco -= 20; + + uiDefBut(block, TEX,B_DIFF,"S:", 10, yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with"); + uiDefBut(block, TEX,B_DIFF,"N:", 100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with"); + uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,190,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming"); + yco -= 20; + + /* auto renaming magic */ + uiBlockEndAlign(block); + + nb_joints = BIF_nbJointsTemplate(); + + if (nb_joints == -1) + { + nb_joints = G.totvertsel; + } + + bone_name = BIF_nameBoneTemplate(); + + BLI_snprintf(joint_label, 32, "%i joints: %s", nb_joints, bone_name); + + uiDefBut(block, LABEL, 1, joint_label, 10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, ""); + yco -= 20; + break; } - - bone_name = BIF_nameBoneTemplate(); - - BLI_snprintf(joint_label, 32, "%i joints: %s", nb_joints, bone_name); - - uiDefBut(block, LABEL, 1, joint_label, 10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, ""); - yco -= 20; + + uiBlockEndAlign(block); uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_DIFF, "Peel Objects", 10, yco, 200, 20, &G.scene->snap_flag, 0, 0, 0, 0, "Peel whole objects as one"); From fe1c4ecd890b3affde13a8e59d507377060266fc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 4 Feb 2009 06:41:48 +0000 Subject: [PATCH 158/252] Relative option for the blur node only applied when the UI updated. This meant that changing the image size later on would still use the old size. Set the relative blur size when executing the node too. --- source/blender/nodes/intern/CMP_nodes/CMP_blur.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c index e7e799b6e76..f9be9533658 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c @@ -567,6 +567,11 @@ static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bN if(out[0]->hasoutput==0) return; + if(nbd->relative) { + nbd->sizex= (int)(nbd->percentx*nbd->image_in_width); + nbd->sizey= (int)(nbd->percenty*nbd->image_in_height); + } + if (((NodeBlurData *)node->storage)->filtertype == R_FILTER_FAST_GAUSS) { CompBuf *new, *img = in[0]->data; /*from eeshlo's original patch, removed to fit in with the existing blur node */ From 8837d69ed3628937ce2c68f14c6e16e6ded23766 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 4 Feb 2009 17:56:31 +0000 Subject: [PATCH 159/252] Bugfix #18251 Patch from Konrad Kleine After read-home file (or restore factory settings) the opengl lights have to be reset. --- source/blender/src/usiblender.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 16c26336b89..6a4c72d1d4b 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -668,6 +668,12 @@ int BIF_read_homefile(int from_memory) success = BKE_read_file_from_memory(datatoc_B_blend, datatoc_B_blend_size, NULL); /* outliner patch for 2.42 .b.blend */ outliner_242_patch(); + + /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ + U.light[0].flag=0; + U.light[1].flag=0; + U.light[2].flag=0; + GPU_default_lights(); } BLI_clean(scestr); From e25318ebefb4dd34443430ab0b7408d3a6118b3d Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 4 Feb 2009 21:38:03 +0000 Subject: [PATCH 160/252] Rename correlation subdividing method into adaptative subdividing method, since that's what it's trying to do and much more understandable from a user's pov. --- source/blender/include/BIF_generate.h | 2 +- source/blender/makesdna/DNA_scene_types.h | 2 +- source/blender/src/drawview.c | 4 ++-- source/blender/src/editarmature.c | 2 +- source/blender/src/editarmature_generate.c | 2 +- source/blender/src/editarmature_sketch.c | 8 ++++---- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/source/blender/include/BIF_generate.h b/source/blender/include/BIF_generate.h index 32d89d32f78..e64edf99bdc 100644 --- a/source/blender/include/BIF_generate.h +++ b/source/blender/include/BIF_generate.h @@ -34,7 +34,7 @@ float calcArcCorrelation(struct BArcIterator *iter, int start, int end, float v0 int nextFixedSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); int nextLengthSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); -int nextCorrelationSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); +int nextAdaptativeSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]); struct EditBone * subdivideArcBy(struct bArmature *arm, ListBase *editbones, struct BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2d5097e7899..c6dff387c49 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -886,7 +886,7 @@ typedef struct Scene { /* toolsettings->bone_sketching_convert */ #define SK_CONVERT_CUT_FIXED 1 #define SK_CONVERT_CUT_LENGTH 2 -#define SK_CONVERT_CUT_CORRELATION 3 +#define SK_CONVERT_CUT_ADAPTATIVE 3 #define SK_CONVERT_RETARGET 4 /* toolsettings->skgen_retarget_options */ diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index c8701d2aa98..8f38d752719 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2336,7 +2336,7 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiBlockBeginAlign(block); - uiDefButC(block, MENU, B_REDR, "Subdivision Method%t|Length%x2|Correlation%x3|Fixed%x1|Template%x4", 10,yco,60,19, &G.scene->toolsettings->bone_sketching_convert, 0, 0, 0, 0, subdiv_tooltip[(unsigned char)G.scene->toolsettings->bone_sketching_convert]); + uiDefButC(block, MENU, B_REDR, "Subdivision Method%t|Length%x2|Adaptative%x3|Fixed%x1|Template%x4", 10,yco,60,19, &G.scene->toolsettings->bone_sketching_convert, 0, 0, 0, 0, subdiv_tooltip[(unsigned char)G.scene->toolsettings->bone_sketching_convert]); switch(G.scene->toolsettings->bone_sketching_convert) { @@ -2344,7 +2344,7 @@ static void view3d_panel_bonesketch_spaces(short cntrl) uiDefButF(block, NUM, B_REDR, "Lim:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0, "Maximum length of the subdivided bones"); yco -= 20; break; - case SK_CONVERT_CUT_CORRELATION: + case SK_CONVERT_CUT_ADAPTATIVE: uiDefButF(block, NUM, B_REDR, "Thres:", 70, yco, 140, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0, "Correlation threshold for subdivision"); yco -= 20; break; diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 4521c9a8312..ec14e2aabe2 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -4737,7 +4737,7 @@ EditBone * test_subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *t initArcIterator(iter, arc, head); - lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextCorrelationSubdivision); + lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextAdaptativeSubdivision); } return lastBone; diff --git a/source/blender/src/editarmature_generate.c b/source/blender/src/editarmature_generate.c index c6e77488212..189a823ab98 100644 --- a/source/blender/src/editarmature_generate.c +++ b/source/blender/src/editarmature_generate.c @@ -177,7 +177,7 @@ int nextFixedSubdivision(BArcIterator *iter, int start, int end, float head[3], return -1; } -int nextCorrelationSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3]) +int nextAdaptativeSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3]) { float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit; float *start_p; diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 73d952b9cbd..80302109b37 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -1316,9 +1316,9 @@ void sk_drawStrokeSubdivision(SK_Stroke *stk) initStrokeIterator(iter, stk, head_index, i); - if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE) { - drawSubdividedStrokeBy(iter, nextCorrelationSubdivision); + drawSubdividedStrokeBy(iter, nextAdaptativeSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { @@ -2214,9 +2214,9 @@ void sk_convertStroke(SK_Stroke *stk) initStrokeIterator(iter, stk, head_index, i); - if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION) + if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE) { - bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextCorrelationSubdivision); + bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextAdaptativeSubdivision); } else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { From fbdd75a4756423a1f884c4738defa31781513823 Mon Sep 17 00:00:00 2001 From: Robin Allen Date: Fri, 6 Feb 2009 00:55:38 +0000 Subject: [PATCH 161/252] Added compose/decompose, fixed bugs. --- source/blender/blenkernel/BKE_node.h | 2 + source/blender/blenkernel/intern/node.c | 2 + source/blender/nodes/TEX_node.h | 3 + .../nodes/intern/TEX_nodes/TEX_compose.c | 71 ++++++++++++++ .../nodes/intern/TEX_nodes/TEX_decompose.c | 92 +++++++++++++++++++ .../nodes/intern/TEX_nodes/TEX_hueSatVal.c | 34 ++++--- .../blender/nodes/intern/TEX_nodes/TEX_proc.c | 34 +++---- 7 files changed, 206 insertions(+), 32 deletions(-) create mode 100644 source/blender/nodes/intern/TEX_nodes/TEX_compose.c create mode 100644 source/blender/nodes/intern/TEX_nodes/TEX_decompose.c diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 1c5b6b124b2..c36590fae86 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -403,6 +403,8 @@ struct TexResult; #define TEX_NODE_TRANSLATE 116 #define TEX_NODE_COORD 117 #define TEX_NODE_DISTANCE 118 +#define TEX_NODE_COMPOSE 119 +#define TEX_NODE_DECOMPOSE 120 /* 201-299 reserved. Use like this: TEX_NODE_PROC + TEX_CLOUDS, etc */ #define TEX_NODE_PROC 200 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 4c84c56180c..25d921bb783 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2888,6 +2888,8 @@ static void registerTextureNodes(ListBase *ntypelist) nodeRegisterType(ntypelist, &tex_node_hue_sat); nodeRegisterType(ntypelist, &tex_node_coord); nodeRegisterType(ntypelist, &tex_node_distance); + nodeRegisterType(ntypelist, &tex_node_compose); + nodeRegisterType(ntypelist, &tex_node_decompose); nodeRegisterType(ntypelist, &tex_node_output); nodeRegisterType(ntypelist, &tex_node_viewer); diff --git a/source/blender/nodes/TEX_node.h b/source/blender/nodes/TEX_node.h index 40cb65eacce..d667cd26a76 100644 --- a/source/blender/nodes/TEX_node.h +++ b/source/blender/nodes/TEX_node.h @@ -58,6 +58,9 @@ extern bNodeType tex_node_distance; extern bNodeType tex_node_rotate; extern bNodeType tex_node_translate; +extern bNodeType tex_node_compose; +extern bNodeType tex_node_decompose; + extern bNodeType tex_node_proc_voronoi; extern bNodeType tex_node_proc_blend; extern bNodeType tex_node_proc_magic; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_compose.c b/source/blender/nodes/intern/TEX_nodes/TEX_compose.c new file mode 100644 index 00000000000..bb7a654b41f --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_compose.c @@ -0,0 +1,71 @@ +/** + * + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../TEX_util.h" + +static bNodeSocketType inputs[]= { + { SOCK_VALUE, 1, "Red", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Green", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Blue", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; +static bNodeSocketType outputs[]= { + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; + +static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + int i; + for(i = 0; i < 4; i++) + out[i] = tex_input_value(in[i], coord, thread); +} + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &colorfn); +} + +bNodeType tex_node_compose= { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_COMPOSE, + /* name */ "Compose RGBA", + /* width+range */ 100, 60, 150, + /* class+opts */ NODE_CLASS_OP_COLOR, 0, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL + +}; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c b/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c new file mode 100644 index 00000000000..3a4710ce98f --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c @@ -0,0 +1,92 @@ +/** + * + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../TEX_util.h" +#include + +static bNodeSocketType inputs[]= { + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; +static bNodeSocketType outputs[]= { + { SOCK_VALUE, 1, "Red", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Green", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Blue", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; + +static void valuefn_r(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + tex_input_rgba(out, in[0], coord, thread); + *out = out[0]; +} + +static void valuefn_g(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + tex_input_rgba(out, in[0], coord, thread); + *out = out[1]; +} + +static void valuefn_b(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + tex_input_rgba(out, in[0], coord, thread); + *out = out[2]; +} + +static void valuefn_a(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + tex_input_rgba(out, in[0], coord, thread); + *out = out[3]; +} + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &valuefn_r); + tex_output(node, in, out[1], &valuefn_g); + tex_output(node, in, out[2], &valuefn_b); + tex_output(node, in, out[3], &valuefn_a); +} + +bNodeType tex_node_decompose= { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_DECOMPOSE, + /* name */ "Decompose RGBA", + /* width+range */ 100, 60, 150, + /* class+opts */ NODE_CLASS_OP_COLOR, 0, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL + +}; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c b/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c index d1a33896fc3..bb1a49fb235 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c @@ -30,16 +30,16 @@ static bNodeSocketType inputs[]= { - { SOCK_VALUE, 1, "Hue", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VALUE, 1, "Saturation", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f}, - { SOCK_VALUE, 1, "Value", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f}, - { SOCK_VALUE, 1, "Fac", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 1, "Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { SOCK_VALUE, 1, "Hue", 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f }, + { SOCK_VALUE, 1, "Saturation", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f }, + { SOCK_VALUE, 1, "Value", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f }, + { SOCK_VALUE, 1, "Factor", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_RGBA, 1, "Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } }; static bNodeSocketType outputs[]= { - { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { -1, 0, "" } }; static void do_hue_sat_fac(bNode *node, float *out, float hue, float sat, float val, float *in, float fac) @@ -67,15 +67,19 @@ static void do_hue_sat_fac(bNode *node, float *out, float hue, float sat, float static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) { - float in0 = tex_input_value(in[0], coord, thread); - float in1 = tex_input_value(in[1], coord, thread); - float in2 = tex_input_value(in[2], coord, thread); - float in3 = tex_input_value(in[3], coord, thread); + float hue = tex_input_value(in[0], coord, thread); + float sat = tex_input_value(in[1], coord, thread); + float val = tex_input_value(in[2], coord, thread); + float fac = tex_input_value(in[3], coord, thread); - float in4[4]; - tex_input_rgba(in4, in[4], coord, thread); + float col[4]; + tex_input_rgba(col, in[4], coord, thread); - do_hue_sat_fac(node, out, in0, in1, in2, in4, in3); + hue += 0.5f; /* [-.5, .5] -> [0, 1] */ + + do_hue_sat_fac(node, out, hue, sat, val, col, fac); + + out[3] = col[3]; } static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_proc.c b/source/blender/nodes/intern/TEX_nodes/TEX_proc.c index 9078dd1be21..ec65cf186a8 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_proc.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_proc.c @@ -110,25 +110,25 @@ static int count_outputs(bNode *node) /* Boilerplate generators */ #define ProcNoInputs(name) \ - static void name##_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread) \ - {} + static void name##_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread) \ + {} #define ProcDef(name) \ - static void name##_colorfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \ - { \ - texfn(result, coord, node, in, 0, &name##_map_inputs, thread); \ - } \ - static void name##_normalfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \ - { \ - texfn(result, coord, node, in, 1, &name##_map_inputs, thread); \ - } \ - static void name##_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) \ - { \ - int outs = count_outputs(node); \ - if(outs >= 1) tex_output(node, in, out[0], &name##_colorfn); \ - if(outs >= 2) tex_output(node, in, out[1], &name##_normalfn); \ - if(outs >= 1) tex_do_preview(node, out[0], data); \ - } + static void name##_colorfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \ + { \ + texfn(result, coord, node, in, 0, &name##_map_inputs, thread); \ + } \ + static void name##_normalfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \ + { \ + texfn(result, coord, node, in, 1, &name##_map_inputs, thread); \ + } \ + static void name##_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) \ + { \ + int outs = count_outputs(node); \ + if(outs >= 1) tex_output(node, in, out[0], &name##_colorfn); \ + if(outs >= 2) tex_output(node, in, out[1], &name##_normalfn); \ + if(outs >= 1) tex_do_preview(node, out[0], data); \ + } /* --- VORONOI -- */ From 6a669d00b230901f3d0a0aba3aeac8eafde7ca84 Mon Sep 17 00:00:00 2001 From: Robin Allen Date: Fri, 6 Feb 2009 01:21:38 +0000 Subject: [PATCH 162/252] Patch #18015, adds "Value to Normal" node --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/nodes/TEX_node.h | 1 + .../nodes/intern/TEX_nodes/TEX_valToNor.c | 92 +++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 source/blender/nodes/intern/TEX_nodes/TEX_valToNor.c diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index c36590fae86..20a9fae33bb 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -405,6 +405,7 @@ struct TexResult; #define TEX_NODE_DISTANCE 118 #define TEX_NODE_COMPOSE 119 #define TEX_NODE_DECOMPOSE 120 +#define TEX_NODE_VALTONOR 121 /* 201-299 reserved. Use like this: TEX_NODE_PROC + TEX_CLOUDS, etc */ #define TEX_NODE_PROC 200 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 25d921bb783..14111f2c175 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2882,6 +2882,7 @@ static void registerTextureNodes(ListBase *ntypelist) nodeRegisterType(ntypelist, &tex_node_mix_rgb); nodeRegisterType(ntypelist, &tex_node_valtorgb); nodeRegisterType(ntypelist, &tex_node_rgbtobw); + nodeRegisterType(ntypelist, &tex_node_valtonor); nodeRegisterType(ntypelist, &tex_node_curve_rgb); nodeRegisterType(ntypelist, &tex_node_curve_time); nodeRegisterType(ntypelist, &tex_node_invert); diff --git a/source/blender/nodes/TEX_node.h b/source/blender/nodes/TEX_node.h index d667cd26a76..3fae2703f0d 100644 --- a/source/blender/nodes/TEX_node.h +++ b/source/blender/nodes/TEX_node.h @@ -41,6 +41,7 @@ extern bNodeType tex_node_math; extern bNodeType tex_node_mix_rgb; extern bNodeType tex_node_valtorgb; +extern bNodeType tex_node_valtonor; extern bNodeType tex_node_rgbtobw; extern bNodeType tex_node_output; extern bNodeType tex_node_viewer; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_valToNor.c b/source/blender/nodes/intern/TEX_nodes/TEX_valToNor.c new file mode 100644 index 00000000000..f63f5682030 --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_valToNor.c @@ -0,0 +1,92 @@ +/** + * + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Jucas. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../TEX_util.h" + +static bNodeSocketType inputs[]= { + { SOCK_VALUE, 1, "Val", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 1, "Nabla", 0.025f, 0.0f, 0.0f, 0.0f, 0.001f, 0.1f }, + { -1, 0, "" } +}; + +static bNodeSocketType outputs[]= { + { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, + { -1, 0, "" } +}; + +static void normalfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + float new_coord[3]; + + float nabla = tex_input_value(in[1], coord, thread); + float val; + float nor[2]; + + val = tex_input_value(in[0], coord, thread); + + new_coord[0] = coord[0] + nabla; + new_coord[1] = coord[1]; + new_coord[2] = coord[2]; + nor[0] = tex_input_value(in[0], new_coord, thread); + + new_coord[0] = coord[0]; + new_coord[1] = coord[1] + nabla; + nor[1] = tex_input_value(in[0], new_coord, thread); + + new_coord[1] = coord[1]; + new_coord[2] = coord[2] + nabla; + nor[2] = tex_input_value(in[0], new_coord, thread); + + out[0] = val-nor[0]; + out[1] = val-nor[1]; + out[2] = val-nor[2]; +} +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &normalfn); + + tex_do_preview(node, out[0], data); +} + +bNodeType tex_node_valtonor = { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_VALTONOR, + /* name */ "Value to Normal", + /* width+range */ 90, 80, 100, + /* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL +}; + From 8f70b931244de5b78f620b2e5a63f46927cd10e2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 6 Feb 2009 14:03:29 +0000 Subject: [PATCH 163/252] 2.4x Sequencer Python API - add metastrips now possible - access to speed options - access to wipe options - added seq.startDisp seq.endDisp seq.update() --- source/blender/python/api2_2x/sceneSequence.c | 1797 ++++++++++------- 1 file changed, 1065 insertions(+), 732 deletions(-) diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index 5be3a1479a6..8775ae9dc63 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -54,7 +54,8 @@ #include "IMB_imbuf_types.h" // RFS: IB_rect #include "IMB_imbuf.h" // RFS: IMB_anim_get_duration -enum seq_consts { +enum seq_consts +{ EXPP_SEQ_ATTR_TYPE = 0, EXPP_SEQ_ATTR_CHAN, EXPP_SEQ_ATTR_LENGTH, @@ -62,7 +63,23 @@ enum seq_consts { EXPP_SEQ_ATTR_STARTOFS, EXPP_SEQ_ATTR_ENDOFS, EXPP_SEQ_ATTR_STARTSTILL, - EXPP_SEQ_ATTR_ENDSTILL + EXPP_SEQ_ATTR_ENDSTILL, + EXPP_SEQ_ATTR_STARTDISP, + EXPP_SEQ_ATTR_ENDDISP +}; + +enum seq_effect_consts +{ + /* speed */ + EXPP_SEQ_ATTR_EFFECT_GLOBAL_SPEED, + EXPP_SEQ_ATTR_EFFECT_IPO_IS_VELOCITY, + EXPP_SEQ_ATTR_EFFECT_FRAME_BLENDING, + EXPP_SEQ_ATTR_EFFECT_NORMALIZE_IPO_0_1, + + /* wipe */ + EXPP_SEQ_ATTR_EFFECT_ANGLE, + EXPP_SEQ_ATTR_EFFECT_BLUR, + EXPP_SEQ_ATTR_EFFECT_WIPE_IN }; @@ -84,141 +101,200 @@ returns None if notfound.\nIf 'name' is not specified, it returns a list of all /*****************************************************************************/ /* Python BPy_Sequence methods table: */ /*****************************************************************************/ -static PyObject *Sequence_copy( BPy_Sequence * self ); -static PyObject *Sequence_new( BPy_Sequence * self, PyObject * args ); -static PyObject *Sequence_remove( BPy_Sequence * self, PyObject * args ); -static PyObject *Sequence_rebuildProxy( BPy_Sequence * self ); +static PyObject *Sequence_copy(BPy_Sequence * self); +static PyObject *Sequence_update(BPy_Sequence * self); +static PyObject *Sequence_new(BPy_Sequence * self, PyObject * args); +static PyObject *Sequence_remove(BPy_Sequence * self, PyObject * args); +static PyObject *Sequence_rebuildProxy(BPy_Sequence * self); -static PyObject *SceneSeq_new( BPy_SceneSeq * self, PyObject * args ); -static PyObject *SceneSeq_remove( BPy_SceneSeq * self, PyObject * args ); -static void intern_pos_update(Sequence * seq); +static PyObject *SceneSeq_new(BPy_SceneSeq * self, PyObject * args); +static PyObject *SceneSeq_remove(BPy_SceneSeq * self, PyObject * args); +static void intern_pos_update(Sequence * seq); static PyMethodDef BPy_Sequence_methods[] = { /* name, method, flags, doc */ - {"new", ( PyCFunction ) Sequence_new, METH_VARARGS, - "(data) - Return a new sequence."}, - {"remove", ( PyCFunction ) Sequence_remove, METH_VARARGS, - "(data) - Remove a strip."}, - {"__copy__", ( PyCFunction ) Sequence_copy, METH_NOARGS, - "() - Return a copy of the sequence containing the same objects."}, - {"copy", ( PyCFunction ) Sequence_copy, METH_NOARGS, - "() - Return a copy of the sequence containing the same objects."}, - {"rebuildProxy", ( PyCFunction ) Sequence_rebuildProxy, METH_VARARGS, - "() - Rebuild the active strip's Proxy."}, + {"new", (PyCFunction) Sequence_new, METH_VARARGS, + "(data) - Return a new sequence."}, + {"remove", (PyCFunction) Sequence_remove, METH_VARARGS, + "(data) - Remove a strip."}, + {"__copy__", (PyCFunction) Sequence_copy, METH_NOARGS, + "() - Return a copy of the sequence containing the same objects."}, + {"copy", (PyCFunction) Sequence_copy, METH_NOARGS, + "() - Return a copy of the sequence containing the same objects."}, + {"update", (PyCFunction) Sequence_update, METH_NOARGS, + "() - Force and update of the sequence strip"}, + {"rebuildProxy", (PyCFunction) Sequence_rebuildProxy, METH_VARARGS, + "() - Rebuild the active strip's Proxy."}, {NULL, NULL, 0, NULL} }; static PyMethodDef BPy_SceneSeq_methods[] = { /* name, method, flags, doc */ - {"new", ( PyCFunction ) SceneSeq_new, METH_VARARGS, - "(data) - Return a new sequence."}, - {"remove", ( PyCFunction ) SceneSeq_remove, METH_VARARGS, - "(data) - Remove a strip."}, + {"new", (PyCFunction) SceneSeq_new, METH_VARARGS, + "(data) - Return a new sequence."}, + {"remove", (PyCFunction) SceneSeq_remove, METH_VARARGS, + "(data) - Remove a strip."}, {NULL, NULL, 0, NULL} }; - /* use to add a sequence to a scene or its listbase */ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) { PyObject *py_data = NULL; - + Sequence *seq; - PyObject *pyob1= NULL, *pyob2= NULL, *pyob3= NULL; /* for effects */ + PyObject *pyob1 = NULL, *pyob2 = NULL, *pyob3 = NULL; /* for effects */ int type; int a; Strip *strip; StripElem *se; int start, machine; - - if( !PyArg_ParseTuple( args, "Oii", &py_data, &start, &machine ) ) - return EXPP_ReturnPyObjError( PyExc_ValueError, - "expect sequence data then 2 ints - (seqdata, start, track)" ); - if (machine < 1 || machine >= MAXSEQ) { - return EXPP_ReturnPyObjError( PyExc_ValueError, - "track out of range" ); + if (!PyArg_ParseTuple(args, "Oii", &py_data, &start, &machine)) + return EXPP_ReturnPyObjError(PyExc_ValueError, + "expect sequence data then 2 ints - (seqdata, start, track)"); + + if (machine < 1 || machine >= MAXSEQ) + { + return EXPP_ReturnPyObjError(PyExc_ValueError, + "track out of range"); } seq = alloc_sequence(seqbase, start, machine); /* warning, this sets last */ - if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) >= 2 && BPy_Sequence_Check(PyTuple_GET_ITEM(py_data, 1))) { - + if (PyList_Check(py_data)) /* new metastrip, list of seqs */ + { + /* Warning, no checks for audio which should not be allowed, or a blank metaseq if an empty list */ + int fail= 0; + Sequence *seq_iter; + PyObject *item; + seq->type= SEQ_META; + + + for(a=PyList_GET_SIZE(py_data)-1; a >= 0; a--) { + item= PyList_GET_ITEM(py_data, a); + if (!BPy_Sequence_Check(item)) { /* ignore non seq types */ + fail= 1; + break; + } + + seq_iter = ((BPy_Sequence *) item)->seq; + if (BLI_findindex(seqbase, seq_iter) == -1) { + fail= 2; + break; + } + } + + if (fail) { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + if (fail==1) + return EXPP_ReturnPyObjError(PyExc_ValueError, "One of more of the list items was not a sequence strip"); + else + return EXPP_ReturnPyObjError(PyExc_ValueError, "One of more of the list items sequence strips is not in this meta or scene"); + } + + + for(a=PyList_GET_SIZE(py_data)-1; a >= 0; a--) { + item= PyList_GET_ITEM(py_data, a); + seq_iter = ((BPy_Sequence *) item)->seq; + BLI_remlink(seqbase, seq_iter); + BLI_addtail(&seq->seqbase, seq_iter); + } + + clear_last_seq(); /* just incase */ + calc_sequence(seq); + + seq->strip= MEM_callocN(sizeof(Strip), "metastrip"); + seq->strip->len= seq->len; + seq->strip->us= 1; + } + else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) >= 2 && BPy_Sequence_Check(PyTuple_GET_ITEM(py_data, 1))) + { + struct SeqEffectHandle sh; - Sequence *seq1, *seq2= NULL, *seq3= NULL; /* for effects */ + Sequence *seq1, *seq2 = NULL, *seq3 = NULL; /* for effects */ - if (!PyArg_ParseTuple( py_data, "iO!|O!O!", &type, &Sequence_Type, &pyob1, &Sequence_Type, &pyob2, &Sequence_Type, &pyob3)) { + if (!PyArg_ParseTuple(py_data, "iO!|O!O!", &type, &Sequence_Type, &pyob1, &Sequence_Type, &pyob2, &Sequence_Type, &pyob3)) + { BLI_remlink(seqbase, seq); free_sequence(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "effect stripts expected an effect type int and 1 to 3 sequence strips"); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "effect stripts expected an effect type int and 1 to 3 sequence strips"); } - seq1= ((BPy_Sequence *)pyob1)->seq; - if(pyob2) seq2= ((BPy_Sequence *)pyob2)->seq; - if(pyob3) seq3= ((BPy_Sequence *)pyob3)->seq; + seq1 = ((BPy_Sequence *) pyob1)->seq; + if (pyob2) seq2 = ((BPy_Sequence *) pyob2)->seq; + if (pyob3) seq3 = ((BPy_Sequence *) pyob3)->seq; - if (type <= SEQ_EFFECT || type > SEQ_EFFECT_MAX || type==SEQ_PLUGIN){ + if (type <= SEQ_EFFECT || type > SEQ_EFFECT_MAX || type == SEQ_PLUGIN) + { BLI_remlink(seqbase, seq); free_sequence(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "sequencer type out of range, expected a value from 9 to 29, plugins not supported"); - } - - if (BLI_findindex(seqbase, seq1)==-1 || (seq2 && BLI_findindex(seqbase, seq2)==-1) || (seq3 && BLI_findindex(seqbase, seq3)==-1)) { - BLI_remlink(seqbase, seq); - free_sequence(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "one of the given effect sequences wasnt in accessible at the same level as the sequence being added"); + return EXPP_ReturnPyObjError(PyExc_ValueError, + "sequencer type out of range, expected a value from 9 to 29, plugins not supported"); } - if ((seq2 && seq2==seq1) || (seq3 && (seq3==seq1 || seq3==seq2))) { + + if (BLI_findindex(seqbase, seq1) == -1 || (seq2 && BLI_findindex(seqbase, seq2) == -1) || (seq3 && BLI_findindex(seqbase, seq3) == -1)) + { BLI_remlink(seqbase, seq); free_sequence(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "2 or more of the sequence arguments were the same"); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "one of the given effect sequences wasnt in accessible at the same level as the sequence being added"); + } + + if ((seq2 && seq2 == seq1) || (seq3 && (seq3 == seq1 || seq3 == seq2))) + { + BLI_remlink(seqbase, seq); + free_sequence(seq); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "2 or more of the sequence arguments were the same"); } /* allocate and initialize */ - seq->type= type; + seq->type = type; sh = get_sequence_effect(seq); - seq->seq1= seq1; - seq->seq2= seq2; - seq->seq3= seq3; + seq->seq1 = seq1; + seq->seq2 = seq2; + seq->seq3 = seq3; sh.init(seq); - if (!seq1) { - seq->len= 1; - seq->startstill= 25; - seq->endstill= 24; + if (!seq1) + { + seq->len = 1; + seq->startstill = 25; + seq->endstill = 24; } calc_sequence(seq); - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= seq->len; - strip->us= 1; - if(seq->len>0) - strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strip->len = seq->len; + strip->us = 1; + if (seq->len > 0) + strip->stripdata = MEM_callocN(seq->len * sizeof (StripElem), "stripelem"); #if 0 /* initialize plugin */ - if(newseq->type == SEQ_PLUGIN) { + if (newseq->type == SEQ_PLUGIN) + { sh.init_plugin(seq, str); - if(newseq->plugin==0) { + if (newseq->plugin == 0) + { BLI_remlink(ed->seqbasep, seq); free_sequence(seq); return 0; @@ -228,66 +304,75 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) update_changed_seq_and_deps(seq, 1, 1); - } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 2) { + } + else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 2) + { /* Image */ PyObject *list; char *name; - - if (!PyArg_ParseTuple( py_data, "sO!", &name, &PyList_Type, &list)) { + + if (!PyArg_ParseTuple(py_data, "sO!", &name, &PyList_Type, &list)) + { BLI_remlink(seqbase, seq); free_sequence(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "images data needs to be a tuple of a string and a list of images - (path, [filenames...])" ); - } - - seq->type= SEQ_IMAGE; - - seq->len = PyList_Size( list ); - - /* strip and stripdata */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= seq->len; - strip->us= 1; - strncpy(strip->dir, name, FILE_MAXDIR-1); - strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - for(a=0; alen; a++) { - name = PyString_AsString(PyList_GetItem( list, a )); - strncpy(se->name, name, FILE_MAXFILE-1); + return EXPP_ReturnPyObjError(PyExc_ValueError, + "images data needs to be a tuple of a string and a list of images - (path, [filenames...])"); + } + + seq->type = SEQ_IMAGE; + + seq->len = PyList_Size(list); + + /* strip and stripdata */ + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strip->len = seq->len; + strip->us = 1; + strncpy(strip->dir, name, FILE_MAXDIR - 1); + strip->stripdata = se = MEM_callocN(seq->len * sizeof (StripElem), "stripelem"); + + for (a = 0; a < seq->len; a++) + { + name = PyString_AsString(PyList_GetItem(list, a)); + strncpy(se->name, name, FILE_MAXFILE - 1); se++; - } - } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 3) { - float r,g,b; + } + } + else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 3) + { + float r, g, b; SolidColorVars *colvars; - if (!PyArg_ParseTuple( py_data, "fff", &r, &g, &b)) { + if (!PyArg_ParseTuple(py_data, "fff", &r, &g, &b)) + { BLI_remlink(seqbase, seq); free_sequence(seq); - return EXPP_ReturnPyObjError( PyExc_ValueError, - "color needs to be a tuple of 3 floats - (r,g,b)" ); + return EXPP_ReturnPyObjError(PyExc_ValueError, + "color needs to be a tuple of 3 floats - (r,g,b)"); } - seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor"); - colvars= (SolidColorVars *)seq->effectdata; + seq->effectdata = MEM_callocN(sizeof (struct SolidColorVars), "solidcolor"); + colvars = (SolidColorVars *) seq->effectdata; + + seq->type = SEQ_COLOR; + + CLAMP(r, 0, 1); + CLAMP(g, 0, 1); + CLAMP(b, 0, 1); - seq->type= SEQ_COLOR; - - CLAMP(r,0,1); - CLAMP(g,0,1); - CLAMP(b,0,1); - colvars->col[0] = r; colvars->col[1] = b; colvars->col[2] = g; - + /* basic defaults */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); strip->len = seq->len = 1; - 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) { + 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; @@ -295,150 +380,159 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) char *type; int totframe; - if (!PyArg_ParseTuple( py_data, "ssss", &filename, &dir, &fullpath, &type )) { + if (!PyArg_ParseTuple(py_data, "ssss", &filename, &dir, &fullpath, &type)) + { BLI_remlink(seqbase, seq); free_sequence(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)" ); + + 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 ) + if (strcmp(type, "movie") == 0) { /* open it as an animation */ struct anim * an = openanim(fullpath, IB_rect); - if(an==0) { + if (an == 0) + { BLI_remlink(seqbase, seq); free_sequence(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "invalid movie strip" ); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + "invalid movie strip"); } /* get the length in frames */ - totframe = IMB_anim_get_duration( an ); + totframe = IMB_anim_get_duration(an); /* set up sequence */ - seq->type= SEQ_MOVIE; - seq->len= totframe; - seq->anim= an; + 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"); + 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); // ???? + strncpy(se->name, filename, FILE_MAXFILE - 1); // ???? } // Audio (HD) strips - if( strcmp( type, "audio_hd" ) == 0 ) + if (strcmp(type, "audio_hd") == 0) { struct hdaudio *hdaudio; - totframe= 0; + totframe = 0; /* is it a sound file? */ - hdaudio = sound_open_hdaudio( fullpath ); - if(hdaudio==0) { + hdaudio = sound_open_hdaudio(fullpath); + if (hdaudio == 0) + { BLI_remlink(seqbase, seq); free_sequence(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - fullpath ); + + return EXPP_ReturnPyObjError(PyExc_ValueError, + fullpath); } - totframe= sound_hdaudio_get_duration(hdaudio, FPS); + totframe = sound_hdaudio_get_duration(hdaudio, FPS); /* set up sequence */ - seq->type= SEQ_HD_SOUND; - seq->len= totframe; - seq->hdaudio= hdaudio; + 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"); + 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); // ???? + strncpy(se->name, filename, FILE_MAXFILE - 1); // ???? } #endif - } else if (BPy_Sound_Check(py_data)) { + } + else if (BPy_Sound_Check(py_data)) + { /* RAM sound */ int totframe; - bSound *sound = (( BPy_Sound * )py_data)->sound; - - seq->type= SEQ_RAM_SOUND; + bSound *sound = ((BPy_Sound *) py_data)->sound; + + seq->type = SEQ_RAM_SOUND; seq->sound = sound; - - totframe= (int) ( ((float)(sound->streamlen-1)/( (float)sce->audio.mixrate*4.0 ))* (float)sce->r.frs_sec / sce->r.frs_sec_base); - + + totframe = (int) (((float) (sound->streamlen - 1) / ((float) sce->audio.mixrate * 4.0))* (float) sce->r.frs_sec / sce->r.frs_sec_base); + sound->flags |= SOUND_FLAGS_SEQUENCE; - + /* strip and stripdata */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= totframe; - strip->us= 1; - strncpy(strip->dir, sound->name, FILE_MAXDIR-1); - strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strip->len = totframe; + strip->us = 1; + strncpy(strip->dir, sound->name, FILE_MAXDIR - 1); + strip->stripdata = se = MEM_callocN(sizeof (StripElem), "stripelem"); /* name sound in first strip */ - strncpy(se->name, sound->name, FILE_MAXFILE-1); - - } else if (BPy_Scene_Check(py_data)) { - /* scene */ - Scene *sceseq = ((BPy_Scene *)py_data)->scene; - - seq->type= SEQ_SCENE; - seq->scene= sceseq; - - /*seq->sfra= sce->r.sfra;*/ - seq->len= sceseq->r.efra - sceseq->r.sfra + 1; + strncpy(se->name, sound->name, FILE_MAXFILE - 1); - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strncpy(seq->name + 2, sceseq->id.name + 2, - sizeof(seq->name) - 2); - strip->len= seq->len; - strip->us= 1; - } else { + } + else if (BPy_Scene_Check(py_data)) + { + /* scene */ + Scene *sceseq = ((BPy_Scene *) py_data)->scene; + + seq->type = SEQ_SCENE; + seq->scene = sceseq; + + /*seq->sfra= sce->r.sfra;*/ + seq->len = sceseq->r.efra - sceseq->r.sfra + 1; + + seq->strip = strip = MEM_callocN(sizeof (Strip), "strip"); + strncpy(seq->name + 2, sceseq->id.name + 2, + sizeof (seq->name) - 2); + strip->len = seq->len; + strip->us = 1; + } + else + { // RFS: REMOVED MOVIE FROM HERE } - strncpy(seq->name+2, "Untitled", 21); + strncpy(seq->name + 2, "Untitled", 21); intern_pos_update(seq); return Sequence_CreatePyObject(seq, NULL, sce); } -static PyObject *Sequence_new( BPy_Sequence * self, PyObject * args ) +static PyObject *Sequence_new(BPy_Sequence * self, PyObject * args) { return NewSeq_internal(&self->seq->seqbase, args, self->scene); } -static PyObject *SceneSeq_new( BPy_SceneSeq * self, PyObject * args ) +static PyObject *SceneSeq_new(BPy_SceneSeq * self, PyObject * args) { - return NewSeq_internal( &((Editing *)self->scene->ed)->seqbase, args, self->scene); + return NewSeq_internal(&((Editing *) self->scene->ed)->seqbase, args, self->scene); } static void del_seq__internal(Sequence *seq) { - if(seq->ipo) seq->ipo->id.us--; - - if(seq->type==SEQ_RAM_SOUND && seq->sound) + if (seq->ipo) seq->ipo->id.us--; + + if (seq->type == SEQ_RAM_SOUND && seq->sound) seq->sound->id.us--; free_sequence(seq); } @@ -447,433 +541,457 @@ static void recurs_del_seq(ListBase *lb) { Sequence *seq, *seqn; - seq= lb->first; - while(seq) { - seqn= seq->next; + seq = lb->first; + while (seq) + { + seqn = seq->next; BLI_remlink(lb, seq); - if(seq->type==SEQ_META) recurs_del_seq(&seq->seqbase); + if (seq->type == SEQ_META) recurs_del_seq(&seq->seqbase); del_seq__internal(seq); - seq= seqn; + seq = seqn; } } static PyObject *RemoveSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) { BPy_Sequence *bpy_seq = NULL; - - if( !PyArg_ParseTuple( args, "O!", &Sequence_Type, &bpy_seq ) ) - return EXPP_ReturnPyObjError( PyExc_ValueError, - "expects a sequence object" ); - + + if (!PyArg_ParseTuple(args, "O!", &Sequence_Type, &bpy_seq)) + return EXPP_ReturnPyObjError(PyExc_ValueError, + "expects a sequence object"); + /* quick way to tell if we dont have the seq */ if (sce != bpy_seq->scene) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Sequence does not exist here, cannot remove" ); - + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Sequence does not exist here, cannot remove"); + recurs_del_seq(&bpy_seq->seq->seqbase); del_seq__internal(bpy_seq->seq); clear_last_seq(); /* just incase */ Py_RETURN_NONE; } -static PyObject *Sequence_remove( BPy_Sequence * self, PyObject * args ) +static PyObject *Sequence_remove(BPy_Sequence * self, PyObject * args) { return RemoveSeq_internal(&self->seq->seqbase, args, self->scene); } -static PyObject *SceneSeq_remove( BPy_SceneSeq * self, PyObject * args ) +static PyObject *SceneSeq_remove(BPy_SceneSeq * self, PyObject * args) { - return RemoveSeq_internal( &((Editing *)self->scene->ed)->seqbase, args, self->scene); + return RemoveSeq_internal(&((Editing *) self->scene->ed)->seqbase, args, self->scene); } - -static PyObject *Sequence_copy( BPy_Sequence * self ) +static PyObject *Sequence_copy(BPy_Sequence * self) { printf("Sequence Copy not implimented yet!\n"); Py_RETURN_NONE; } +static PyObject *Sequence_update(BPy_Sequence * self) +{ + calc_sequence(self->seq); + calc_sequence_disp(self->seq); + Py_RETURN_NONE; +} + /*****************************************************************************/ /* PythonTypeObject callback function prototypes */ /*****************************************************************************/ -static PyObject *Sequence_repr( BPy_Sequence * obj ); -static PyObject *SceneSeq_repr( BPy_SceneSeq * obj ); -static int Sequence_compare( BPy_Sequence * a, BPy_Sequence * b ); -static int SceneSeq_compare( BPy_SceneSeq * a, BPy_SceneSeq * b ); +static PyObject *Sequence_repr(BPy_Sequence * obj); +static PyObject *SceneSeq_repr(BPy_SceneSeq * obj); +static int Sequence_compare(BPy_Sequence * a, BPy_Sequence * b); +static int SceneSeq_compare(BPy_SceneSeq * a, BPy_SceneSeq * b); /*****************************************************************************/ /* Python BPy_Sequence methods: */ + /*****************************************************************************/ -static PyObject *Sequence_getIter( BPy_Sequence * self ) +static PyObject *Sequence_getIter(BPy_Sequence * self) { Sequence *iter = self->seq->seqbase.first; - - if (!self->iter) { + + if (!self->iter) + { self->iter = iter; - return EXPP_incr_ret ( (PyObject *) self ); - } else { + return EXPP_incr_ret((PyObject *) self); + } + else + { return Sequence_CreatePyObject(self->seq, iter, self->scene); } } -static PyObject *SceneSeq_getIter( BPy_SceneSeq * self ) +static PyObject *SceneSeq_getIter(BPy_SceneSeq * self) { - Sequence *iter = ((Editing *)self->scene->ed)->seqbase.first; - - if (!self->iter) { + Sequence *iter = ((Editing *) self->scene->ed)->seqbase.first; + + if (!self->iter) + { self->iter = iter; - return EXPP_incr_ret ( (PyObject *) self ); - } else { + return EXPP_incr_ret((PyObject *) self); + } + else + { return SceneSeq_CreatePyObject(self->scene, iter); } } +/* + * Return next Seq + */ +static PyObject *Sequence_nextIter(BPy_Sequence * self) +{ + PyObject *object; + if (!(self->iter)) + { + self->iter = NULL; /* so we can add objects again */ + return EXPP_ReturnPyObjError(PyExc_StopIteration, + "iterator at end"); + } + + object = Sequence_CreatePyObject(self->iter, NULL, self->scene); + self->iter = self->iter->next; + return object; +} /* * Return next Seq */ -static PyObject *Sequence_nextIter( BPy_Sequence * self ) +static PyObject *SceneSeq_nextIter(BPy_Sequence * self) { PyObject *object; - if( !(self->iter) ) { + if (!(self->iter)) + { self->iter = NULL; /* so we can add objects again */ - return EXPP_ReturnPyObjError( PyExc_StopIteration, - "iterator at end" ); + return EXPP_ReturnPyObjError(PyExc_StopIteration, + "iterator at end"); } - - object= Sequence_CreatePyObject( self->iter, NULL, self->scene ); - self->iter= self->iter->next; + + object = Sequence_CreatePyObject(self->iter, NULL, self->scene); + self->iter = self->iter->next; return object; } - -/* - * Return next Seq - */ -static PyObject *SceneSeq_nextIter( BPy_Sequence * self ) +static PyObject *Sequence_getName(BPy_Sequence * self) { - PyObject *object; - if( !(self->iter) ) { - self->iter = NULL; /* so we can add objects again */ - return EXPP_ReturnPyObjError( PyExc_StopIteration, - "iterator at end" ); - } - - object= Sequence_CreatePyObject( self->iter, NULL, self->scene ); - self->iter= self->iter->next; - return object; + return PyString_FromString(self->seq->name + 2); } - -static PyObject *Sequence_getName( BPy_Sequence * self ) -{ - return PyString_FromString( self->seq->name+2 ); -} - -static int Sequence_setName( BPy_Sequence * self, PyObject * value ) +static int Sequence_setName(BPy_Sequence * self, PyObject * value) { char *name = NULL; - - name = PyString_AsString ( value ); - if( !name ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected string argument" ); - strncpy(self->seq->name+2, name, 21); + name = PyString_AsString(value); + if (!name) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected string argument"); + + strncpy(self->seq->name + 2, name, 21); return 0; } - -static PyObject *Sequence_getProxyDir( BPy_Sequence * self ) +static PyObject *Sequence_getProxyDir(BPy_Sequence * self) { - return PyString_FromString( self->seq->strip->proxy ? self->seq->strip->proxy->dir : "" ); + return PyString_FromString(self->seq->strip->proxy ? self->seq->strip->proxy->dir : ""); } - -static int Sequence_setProxyDir( BPy_Sequence * self, PyObject * value ) +static int Sequence_setProxyDir(BPy_Sequence * self, PyObject * value) { char *name = NULL; - - name = PyString_AsString ( value ); - if( !name ) { - return EXPP_ReturnIntError( PyExc_TypeError, - "expected string argument" ); + + name = PyString_AsString(value); + if (!name) + { + return EXPP_ReturnIntError(PyExc_TypeError, + "expected string argument"); } - - if (strlen(name) == 0) { - if (self->seq->strip->proxy) { - MEM_freeN(self->seq->strip->proxy); + + if (strlen(name) == 0) + { + if (self->seq->strip->proxy) + { + MEM_freeN(self->seq->strip->proxy); } - } else { - self->seq->strip->proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy"); - strncpy(self->seq->strip->proxy->dir, name, sizeof(struct StripProxy)); + } + else + { + self->seq->strip->proxy = MEM_callocN(sizeof (struct StripProxy), "StripProxy"); + strncpy(self->seq->strip->proxy->dir, name, sizeof (struct StripProxy)); } return 0; } - -static PyObject *Sequence_rebuildProxy( BPy_Sequence * self ) +static PyObject *Sequence_rebuildProxy(BPy_Sequence * self) { if (self->seq->strip->proxy) seq_proxy_rebuild(self->seq); Py_RETURN_NONE; } - -static PyObject *Sequence_getSound( BPy_Sequence * self ) +static PyObject *Sequence_getSound(BPy_Sequence * self) { if (self->seq->type == SEQ_RAM_SOUND && self->seq->sound) return Sound_CreatePyObject(self->seq->sound); Py_RETURN_NONE; } -static PyObject *Sequence_getIpo( BPy_Sequence * self ) +static PyObject *Sequence_getIpo(BPy_Sequence * self) { struct Ipo *ipo; - + ipo = self->seq->ipo; - if( ipo ) - return Ipo_CreatePyObject( ipo ); + if (ipo) + return Ipo_CreatePyObject(ipo); Py_RETURN_NONE; } - -static PyObject *SceneSeq_getActive( BPy_SceneSeq * self ) +static PyObject *SceneSeq_getActive(BPy_SceneSeq * self) { Sequence *last_seq = NULL, *seq; Editing *ed = self->scene->ed; if (!ed) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "scene has no sequence data to edit" ); - + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "scene has no sequence data to edit"); + seq = ed->seqbasep->first; - - while (seq) { + + while (seq) + { if (seq->flag & SELECT) last_seq = seq; - + seq = seq->next; } if (last_seq) - return Sequence_CreatePyObject(last_seq, NULL, self->scene ); - + return Sequence_CreatePyObject(last_seq, NULL, self->scene); + Py_RETURN_NONE; } -static PyObject *SceneSeq_getMetaStrip( BPy_SceneSeq * self ) +static PyObject *SceneSeq_getMetaStrip(BPy_SceneSeq * self) { Sequence *seq = NULL; Editing *ed = self->scene->ed; MetaStack *ms; if (!ed) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "scene has no sequence data to edit" ); - + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "scene has no sequence data to edit"); + ms = ed->metastack.last; if (!ms) Py_RETURN_NONE; - + seq = ms->parseq; return Sequence_CreatePyObject(seq, NULL, self->scene); } - /* * this should accept a Py_None argument and just delete the Ipo link * (as Object_clearIpo() does) */ -static int Sequence_setIpo( BPy_Sequence * self, PyObject * value ) +static int Sequence_setIpo(BPy_Sequence * self, PyObject * value) { Ipo *ipo = NULL; Ipo *oldipo; ID *id; - + oldipo = self->seq->ipo; - + /* if parameter is not None, check for valid Ipo */ - if ( value != Py_None ) { - if ( !BPy_Ipo_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected an Ipo object" ); + if (value != Py_None) + { + if (!BPy_Ipo_Check(value)) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected an Ipo object"); - ipo = Ipo_FromPyObject( value ); + ipo = Ipo_FromPyObject(value); - if( !ipo ) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "null ipo!" ); + if (!ipo) + return EXPP_ReturnIntError(PyExc_RuntimeError, + "null ipo!"); - if( ipo->blocktype != ID_SEQ ) - return EXPP_ReturnIntError( PyExc_TypeError, - "Ipo is not a sequence data Ipo" ); + if (ipo->blocktype != ID_SEQ) + return EXPP_ReturnIntError(PyExc_TypeError, + "Ipo is not a sequence data Ipo"); } /* if already linked to Ipo, delete link */ - if ( oldipo ) { + if (oldipo) + { id = &oldipo->id; - if( id->us > 0 ) + if (id->us > 0) id->us--; } /* assign new Ipo and increment user count, or set to NULL if deleting */ self->seq->ipo = ipo; - if ( ipo ) + if (ipo) id_us_plus(&ipo->id); return 0; } -static PyObject *Sequence_getScene( BPy_Sequence * self ) +static PyObject *Sequence_getScene(BPy_Sequence * self) { struct Scene *scene; - + scene = self->seq->scene; - if( scene ) - return Scene_CreatePyObject( scene ); + if (scene) + return Scene_CreatePyObject(scene); Py_RETURN_NONE; } - -static PyObject *Sequence_getImages( BPy_Sequence * self ) +static PyObject *Sequence_getImages(BPy_Sequence * self) { Strip *strip; StripElem *se; int i; PyObject *list, *ret; - - if (self->seq->type != SEQ_IMAGE) { + + if (self->seq->type != SEQ_IMAGE) + { list = PyList_New(0); - ret= Py_BuildValue( "sO", "", list); + ret = Py_BuildValue("sO", "", list); Py_DECREF(list); return ret; } - - /*return EXPP_ReturnPyObjError( PyExc_TypeError, - "Sequence is not an image type" );*/ - - + + /*return EXPP_ReturnPyObjError( PyExc_TypeError, + "Sequence is not an image type" );*/ + + strip = self->seq->strip; se = strip->stripdata; list = PyList_New(strip->len); - - for (i=0; ilen; i++, se++) { - PyList_SetItem( list, i, PyString_FromString(se->name) ); + + for (i = 0; i < strip->len; i++, se++) + { + PyList_SetItem(list, i, PyString_FromString(se->name)); } - - ret= Py_BuildValue( "sO", strip->dir, list); + + ret = Py_BuildValue("sO", strip->dir, list); Py_DECREF(list); return ret; } -static int Sequence_setImages( BPy_Sequence * self, PyObject *value ) +static int Sequence_setImages(BPy_Sequence * self, PyObject *value) { Strip *strip; StripElem *se; int i; PyObject *list; char *basepath, *name; - - if (self->seq->type != SEQ_IMAGE) { - return EXPP_ReturnIntError( PyExc_TypeError, - "Sequence is not an image type" ); + + if (self->seq->type != SEQ_IMAGE) + { + return EXPP_ReturnIntError(PyExc_TypeError, + "Sequence is not an image type"); } - - if( !PyArg_ParseTuple - ( value, "sO!", &basepath, &PyList_Type, &list ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected string and optional list argument" ); - + + if (!PyArg_ParseTuple + (value, "sO!", &basepath, &PyList_Type, &list)) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected string and optional list argument"); + strip = self->seq->strip; se = strip->stripdata; - + /* for now dont support different image list sizes */ - if (PyList_Size(list) != strip->len) { - return EXPP_ReturnIntError( PyExc_TypeError, - "at the moment only image lista with the same number of images as the strip are supported" ); + if (PyList_Size(list) != strip->len) + { + return EXPP_ReturnIntError(PyExc_TypeError, + "at the moment only image lista with the same number of images as the strip are supported"); } - - strncpy(strip->dir, basepath, sizeof(strip->dir)); - - for (i=0; ilen; i++, se++) { + + strncpy(strip->dir, basepath, sizeof (strip->dir)); + + for (i = 0; i < strip->len; i++, se++) + { name = PyString_AsString(PyList_GetItem(list, i)); - if (name) { - strncpy(se->name, name, sizeof(se->name)); - } else { + if (name) + { + strncpy(se->name, name, sizeof (se->name)); + } + else + { PyErr_Clear(); } } - + return 0; } -static PyObject *M_Sequence_BlendModesDict( void ) +static PyObject *M_Sequence_BlendModesDict(void) { - PyObject *M = PyConstant_New( ); + PyObject *M = PyConstant_New(); - if( M ) { - BPy_constant *d = ( BPy_constant * ) M; - PyConstant_Insert( d, "CROSS", PyInt_FromLong( SEQ_CROSS ) ); - PyConstant_Insert( d, "ADD", PyInt_FromLong( SEQ_ADD ) ); - PyConstant_Insert( d, "SUBTRACT", PyInt_FromLong( SEQ_SUB ) ); - PyConstant_Insert( d, "ALPHAOVER", PyInt_FromLong( SEQ_ALPHAOVER ) ); - PyConstant_Insert( d, "ALPHAUNDER", PyInt_FromLong( SEQ_ALPHAUNDER ) ); - PyConstant_Insert( d, "GAMMACROSS", PyInt_FromLong( SEQ_GAMCROSS ) ); - PyConstant_Insert( d, "MULTIPLY", PyInt_FromLong( SEQ_MUL ) ); - PyConstant_Insert( d, "OVERDROP", PyInt_FromLong( SEQ_OVERDROP ) ); - PyConstant_Insert( d, "PLUGIN", PyInt_FromLong( SEQ_PLUGIN ) ); - PyConstant_Insert( d, "WIPE", PyInt_FromLong( SEQ_WIPE ) ); - PyConstant_Insert( d, "GLOW", PyInt_FromLong( SEQ_GLOW ) ); - PyConstant_Insert( d, "TRANSFORM", PyInt_FromLong( SEQ_TRANSFORM ) ); - PyConstant_Insert( d, "COLOR", PyInt_FromLong( SEQ_COLOR ) ); - PyConstant_Insert( d, "SPEED", PyInt_FromLong( SEQ_SPEED ) ); + if (M) + { + BPy_constant *d = (BPy_constant *) M; + PyConstant_Insert(d, "CROSS", PyInt_FromLong(SEQ_CROSS)); + PyConstant_Insert(d, "ADD", PyInt_FromLong(SEQ_ADD)); + PyConstant_Insert(d, "SUBTRACT", PyInt_FromLong(SEQ_SUB)); + PyConstant_Insert(d, "ALPHAOVER", PyInt_FromLong(SEQ_ALPHAOVER)); + PyConstant_Insert(d, "ALPHAUNDER", PyInt_FromLong(SEQ_ALPHAUNDER)); + PyConstant_Insert(d, "GAMMACROSS", PyInt_FromLong(SEQ_GAMCROSS)); + PyConstant_Insert(d, "MULTIPLY", PyInt_FromLong(SEQ_MUL)); + PyConstant_Insert(d, "OVERDROP", PyInt_FromLong(SEQ_OVERDROP)); + PyConstant_Insert(d, "PLUGIN", PyInt_FromLong(SEQ_PLUGIN)); + PyConstant_Insert(d, "WIPE", PyInt_FromLong(SEQ_WIPE)); + PyConstant_Insert(d, "GLOW", PyInt_FromLong(SEQ_GLOW)); + PyConstant_Insert(d, "TRANSFORM", PyInt_FromLong(SEQ_TRANSFORM)); + PyConstant_Insert(d, "COLOR", PyInt_FromLong(SEQ_COLOR)); + PyConstant_Insert(d, "SPEED", PyInt_FromLong(SEQ_SPEED)); } return M; } -static PyObject *Sequence_getBlendMode( BPy_Sequence * self ) +static PyObject *Sequence_getBlendMode(BPy_Sequence * self) { - return PyInt_FromLong( self->seq->blend_mode ); + return PyInt_FromLong(self->seq->blend_mode); } -static int Sequence_setBlendMode( BPy_Sequence * self, PyObject * value ) +static int Sequence_setBlendMode(BPy_Sequence * self, PyObject * value) { - struct Sequence *seq= self->seq; - int number = PyInt_AsLong( value ); - - if( number==-1 && PyErr_Occurred() ) - return EXPP_ReturnIntError( PyExc_TypeError, "expected an int value" ); - - if ( !seq_can_blend(seq) ) - return EXPP_ReturnIntError( PyExc_AttributeError, "this sequence type dosnt support blending" ); - - if (numberSEQ_EFFECT_MAX) - return EXPP_ReturnIntError( PyExc_TypeError, "expected an int value" ); - - seq->blend_mode=number; - + struct Sequence *seq = self->seq; + int number = PyInt_AsLong(value); + + if (number == -1 && PyErr_Occurred()) + return EXPP_ReturnIntError(PyExc_TypeError, "expected an int value"); + + if (!seq_can_blend(seq)) + return EXPP_ReturnIntError(PyExc_AttributeError, "this sequence type dosnt support blending"); + + if (number < SEQ_EFFECT || number > SEQ_EFFECT_MAX) + return EXPP_ReturnIntError(PyExc_TypeError, "expected an int value"); + + seq->blend_mode = number; + return 0; } /* * get floating point attributes */ -static PyObject *getIntAttr( BPy_Sequence *self, void *type ) +static PyObject *getIntAttr(BPy_Sequence *self, void *type) { int param; - struct Sequence *seq= self->seq; - + struct Sequence *seq = self->seq; + /*printf("%i %i %i %i %i %i %i %i %i\n", seq->len, seq->start, seq->startofs, seq->endofs, seq->startstill, seq->endstill, seq->startdisp, seq->enddisp, seq->depth );*/ - switch( GET_INT_FROM_POINTER(type) ) { - case EXPP_SEQ_ATTR_TYPE: + switch (GET_INT_FROM_POINTER(type)) + { + case EXPP_SEQ_ATTR_TYPE: param = seq->type; break; case EXPP_SEQ_ATTR_CHAN: @@ -897,43 +1015,52 @@ static PyObject *getIntAttr( BPy_Sequence *self, void *type ) case EXPP_SEQ_ATTR_ENDSTILL: param = seq->endstill; break; + case EXPP_SEQ_ATTR_STARTDISP: + param = seq->startdisp; + break; + case EXPP_SEQ_ATTR_ENDDISP: + param = seq->enddisp; + break; default: - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "undefined type in getIntAttr" ); + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "undefined type in getIntAttr"); } - return PyInt_FromLong( param ); + return PyInt_FromLong(param); } /* internal functions for recursivly updating metastrip locatons */ -static void intern_pos_update(Sequence * seq) { +static void intern_pos_update(Sequence * seq) +{ /* update startdisp and enddisp */ calc_sequence_disp(seq); } -void intern_recursive_pos_update(Sequence * seq, int offset) { +void intern_recursive_pos_update(Sequence * seq, int offset) +{ Sequence *iterseq; intern_pos_update(seq); if (seq->type != SEQ_META) return; - - for (iterseq = seq->seqbase.first; iterseq; iterseq= iterseq->next) { + + for (iterseq = seq->seqbase.first; iterseq; iterseq = iterseq->next) + { iterseq->start -= offset; intern_recursive_pos_update(iterseq, offset); } } - -static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) +static int setIntAttrClamp(BPy_Sequence *self, PyObject *value, void *type) { - struct Sequence *seq= self->seq; - int number, origval=0, regen_data; + struct Sequence *seq = self->seq; + int number, origval = 0, regen_data; - if( !PyInt_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, "expected an int value" ); - - number = PyInt_AS_LONG( value ); - - switch( GET_INT_FROM_POINTER(type) ) { + if (!PyInt_Check(value)) + return EXPP_ReturnIntError(PyExc_TypeError, "expected an int value"); + + number = PyInt_AS_LONG(value); + + switch (GET_INT_FROM_POINTER(type)) + { case EXPP_SEQ_ATTR_CHAN: CLAMP(number, 1, 1024); seq->machine = number; @@ -941,18 +1068,18 @@ static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) break; case EXPP_SEQ_ATTR_START: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "cannot set the location of an effect directly" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "cannot set the location of an effect directly"); CLAMP(number, -MAXFRAME, MAXFRAME); origval = seq->start; seq->start = number; regen_data = 0; break; - + case EXPP_SEQ_ATTR_STARTOFS: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "This property dosnt apply to an effect" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "This property dosnt apply to an effect"); CLAMP(number, 0, seq->len - seq->endofs); origval = seq->startofs; seq->startofs = number; @@ -960,8 +1087,8 @@ static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) break; case EXPP_SEQ_ATTR_ENDOFS: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "This property dosnt apply to an effect" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "This property dosnt apply to an effect"); CLAMP(number, 0, seq->len - seq->startofs); origval = seq->endofs; seq->endofs = number; @@ -969,8 +1096,8 @@ static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) break; case EXPP_SEQ_ATTR_STARTSTILL: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "This property dosnt apply to an effect" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "This property dosnt apply to an effect"); CLAMP(number, 1, MAXFRAME); origval = seq->startstill; seq->startstill = number; @@ -978,42 +1105,46 @@ static int setIntAttrClamp( BPy_Sequence *self, PyObject *value, void *type ) break; case EXPP_SEQ_ATTR_ENDSTILL: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "This property dosnt apply to an effect" ); - CLAMP(number, seq->startstill+1, MAXFRAME); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "This property dosnt apply to an effect"); + CLAMP(number, seq->startstill + 1, MAXFRAME); origval = seq->endstill; seq->endstill = number; regen_data = 1; break; case EXPP_SEQ_ATTR_LENGTH: if (self->seq->type == SEQ_EFFECT) - return EXPP_ReturnIntError( PyExc_RuntimeError, - "cannot set the length of an effect directly" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "cannot set the length of an effect directly"); CLAMP(number, 1, MAXFRAME); origval = seq->len; seq->len = number; regen_data = 1; break; default: - return EXPP_ReturnIntError( PyExc_RuntimeError, - "undefined type in setFloatAttrClamp" ); + return EXPP_ReturnIntError(PyExc_RuntimeError, + "undefined type in setFloatAttrClamp"); } - if (number != origval) { + if (number != origval) + { intern_pos_update(seq); - + if (GET_INT_FROM_POINTER(type) == EXPP_SEQ_ATTR_START) intern_recursive_pos_update(seq, origval - seq->start); - - if (regen_data) { + + if (regen_data) + { new_tstripdata(seq); } + + calc_sequence(seq); + calc_sequence_disp(seq); } return 0; } - -static PyObject *getFlagAttr( BPy_Sequence *self, void *type ) +static PyObject *getFlagAttr(BPy_Sequence *self, void *type) { if (self->seq->flag & GET_INT_FROM_POINTER(type)) Py_RETURN_TRUE; @@ -1021,89 +1152,95 @@ static PyObject *getFlagAttr( BPy_Sequence *self, void *type ) Py_RETURN_FALSE; } - /* * set floating point attributes which require clamping */ -static int setFlagAttr( BPy_Sequence *self, PyObject *value, void *type ) +static int setFlagAttr(BPy_Sequence *self, PyObject *value, void *type) { int t = GET_INT_FROM_POINTER(type); - int param = PyObject_IsTrue( value ); - - if( param == -1 ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected True/False or 0/1" ); - + int param = PyObject_IsTrue(value); + + if (param == -1) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected True/False or 0/1"); + if (param) self->seq->flag |= t; - else { + else + { /* dont allow leftsel and rightsel when its not selected */ if (t == SELECT) t = t + SEQ_LEFTSEL + SEQ_RIGHTSEL; - + self->seq->flag &= ~t; } return 0; } -static PyObject *getEffectSeq( BPy_Sequence *self, void *type ) +static PyObject *getEffectSeq(BPy_Sequence *self, void *type) { int t = GET_INT_FROM_POINTER(type); - Sequence *seq= NULL; - switch(t) { + Sequence *seq = NULL; + switch (t) + { case 1: - seq= self->seq->seq1; + seq = self->seq->seq1; break; case 2: - seq= self->seq->seq2; + seq = self->seq->seq2; break; case 3: - seq= self->seq->seq3; + seq = self->seq->seq3; break; } - if (seq) { - return Sequence_CreatePyObject(seq, NULL, self->scene); - } else { + if (seq) + { + return Sequence_CreatePyObject(seq, NULL, self->scene); + } + else + { Py_RETURN_NONE; } } - /* * set one of the effect sequences */ -static int setEffectSeq( BPy_Sequence *self, PyObject *value, void *type ) +static int setEffectSeq(BPy_Sequence *self, PyObject *value, void *type) { int t = GET_INT_FROM_POINTER(type); Sequence **seq; - if ((value==Py_None || BPy_Sequence_Check(value))==0) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected Sequence or None" ); - - switch(t) { + if ((value == Py_None || BPy_Sequence_Check(value)) == 0) + return EXPP_ReturnIntError(PyExc_TypeError, + "expected Sequence or None"); + + switch (t) + { case 1: - seq= &self->seq->seq1; + seq = &self->seq->seq1; break; case 2: - seq= &self->seq->seq2; + seq = &self->seq->seq2; break; case 3: - seq= &self->seq->seq3; + seq = &self->seq->seq3; break; } - if (value==Py_None) - *seq= NULL; - else { - Sequence *newseq= ((BPy_Sequence *)value)->seq; - if (newseq==self->seq) { - return EXPP_ReturnIntError( PyExc_TypeError, "cannot set a sequence as its own effect" ); + if (value == Py_None) + *seq = NULL; + else + { + Sequence *newseq = ((BPy_Sequence *) value)->seq; + if (newseq == self->seq) + { + return EXPP_ReturnIntError(PyExc_TypeError, "cannot set a sequence as its own effect"); } - *seq= ((BPy_Sequence *)value)->seq; + *seq = ((BPy_Sequence *) value)->seq; } @@ -1114,139 +1251,325 @@ static int setEffectSeq( BPy_Sequence *self, PyObject *value, void *type ) } + +static PyObject *getSpeedEffect(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= self->seq; + SpeedControlVars * v; + + if (seq->type != SEQ_SPEED) + return EXPP_ReturnPyObjError(PyExc_TypeError, "Not a speed effect strip" ); + + v = (SpeedControlVars *)seq->effectdata; + + switch (t) { + case EXPP_SEQ_ATTR_EFFECT_GLOBAL_SPEED: + return PyFloat_FromDouble(v->globalSpeed); + break; + case EXPP_SEQ_ATTR_EFFECT_IPO_IS_VELOCITY: + return PyBool_FromLong(v->flags & SEQ_SPEED_INTEGRATE); + break; + case EXPP_SEQ_ATTR_EFFECT_FRAME_BLENDING: + return PyBool_FromLong(v->flags & SEQ_SPEED_BLEND); + break; + case EXPP_SEQ_ATTR_EFFECT_NORMALIZE_IPO_0_1: + return PyBool_FromLong(v->flags & SEQ_SPEED_COMPRESS_IPO_Y); + break; + } + + if (PyErr_Occurred()) { + return NULL; + } + + Py_RETURN_NONE; +} + +/* + * set one of the effect sequences + */ + +static int setSpeedEffect(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= self->seq; + SpeedControlVars * v; + + if (seq->type != SEQ_SPEED) + return EXPP_ReturnIntError(PyExc_TypeError, "Not a speed effect strip" ); + + v = (SpeedControlVars *)seq->effectdata; + + switch (t) { + case EXPP_SEQ_ATTR_EFFECT_GLOBAL_SPEED: + v->globalSpeed= PyFloat_AsDouble(value); + CLAMP(v->globalSpeed, 0.0f, 100.0f); + break; + case EXPP_SEQ_ATTR_EFFECT_IPO_IS_VELOCITY: + if (PyObject_IsTrue( value )) v->flags |= SEQ_SPEED_INTEGRATE; + else v->flags &= ~SEQ_SPEED_INTEGRATE; + break; + case EXPP_SEQ_ATTR_EFFECT_FRAME_BLENDING: + if (PyObject_IsTrue( value )) v->flags |= SEQ_SPEED_BLEND; + else v->flags &= ~SEQ_SPEED_BLEND; + break; + case EXPP_SEQ_ATTR_EFFECT_NORMALIZE_IPO_0_1: + if (PyObject_IsTrue( value )) v->flags |= SEQ_SPEED_COMPRESS_IPO_Y; + else v->flags &= ~SEQ_SPEED_COMPRESS_IPO_Y; + break; + } + + if (PyErr_Occurred()) { + return -1; + } + + return 0; +} + + + +static PyObject *getWipeEffect(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= self->seq; + WipeVars * v; + + if (seq->type != SEQ_WIPE) + return EXPP_ReturnPyObjError(PyExc_TypeError, "Not a wipe effect strip" ); + + v = (WipeVars *)seq->effectdata; + + switch (t) { + case EXPP_SEQ_ATTR_EFFECT_ANGLE: + return PyFloat_FromDouble(v->angle); + break; + case EXPP_SEQ_ATTR_EFFECT_BLUR: + return PyFloat_FromDouble(v->edgeWidth); + break; + case EXPP_SEQ_ATTR_EFFECT_WIPE_IN: + return PyBool_FromLong(v->forward); + break; + } + + if (PyErr_Occurred()) { + return NULL; + } + + Py_RETURN_NONE; +} + +/* + * set one of the effect sequences + */ + +static int setWipeEffect(BPy_Sequence *self, PyObject *value, void *type) +{ + int t = GET_INT_FROM_POINTER(type); + Sequence *seq= self->seq; + WipeVars * v; + + if (seq->type != SEQ_WIPE) + return EXPP_ReturnIntError(PyExc_TypeError, "Not a wipe effect strip" ); + + v = (WipeVars *)seq->effectdata; + + switch (t) { + case EXPP_SEQ_ATTR_EFFECT_ANGLE: + v->angle= PyFloat_AsDouble(value); + CLAMP(v->angle, -90.0f, 90.0f); + break; + case EXPP_SEQ_ATTR_EFFECT_BLUR: + v->edgeWidth= PyFloat_AsDouble(value); + CLAMP(v->edgeWidth, -90.0f, 90.0f); + break; + case EXPP_SEQ_ATTR_EFFECT_WIPE_IN: + if (PyObject_IsTrue( value )) v->forward= 1; + else v->forward= 0; + break; + } + + if (PyErr_Occurred()) { + return -1; + } + + return 0; +} + + + /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef BPy_Sequence_getseters[] = { {"name", - (getter)Sequence_getName, (setter)Sequence_setName, - "Sequence name", - NULL}, + (getter) Sequence_getName, (setter) Sequence_setName, + "Sequence name", + NULL}, {"proxyDir", - (getter)Sequence_getProxyDir, (setter)Sequence_setProxyDir, - "Sequence proxy directory", - NULL}, + (getter) Sequence_getProxyDir, (setter) Sequence_setProxyDir, + "Sequence proxy directory", + NULL}, {"ipo", - (getter)Sequence_getIpo, (setter)Sequence_setIpo, - "Sequence ipo", - NULL}, + (getter) Sequence_getIpo, (setter) Sequence_setIpo, + "Sequence ipo", + NULL}, {"scene", - (getter)Sequence_getScene, (setter)NULL, - "Sequence scene", - NULL}, + (getter) Sequence_getScene, (setter) NULL, + "Sequence scene", + NULL}, {"sound", - (getter)Sequence_getSound, (setter)NULL, - "Sequence name", - NULL}, + (getter) Sequence_getSound, (setter) NULL, + "Sequence name", + NULL}, {"images", - (getter)Sequence_getImages, (setter)Sequence_setImages, - "Sequence scene", - NULL}, + (getter) Sequence_getImages, (setter) Sequence_setImages, + "Sequence scene", + NULL}, {"blendMode", - (getter)Sequence_getBlendMode, (setter)Sequence_setBlendMode, - "Sequence Blend Mode", - NULL}, + (getter) Sequence_getBlendMode, (setter) Sequence_setBlendMode, + "Sequence Blend Mode", + NULL}, {"type", - (getter)getIntAttr, (setter)NULL, - "", - (void *) EXPP_SEQ_ATTR_TYPE}, + (getter) getIntAttr, (setter) NULL, + "", + (void *) EXPP_SEQ_ATTR_TYPE}, {"channel", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_CHAN}, - + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_CHAN}, + {"length", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_LENGTH}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_LENGTH}, {"start", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_START}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_START}, {"startOffset", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_STARTOFS}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_STARTOFS}, {"endOffset", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_ENDOFS}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_ENDOFS}, {"startStill", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_STARTSTILL}, + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_STARTSTILL}, {"endStill", - (getter)getIntAttr, (setter)setIntAttrClamp, - "", - (void *) EXPP_SEQ_ATTR_ENDSTILL}, - + (getter) getIntAttr, (setter) setIntAttrClamp, + "", + (void *) EXPP_SEQ_ATTR_ENDSTILL}, + {"startDisp", + (getter) getIntAttr, (setter) NULL, + "", + (void *) EXPP_SEQ_ATTR_STARTDISP}, + {"endDisp", + (getter) getIntAttr, (setter) NULL, + "", + (void *) EXPP_SEQ_ATTR_ENDDISP}, + {"sel", - (getter)getFlagAttr, (setter)setFlagAttr, - "Sequence audio mute option", - (void *)SELECT}, + (getter) getFlagAttr, (setter) setFlagAttr, + "Sequence audio mute option", + (void *) SELECT}, {"selLeft", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_LEFTSEL}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_LEFTSEL}, {"selRight", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_RIGHTSEL}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_RIGHTSEL}, {"filtery", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_FILTERY}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_FILTERY}, {"flipX", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_FLIPX}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_FLIPX}, {"flipY", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_FLIPY}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_FLIPY}, {"mute", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_MUTE}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_MUTE}, {"floatBuffer", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_MAKE_FLOAT}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_MAKE_FLOAT}, {"lock", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_LOCK}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_LOCK}, {"useProxy", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_USE_PROXY}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_USE_PROXY}, {"premul", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_MAKE_PREMUL}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_MAKE_PREMUL}, {"reversed", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_REVERSE_FRAMES}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_REVERSE_FRAMES}, {"ipoLocked", - (getter)getFlagAttr, (setter)setFlagAttr, - "", - (void *)SEQ_IPO_FRAME_LOCKED}, + (getter) getFlagAttr, (setter) setFlagAttr, + "", + (void *) SEQ_IPO_FRAME_LOCKED}, {"seq1", - (getter)getEffectSeq, (setter)setEffectSeq, - "", - (void *)1}, + (getter) getEffectSeq, (setter) setEffectSeq, + "", + (void *) 1}, {"seq2", - (getter)getEffectSeq, (setter)setEffectSeq, - "", - (void *)2}, + (getter) getEffectSeq, (setter) setEffectSeq, + "", + (void *) 2}, {"seq3", - (getter)getEffectSeq, (setter)setEffectSeq, - "", - (void *)3}, - {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ + (getter) getEffectSeq, (setter) setEffectSeq, + "", + (void *) 3}, + + /* effects */ + {"speedEffectGlobalSpeed", + (getter) getSpeedEffect, (setter) setSpeedEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_GLOBAL_SPEED}, + {"speedEffectIpoVelocity", + (getter) getSpeedEffect, (setter) setSpeedEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_IPO_IS_VELOCITY}, + {"speedEffectFrameBlending", + (getter) getSpeedEffect, (setter) setSpeedEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_FRAME_BLENDING}, + {"speedEffectIpoNormalize", + (getter) getSpeedEffect, (setter) setSpeedEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_NORMALIZE_IPO_0_1}, + + {"wipeEffectAngle", + (getter) getWipeEffect, (setter) setWipeEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_ANGLE}, + {"wipeEffectBlur", + (getter) getWipeEffect, (setter) setWipeEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_BLUR}, + {"wipeEffectWipeIn", + (getter) getWipeEffect, (setter) setWipeEffect, + "", + (void *) EXPP_SEQ_ATTR_EFFECT_WIPE_IN}, + + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; /*****************************************************************************/ @@ -1254,98 +1577,98 @@ static PyGetSetDef BPy_Sequence_getseters[] = { /*****************************************************************************/ static PyGetSetDef BPy_SceneSeq_getseters[] = { {"active", - (getter)SceneSeq_getActive, (setter)NULL, - "the active strip", - NULL}, + (getter) SceneSeq_getActive, (setter) NULL, + "the active strip", + NULL}, {"metastrip", - (getter)SceneSeq_getMetaStrip, (setter)NULL, - "The currently active metastrip the user is editing", - NULL}, - {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ + (getter) SceneSeq_getMetaStrip, (setter) NULL, + "The currently active metastrip the user is editing", + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; /*****************************************************************************/ /* Python TypeSequence structure definition: */ /*****************************************************************************/ PyTypeObject Sequence_Type = { - PyObject_HEAD_INIT( NULL ) /* required py macro */ - 0, /* ob_size */ + PyObject_HEAD_INIT(NULL) /* required py macro */ + 0, /* ob_size */ /* For printing, in format "." */ - "Blender Sequence", /* char *tp_name; */ - sizeof( BPy_Sequence ), /* int tp_basicsize; */ - 0, /* tp_itemsize; For allocation */ + "Blender Sequence", /* char *tp_name; */ + sizeof ( BPy_Sequence), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ /* Methods to implement standard operations */ - NULL,/* destructor tp_dealloc; */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - ( cmpfunc ) Sequence_compare, /* cmpfunc tp_compare; */ - ( reprfunc ) Sequence_repr, /* reprfunc tp_repr; */ + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + (cmpfunc) Sequence_compare, /* cmpfunc tp_compare; */ + (reprfunc) Sequence_repr, /* reprfunc tp_repr; */ /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* traverseproc tp_traverse; */ /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset; */ + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ - /*** Added in release 2.2 ***/ + /*** Added in release 2.2 ***/ /* Iterators */ - ( getiterfunc ) Sequence_getIter, /* getiterfunc tp_iter; */ - ( iternextfunc ) Sequence_nextIter, /* iternextfunc tp_iternext; */ + (getiterfunc) Sequence_getIter, /* getiterfunc tp_iter; */ + (iternextfunc) Sequence_nextIter, /* iternextfunc tp_iternext; */ - /*** Attribute descriptor and subclassing stuff ***/ - BPy_Sequence_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - BPy_Sequence_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ + /*** Attribute descriptor and subclassing stuff ***/ + BPy_Sequence_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_Sequence_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ + NULL, /* freefunc tp_free; */ /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ NULL }; @@ -1355,84 +1678,84 @@ PyTypeObject Sequence_Type = { /* Python TypeSequence structure definition: */ /*****************************************************************************/ PyTypeObject SceneSeq_Type = { - PyObject_HEAD_INIT( NULL ) /* required py macro */ - 0, /* ob_size */ + PyObject_HEAD_INIT(NULL) /* required py macro */ + 0, /* ob_size */ /* For printing, in format "." */ - "Blender SceneSeq", /* char *tp_name; */ - sizeof( BPy_Sequence ), /* int tp_basicsize; */ - 0, /* tp_itemsize; For allocation */ + "Blender SceneSeq", /* char *tp_name; */ + sizeof ( BPy_Sequence), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ /* Methods to implement standard operations */ - NULL,/* destructor tp_dealloc; */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - ( cmpfunc ) SceneSeq_compare, /* cmpfunc tp_compare; */ - ( reprfunc ) SceneSeq_repr, /* reprfunc tp_repr; */ + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + (cmpfunc) SceneSeq_compare, /* cmpfunc tp_compare; */ + (reprfunc) SceneSeq_repr, /* reprfunc tp_repr; */ /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* traverseproc tp_traverse; */ /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset; */ + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ - /*** Added in release 2.2 ***/ + /*** Added in release 2.2 ***/ /* Iterators */ - ( getiterfunc ) SceneSeq_getIter, /* getiterfunc tp_iter; */ - ( iternextfunc ) SceneSeq_nextIter, /* iternextfunc tp_iternext; */ + (getiterfunc) SceneSeq_getIter, /* getiterfunc tp_iter; */ + (iternextfunc) SceneSeq_nextIter, /* iternextfunc tp_iternext; */ - /*** Attribute descriptor and subclassing stuff ***/ - BPy_SceneSeq_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - BPy_SceneSeq_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ + /*** Attribute descriptor and subclassing stuff ***/ + BPy_SceneSeq_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_SceneSeq_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ + NULL, /* freefunc tp_free; */ /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ NULL }; @@ -1446,27 +1769,28 @@ PyObject *M_Sequence_Get( PyObject * self, PyObject * args ) { return SceneSeq_CreatePyObject( G.scene, NULL ); } -*/ + */ /*****************************************************************************/ /* Function: initObject */ -/*****************************************************************************/ -PyObject *Sequence_Init( void ) -{ - PyObject *BlendModesDict = M_Sequence_BlendModesDict( ); - PyObject *submodule; - if( PyType_Ready( &Sequence_Type ) < 0 ) - return NULL; - if( PyType_Ready( &SceneSeq_Type ) < 0 ) - return NULL; - - /* NULL was M_Sequence_methods*/ - submodule = Py_InitModule3( "Blender.Scene.Sequence", NULL, -"The Blender Sequence module\n\n\ -This module provides access to **Sequence Data** in Blender.\n" ); - if( BlendModesDict ) - PyModule_AddObject( submodule, "BlendModes", BlendModesDict ); +/*****************************************************************************/ +PyObject *Sequence_Init(void) +{ + PyObject *BlendModesDict = M_Sequence_BlendModesDict(); + PyObject *submodule; + if (PyType_Ready(&Sequence_Type) < 0) + return NULL; + if (PyType_Ready(&SceneSeq_Type) < 0) + return NULL; + + /* NULL was M_Sequence_methods*/ + submodule = Py_InitModule3("Blender.Scene.Sequence", NULL, + "The Blender Sequence module\n\n\ +This module provides access to **Sequence Data** in Blender.\n"); + + if (BlendModesDict) + PyModule_AddObject(submodule, "BlendModes", BlendModesDict); /*Add SUBMODULES to the module*/ /*PyDict_SetItemString(dict, "Constraint", Constraint_Init()); //creates a *new* module*/ @@ -1478,68 +1802,74 @@ This module provides access to **Sequence Data** in Blender.\n" ); /* Function: Sequence_CreatePyObject */ /* Description: This function will create a new BlenObject from an existing */ /* Object structure. */ + /*****************************************************************************/ -PyObject *Sequence_CreatePyObject( struct Sequence * seq, struct Sequence * iter, struct Scene *sce) +PyObject *Sequence_CreatePyObject(struct Sequence * seq, struct Sequence * iter, struct Scene *sce) { BPy_Sequence *pyseq; - if( !seq ) + if (!seq) Py_RETURN_NONE; pyseq = - ( BPy_Sequence * ) PyObject_NEW( BPy_Sequence, &Sequence_Type ); + (BPy_Sequence *) PyObject_NEW(BPy_Sequence, &Sequence_Type); - if( pyseq == NULL ) { - return ( NULL ); + if (pyseq == NULL) + { + return ( NULL); } pyseq->seq = seq; pyseq->iter = iter; pyseq->scene = sce; - - return ( ( PyObject * ) pyseq ); + + return ( (PyObject *) pyseq); } /*****************************************************************************/ /* Function: SceneSeq_CreatePyObject */ /* Description: This function will create a new BlenObject from an existing */ /* Object structure. */ + /*****************************************************************************/ -PyObject *SceneSeq_CreatePyObject( struct Scene * scn, struct Sequence * iter) +PyObject *SceneSeq_CreatePyObject(struct Scene * scn, struct Sequence * iter) { BPy_SceneSeq *pysceseq; - if( !scn ) + if (!scn) Py_RETURN_NONE; - if ( !scn->ed ) { + if (!scn->ed) + { Editing *ed; - ed= scn->ed= MEM_callocN( sizeof(Editing), "addseq"); - ed->seqbasep= &ed->seqbase; + ed = scn->ed = MEM_callocN(sizeof (Editing), "addseq"); + ed->seqbasep = &ed->seqbase; } - - pysceseq = - ( BPy_SceneSeq * ) PyObject_NEW( BPy_SceneSeq, &SceneSeq_Type ); - if( pysceseq == NULL ) { - return ( NULL ); + pysceseq = + (BPy_SceneSeq *) PyObject_NEW(BPy_SceneSeq, &SceneSeq_Type); + + if (pysceseq == NULL) + { + return ( NULL); } pysceseq->scene = scn; pysceseq->iter = iter; - - return ( ( PyObject * ) pysceseq ); + + return ( (PyObject *) pysceseq); } /*****************************************************************************/ /* Function: Sequence_FromPyObject */ /* Description: This function returns the Blender sequence from the given */ /* PyObject. */ + /*****************************************************************************/ -struct Sequence *Sequence_FromPyObject( PyObject * py_seq ) +struct Sequence *Sequence_FromPyObject(PyObject * py_seq) { BPy_Sequence *blen_seq; - blen_seq = ( BPy_Sequence * ) py_seq; - return ( blen_seq->seq ); + blen_seq = (BPy_Sequence *) py_seq; + return ( blen_seq->seq); } /*****************************************************************************/ @@ -1549,33 +1879,36 @@ struct Sequence *Sequence_FromPyObject( PyObject * py_seq ) /* comparisons are meaninful. Returns 0 for equality and -1 if */ /* they don't point to the same Blender Object struct. */ /* In Python it becomes 1 if they are equal, 0 otherwise. */ + /*****************************************************************************/ -static int Sequence_compare( BPy_Sequence * a, BPy_Sequence * b ) +static int Sequence_compare(BPy_Sequence * a, BPy_Sequence * b) { Sequence *pa = a->seq, *pb = b->seq; - return ( pa == pb ) ? 0 : -1; + return ( pa == pb) ? 0 : -1; } -static int SceneSeq_compare( BPy_SceneSeq * a, BPy_SceneSeq * b ) +static int SceneSeq_compare(BPy_SceneSeq * a, BPy_SceneSeq * b) { - + Scene *pa = a->scene, *pb = b->scene; - return ( pa == pb ) ? 0 : -1; + return ( pa == pb) ? 0 : -1; } /*****************************************************************************/ /* Function: Sequence_repr / SceneSeq_repr */ /* Description: This is a callback function for the BPy_Sequence type. It */ /* builds a meaninful string to represent object objects. */ + /*****************************************************************************/ -static PyObject *Sequence_repr( BPy_Sequence * self ) +static PyObject *Sequence_repr(BPy_Sequence * self) { - return PyString_FromFormat( "[Sequence Strip \"%s\"]", - self->seq->name + 2 ); -} -static PyObject *SceneSeq_repr( BPy_SceneSeq * self ) -{ - return PyString_FromFormat( "[Scene Sequence \"%s\"]", - self->scene->id.name + 2 ); + return PyString_FromFormat("[Sequence Strip \"%s\"]", + self->seq->name + 2); +} + +static PyObject *SceneSeq_repr(BPy_SceneSeq * self) +{ + return PyString_FromFormat("[Scene Sequence \"%s\"]", + self->scene->id.name + 2); } From 86c25491e14d11174324ec14056d7cc94891d359 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 6 Feb 2009 16:38:53 +0000 Subject: [PATCH 164/252] =?UTF-8?q?[#18257]=20Workaround=20for=20bug=20in?= =?UTF-8?q?=20freealut=201.1.0=20by=20J=C3=B6rg=20M=C3=BCller=20(nexyon)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this area is not maintained, I can only say it works on my system (linux/32bit) And nexyon assured me he checked over this patch well. Blender using the deprecated function is not great, but nexyon's bugfix would not be available until the next version of freealut so better to work around it by using the new function. Please test game sounds play back on win32 and Mac, in cases that it worked in the first place. --- intern/SoundSystem/openal/SND_OpenALDevice.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp index c660e9aecba..9ce30f985ac 100644 --- a/intern/SoundSystem/openal/SND_OpenALDevice.cpp +++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp @@ -235,7 +235,8 @@ SND_OpenALDevice::SND_OpenALDevice() if (m_context) { #ifdef AL_VERSION_1_1 - alcMakeContextCurrent((ALCcontext*)m_context); + alcMakeContextCurrent((ALCcontext*)m_context); + alutInitWithoutContext(NULL, NULL); /* in this case we dont want alut to initialize the context, see above */ #else alcMakeContextCurrent(m_context); #endif @@ -380,6 +381,9 @@ SND_OpenALDevice::~SND_OpenALDevice() #else if (m_device) alcCloseDevice((ALCdevice*) m_device); +#ifdef AL_VERSION_1_1 + alutExit(); +#endif #endif } @@ -437,7 +441,9 @@ SND_WaveSlot* SND_OpenALDevice::LoadSample(const STR_String& name, alutLoadWAVMemory((char*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate); // openal_2.12 #else #ifdef AL_VERSION_1_1 - alutLoadWAVMemory((ALbyte*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate, &loop);// openal_2.14+ + float frequency = 0.0f; + data = alutLoadMemoryFromFileImage(memlocation, size, &sampleformat, &numberofsamples, &frequency); + samplerate = (int)frequency; #else alutLoadWAVMemory((signed char*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate, &loop);// openal_2.14+ @@ -480,7 +486,11 @@ SND_WaveSlot* SND_OpenALDevice::LoadSample(const STR_String& name, } /* and free the original stuff (copy was made in openal) */ +#if defined(OUDE_OPENAL) || defined (__APPLE__) || !defined(AL_VERSION_1_1) alutUnloadWAV(sampleformat, data, numberofsamples, samplerate); +#else + free(data); +#endif } } else From 09099111e39a7363fa186c4200b60b3b2bd93f9e Mon Sep 17 00:00:00 2001 From: Robin Allen Date: Fri, 6 Feb 2009 18:09:35 +0000 Subject: [PATCH 165/252] Added Scale, fixed bugs incl. patch #18037 --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/nodes/TEX_node.h | 1 + .../nodes/intern/TEX_nodes/TEX_compose.c | 28 +++---- .../nodes/intern/TEX_nodes/TEX_decompose.c | 10 +-- .../blender/nodes/intern/TEX_nodes/TEX_math.c | 23 ++++++ .../nodes/intern/TEX_nodes/TEX_rotate.c | 2 - .../nodes/intern/TEX_nodes/TEX_scale.c | 76 +++++++++++++++++++ .../nodes/intern/TEX_nodes/TEX_translate.c | 2 - 9 files changed, 121 insertions(+), 23 deletions(-) create mode 100644 source/blender/nodes/intern/TEX_nodes/TEX_scale.c diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 20a9fae33bb..3f04330f2a3 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -406,6 +406,7 @@ struct TexResult; #define TEX_NODE_COMPOSE 119 #define TEX_NODE_DECOMPOSE 120 #define TEX_NODE_VALTONOR 121 +#define TEX_NODE_SCALE 122 /* 201-299 reserved. Use like this: TEX_NODE_PROC + TEX_CLOUDS, etc */ #define TEX_NODE_PROC 200 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 14111f2c175..978b47b651f 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2902,6 +2902,7 @@ static void registerTextureNodes(ListBase *ntypelist) nodeRegisterType(ntypelist, &tex_node_rotate); nodeRegisterType(ntypelist, &tex_node_translate); + nodeRegisterType(ntypelist, &tex_node_scale); nodeRegisterType(ntypelist, &tex_node_proc_voronoi); nodeRegisterType(ntypelist, &tex_node_proc_blend); diff --git a/source/blender/nodes/TEX_node.h b/source/blender/nodes/TEX_node.h index 3fae2703f0d..c52fc757507 100644 --- a/source/blender/nodes/TEX_node.h +++ b/source/blender/nodes/TEX_node.h @@ -58,6 +58,7 @@ extern bNodeType tex_node_distance; extern bNodeType tex_node_rotate; extern bNodeType tex_node_translate; +extern bNodeType tex_node_scale; extern bNodeType tex_node_compose; extern bNodeType tex_node_decompose; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_compose.c b/source/blender/nodes/intern/TEX_nodes/TEX_compose.c index bb7a654b41f..26576befa3e 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_compose.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_compose.c @@ -53,19 +53,19 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) } bNodeType tex_node_compose= { - /* *next,*prev */ NULL, NULL, - /* type code */ TEX_NODE_COMPOSE, - /* name */ "Compose RGBA", - /* width+range */ 100, 60, 150, - /* class+opts */ NODE_CLASS_OP_COLOR, 0, - /* input sock */ inputs, - /* output sock */ outputs, - /* storage */ "", - /* execfunc */ exec, - /* butfunc */ NULL, - /* initfunc */ NULL, - /* freestoragefunc */ NULL, - /* copystoragefunc */ NULL, - /* id */ NULL + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_COMPOSE, + /* name */ "Compose RGBA", + /* width+range */ 100, 60, 150, + /* class+opts */ NODE_CLASS_OP_COLOR, 0, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL }; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c b/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c index 3a4710ce98f..c08eb12a18f 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_decompose.c @@ -30,14 +30,14 @@ #include static bNodeSocketType inputs[]= { - { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, { -1, 0, "" } }; static bNodeSocketType outputs[]= { - { SOCK_VALUE, 1, "Red", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, - { SOCK_VALUE, 1, "Green", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, - { SOCK_VALUE, 1, "Blue", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, - { SOCK_VALUE, 1, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 0, "Red", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 0, "Green", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 0, "Blue", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, + { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, { -1, 0, "" } }; diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_math.c b/source/blender/nodes/intern/TEX_nodes/TEX_math.c index a2c66078692..bac91fc0901 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_math.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_math.c @@ -143,6 +143,29 @@ static void valuefn(float *out, float *coord, bNode *node, bNodeStack **in, shor *out= (int)(in0 + 0.5f); } break; + + case 15: /* Less Than */ + { + if( in0 < in1 ) + *out= 1.0f; + else + *out= 0.0f; + } + break; + + case 16: /* Greater Than */ + { + if( in0 > in1 ) + *out= 1.0f; + else + *out= 0.0f; + } + break; + + default: + fprintf(stderr, + "%s:%d: unhandeld value in switch statement: %d\n", + __FILE__, __LINE__, node->custom1); } } diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c b/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c index 93bf17d4862..3a2c2b1def1 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c @@ -91,8 +91,6 @@ static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, shor static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { tex_output(node, in, out[0], &colorfn); - - tex_do_preview(node, out[0], data); } bNodeType tex_node_rotate= { diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_scale.c b/source/blender/nodes/intern/TEX_nodes/TEX_scale.c new file mode 100644 index 00000000000..792c3468e9f --- /dev/null +++ b/source/blender/nodes/intern/TEX_nodes/TEX_scale.c @@ -0,0 +1,76 @@ +/** + * + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include "../TEX_util.h" + +static bNodeSocketType inputs[]= { + { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, + { SOCK_VECTOR, 1, "Scale", 1.0f, 1.0f, 1.0f, 0.0f, -10.0f, 10.0f }, + { -1, 0, "" } +}; + +static bNodeSocketType outputs[]= { + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread) +{ + float scale[3], new_coord[3]; + + tex_input_vec(scale, in[1], coord, thread); + + new_coord[0] = coord[0] * scale[0]; + new_coord[1] = coord[1] * scale[1]; + new_coord[2] = coord[2] * scale[2]; + + tex_input_rgba(out, in[0], new_coord, thread); +} +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + tex_output(node, in, out[0], &colorfn); +} + +bNodeType tex_node_scale = { + /* *next,*prev */ NULL, NULL, + /* type code */ TEX_NODE_SCALE, + /* name */ "Scale", + /* width+range */ 90, 80, 100, + /* class+opts */ NODE_CLASS_DISTORT, NODE_OPTIONS, + /* input sock */ inputs, + /* output sock */ outputs, + /* storage */ "", + /* execfunc */ exec, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL +}; + diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_translate.c b/source/blender/nodes/intern/TEX_nodes/TEX_translate.c index bd7e61d0ff4..0e903301789 100644 --- a/source/blender/nodes/intern/TEX_nodes/TEX_translate.c +++ b/source/blender/nodes/intern/TEX_nodes/TEX_translate.c @@ -55,8 +55,6 @@ static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, shor static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { tex_output(node, in, out[0], &colorfn); - - tex_do_preview(node, out[0], data); } bNodeType tex_node_translate = { From e40803a5b3ac860f895c2180fe90f0040f3583d5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 6 Feb 2009 19:21:24 +0000 Subject: [PATCH 166/252] Fix for bug #18228: OpenGL specular did not get the correct view vector in perspective mode. This is default OpenGL behavior, but by now this optimization is really insignificant. Works in both the 3d view and game engine. --- source/blender/gpu/GPU_draw.h | 2 +- source/blender/gpu/intern/gpu_draw.c | 11 ++++++---- source/blender/include/BSE_view.h | 1 + source/blender/src/drawmesh.c | 6 +++-- source/blender/src/view.c | 22 +++++++++++++++++++ .../BlenderRoutines/KX_BlenderRenderTools.cpp | 9 ++++---- .../BlenderRoutines/KX_BlenderRenderTools.h | 4 ++-- .../GamePlayer/common/GPC_RenderTools.cpp | 9 ++++---- .../GamePlayer/common/GPC_RenderTools.h | 4 ++-- .../gameengine/Rasterizer/RAS_IRasterizer.h | 2 ++ .../gameengine/Rasterizer/RAS_IRenderTools.h | 1 + .../Rasterizer/RAS_MaterialBucket.cpp | 4 ++-- .../RAS_OpenGLRasterizer.cpp | 11 +++++++++- .../RAS_OpenGLRasterizer.h | 2 ++ 14 files changed, 66 insertions(+), 22 deletions(-) diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 2399e7b6a8c..a5a2e2dd13e 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -82,7 +82,7 @@ int GPU_set_tpage(struct MTFace *tface); int GPU_default_lights(void); int GPU_scene_object_lights(struct Scene *scene, struct Object *ob, - int lay, float viewmat[][4]); + int lay, float viewmat[][4], int ortho); /* Text render * - based on moving uv coordinates */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 4025a12a867..84bed5ccdbd 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -993,6 +993,8 @@ int GPU_default_lights(void) U.light[2].spec[3]= 1.0; } + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); + 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); @@ -1030,7 +1032,7 @@ int GPU_default_lights(void) return count; } -int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4]) +int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4], int ortho) { Base *base; Lamp *la; @@ -1041,6 +1043,10 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4 for(count=0; count<8; count++) glDisable(GL_LIGHT0+count); + /* view direction for specular is not compute correct by default in + * opengl, so we set the settings ourselfs */ + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (ortho)? GL_FALSE: GL_TRUE); + count= 0; for(base=scene->base.first; base; base=base->next) { @@ -1127,9 +1133,6 @@ void GPU_state_init(void) 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); diff --git a/source/blender/include/BSE_view.h b/source/blender/include/BSE_view.h index 55363bcf1f4..2a0485e229b 100644 --- a/source/blender/include/BSE_view.h +++ b/source/blender/include/BSE_view.h @@ -82,6 +82,7 @@ void viewmoveNDOF(int mode); void view_zoom_mouseloc(float dfac, short *mouseloc); int view_mouse_depth( float mouse_worldloc[3], short mval[2], int dist); +int get_view3d_ortho(struct View3D *v3d); int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize); void setwinmatrixview3d(int winx, int winy, struct rctf *rect); diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index ba266fa8c29..860bd8cee8f 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -75,6 +75,7 @@ #include "BDR_drawmesh.h" #include "BSE_drawview.h" +#include "BSE_view.h" #include "GPU_extensions.h" #include "GPU_draw.h" @@ -351,9 +352,10 @@ static void draw_textured_begin(Object *ob) solidtex= 1; Gtexdraw.islit= -1; } - else + 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= GPU_scene_object_lights(G.scene, ob, G.vd->lay, G.vd->viewmat, get_view3d_ortho(G.vd)); + } obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255); obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255); diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 8c16cfe705d..302bdf00e99 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -1579,6 +1579,28 @@ void object_view_settings(Object *ob, float *lens, float *clipsta, float *clipen } } +int get_view3d_ortho(View3D *v3d) +{ + Camera *cam; + + if(v3d->persp==V3D_CAMOB) { + if(v3d->camera && v3d->camera->type==OB_CAMERA) { + cam= v3d->camera->data; + + if(cam && cam->type==CAM_ORTHO) + return 1; + else + return 0; + } + else + return 0; + } + + if(v3d->persp==V3D_ORTHO) + return 1; + + return 0; +} int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize) { diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 1797d6c1a0f..42ad7769cbd 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -80,7 +80,7 @@ void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) * 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) +void KX_BlenderRenderTools::ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat) { if(m_lastlightlayer == layer) return; @@ -101,12 +101,12 @@ void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewm } if(enable) - EnableOpenGLLights(); + EnableOpenGLLights(rasty); else DisableOpenGLLights(); } -void KX_BlenderRenderTools::EnableOpenGLLights() +void KX_BlenderRenderTools::EnableOpenGLLights(RAS_IRasterizer *rasty) { if(m_lastlighting == true) return; @@ -115,7 +115,8 @@ void KX_BlenderRenderTools::EnableOpenGLLights() glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (rasty->GetCameraOrtho())? GL_FALSE: GL_TRUE); if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index a7618462c9b..ebf7562503f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -60,9 +60,9 @@ public: void EndFrame(RAS_IRasterizer* rasty); void BeginFrame(RAS_IRasterizer* rasty); - void EnableOpenGLLights(); + void EnableOpenGLLights(RAS_IRasterizer *rasty); void DisableOpenGLLights(); - void ProcessLighting(int layer, const MT_Transform& viewmat); + void ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat); void RenderText2D(RAS_TEXT_RENDER_MODE mode, const char* text, diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index 78d8eaf2aa3..c0d6248a3ca 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -85,7 +85,7 @@ void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty) * 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::ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat) { if(m_lastlightlayer == layer) return; @@ -106,12 +106,12 @@ void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) } if(enable) - EnableOpenGLLights(); + EnableOpenGLLights(rasty); else DisableOpenGLLights(); } -void GPC_RenderTools::EnableOpenGLLights() +void GPC_RenderTools::EnableOpenGLLights(RAS_IRasterizer *rasty) { if(m_lastlighting == true) return; @@ -120,7 +120,8 @@ void GPC_RenderTools::EnableOpenGLLights() glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (rasty->GetCameraOrtho())? GL_FALSE: GL_TRUE); if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index 382956e73ea..2a1b66a3aa9 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -65,9 +65,9 @@ public: void EndFrame(RAS_IRasterizer* rasty); void BeginFrame(RAS_IRasterizer* rasty); - void EnableOpenGLLights(); + void EnableOpenGLLights(RAS_IRasterizer *rasty); void DisableOpenGLLights(); - void ProcessLighting(int layer, const MT_Transform& viewmat); + void ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat); /* @attention mode is ignored here */ void RenderText2D(RAS_TEXT_RENDER_MODE mode, diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index b4b90c3608b..d529ca8973a 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -255,6 +255,8 @@ public: /** */ virtual const MT_Point3& GetCameraPosition()=0; + virtual bool GetCameraOrtho()=0; + /** */ virtual void SetFog(float start, diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h index 57f331e64cb..a289ffed492 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.h +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h @@ -134,6 +134,7 @@ public: virtual void ProcessLighting( + RAS_IRasterizer *rasty, int layer, const MT_Transform& trans )=0; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index ad8d7ebd5b0..d8631c1edf6 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -517,9 +517,9 @@ bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_I return false; if (m_material->UsesLighting(rasty)) - rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans); + rendertools->ProcessLighting(rasty, RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans); else - rendertools->ProcessLighting(-1, cameratrans); + rendertools->ProcessLighting(rasty, -1, cameratrans); return true; } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 3cad5fe74f2..08c600e7682 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -59,6 +59,8 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_2DCanvas(canvas), m_fogenabled(false), m_time(0.0), + m_campos(0.0f, 0.0f, 0.0f), + m_camortho(false), m_stereomode(RAS_STEREO_NOSTEREO), m_curreye(RAS_STEREO_LEFTEYE), m_eyeseparation(0.0), @@ -756,8 +758,9 @@ void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) glMatrixMode(GL_PROJECTION); double* matrix = &mat(0,0); glLoadMatrixd(matrix); -} + m_camortho= (mat(3, 3) != 0.0f); +} void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat) { @@ -767,6 +770,8 @@ void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat) mat.getValue(matrix); /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */ glLoadMatrixd(matrix); + + m_camortho= (mat[3][3] != 0.0f); } MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( @@ -883,6 +888,10 @@ const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition() return m_campos; } +bool RAS_OpenGLRasterizer::GetCameraOrtho() +{ + return m_camortho; +} void RAS_OpenGLRasterizer::SetCullFace(bool enable) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index d39fd642f86..c72d4880437 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -80,6 +80,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer MT_Matrix4x4 m_viewmatrix; MT_Matrix4x4 m_viewinvmatrix; MT_Point3 m_campos; + bool m_camortho; StereoMode m_stereomode; StereoEye m_curreye; @@ -168,6 +169,7 @@ public: ); virtual const MT_Point3& GetCameraPosition(); + virtual bool GetCameraOrtho(); virtual void SetFog( float start, From 59e96a2831ef52bff36f900bb4bb31fffe072f7d Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 7 Feb 2009 20:35:16 +0000 Subject: [PATCH 167/252] BGE Py API cleanup: Camera Actuator. --- .../gameengine/Ketsji/KX_CameraActuator.cpp | 35 +++++++++++++++++-- source/gameengine/Ketsji/KX_CameraActuator.h | 15 ++++---- source/gameengine/PyDoc/KX_CameraActuator.py | 9 +++++ 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 4d24e83843e..98dd9ab3e68 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -36,6 +36,7 @@ #include "KX_GameObject.h" #include "PyObjectPlus.h" +#include "blendef.h" STR_String KX_CameraActuator::X_AXIS_STRING = "x"; STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; @@ -52,9 +53,9 @@ STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; KX_CameraActuator::KX_CameraActuator( SCA_IObject* gameobj, SCA_IObject *obj, - MT_Scalar hght, - MT_Scalar minhght, - MT_Scalar maxhght, + float hght, + float minhght, + float maxhght, bool xytog, PyTypeObject* T ): @@ -399,6 +400,7 @@ PyParentObject KX_CameraActuator::Parents[] = { PyMethodDef KX_CameraActuator::Methods[] = { {"setObject",(PyCFunction) KX_CameraActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"getObject",(PyCFunction) KX_CameraActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, + // ---> deprecated {"setMin" ,(PyCFunction) KX_CameraActuator::sPySetMin, METH_VARARGS, (PY_METHODCHAR)SetMin_doc}, {"getMin" ,(PyCFunction) KX_CameraActuator::sPyGetMin, METH_NOARGS, (PY_METHODCHAR)GetMin_doc}, {"setMax" ,(PyCFunction) KX_CameraActuator::sPySetMax, METH_VARARGS, (PY_METHODCHAR)SetMax_doc}, @@ -410,9 +412,28 @@ PyMethodDef KX_CameraActuator::Methods[] = { {NULL,NULL,NULL,NULL} //Sentinel }; +PyAttributeDef KX_CameraActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RW("min",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_minHeight), + KX_PYATTRIBUTE_FLOAT_RW("max",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_maxHeight), + KX_PYATTRIBUTE_FLOAT_RW("height",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_height), + KX_PYATTRIBUTE_BOOL_RW("xy",KX_CameraActuator,m_x), + {NULL} +}; + PyObject* KX_CameraActuator::_getattr(const STR_String& attr) { + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_IActuator); } + +int KX_CameraActuator::_setattr(const STR_String& attr, PyObject* value) { + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + return SCA_IActuator::_setattr(attr, value); +} + /* get obj ---------------------------------------------------------- */ const char KX_CameraActuator::GetObject_doc[] = "getObject(name_only = 1)\n" @@ -462,6 +483,7 @@ PyObject* KX_CameraActuator::PyGetMin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getMin()", "the min property"); return PyFloat_FromDouble(m_minHeight); } /* set min ---------------------------------------------------------- */ @@ -472,6 +494,7 @@ PyObject* KX_CameraActuator::PySetMin(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setMin()", "the min property"); float min; if(PyArg_ParseTuple(args,"f", &min)) { @@ -488,6 +511,7 @@ PyObject* KX_CameraActuator::PyGetMax(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getMax()", "the max property"); return PyFloat_FromDouble(m_maxHeight); } /* set min ---------------------------------------------------------- */ @@ -498,6 +522,7 @@ PyObject* KX_CameraActuator::PySetMax(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getMax()", "the max property"); float max; if(PyArg_ParseTuple(args,"f", &max)) { @@ -514,6 +539,7 @@ PyObject* KX_CameraActuator::PyGetHeight(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getHeight()", "the height property"); return PyFloat_FromDouble(m_height); } /* set height ---------------------------------------------------------- */ @@ -524,6 +550,7 @@ PyObject* KX_CameraActuator::PySetHeight(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getHeight()", "the height property"); float height; if(PyArg_ParseTuple(args,"f", &height)) { @@ -541,6 +568,7 @@ PyObject* KX_CameraActuator::PySetXY(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setXY()", "the xy property"); int value; if(PyArg_ParseTuple(args,"i", &value)) { @@ -559,6 +587,7 @@ PyObject* KX_CameraActuator::PyGetXY(PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getXY()", "the xy property"); return PyInt_FromLong(m_x); } diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index d53d12b3b82..4acca12833c 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -59,13 +59,13 @@ private : //const MT_Scalar m_maxHeight; /** height (float), */ - MT_Scalar m_height; + float m_height; /** min (float), */ - MT_Scalar m_minHeight; + float m_minHeight; /** max (float), */ - MT_Scalar m_maxHeight; + float m_maxHeight; /** xy toggle (pick one): true == x, false == y */ bool m_x; @@ -88,9 +88,9 @@ private : SCA_IObject *gameobj, //const CValue *ob, SCA_IObject *ob, - MT_Scalar hght, - MT_Scalar minhght, - MT_Scalar maxhght, + float hght, + float minhght, + float maxhght, bool xytog, PyTypeObject* T=&Type @@ -121,7 +121,8 @@ private : /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); - + virtual int _setattr(const STR_String& attr, PyObject* value); + /* set object to look at */ KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject); /* get current object */ diff --git a/source/gameengine/PyDoc/KX_CameraActuator.py b/source/gameengine/PyDoc/KX_CameraActuator.py index 9a9abaf3d57..c4d5c9bcbfc 100644 --- a/source/gameengine/PyDoc/KX_CameraActuator.py +++ b/source/gameengine/PyDoc/KX_CameraActuator.py @@ -6,6 +6,15 @@ class KX_CameraActuator(SCA_IActuator): """ Applies changes to a camera. + @ivar min: minimum distance to the target object maintained by the actuator + @type min: float + @ivar max: maximum distance to stay from the target object + @type max: float + @ivar height: height to stay above the target object + @type height: float + @ivar xy: axis this actuator is tracking, true=X, false=Y + @type xy: boolean + @author: snail """ def getObject(name_only = 1): From 4f3768af4958dba8e3c9ca2f36f93b818e329735 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 7 Feb 2009 20:47:23 +0000 Subject: [PATCH 168/252] Update MSVC9 project files --- projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj | 9 +++++++++ projectfiles_vc9/blender/nodes/nodes.vcproj | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj b/projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj index 703a6407f9a..ed57fca060a 100644 --- a/projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj +++ b/projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj @@ -4,6 +4,7 @@ Version="9,00" Name="BL_imbuf" ProjectGUID="{415BFD6E-64CF-422B-AF88-C07F040A7292}" + RootNamespace="BL_imbuf" TargetFrameworkVersion="131072" > @@ -551,6 +552,10 @@ RelativePath="..\..\..\source\blender\imbuf\intern\iris.c" > + + @@ -829,6 +834,10 @@ RelativePath="..\..\..\source\blender\imbuf\intern\IMB_iris.h" > + + diff --git a/projectfiles_vc9/blender/nodes/nodes.vcproj b/projectfiles_vc9/blender/nodes/nodes.vcproj index 4b194c83c00..e782da120e1 100644 --- a/projectfiles_vc9/blender/nodes/nodes.vcproj +++ b/projectfiles_vc9/blender/nodes/nodes.vcproj @@ -4,6 +4,7 @@ Version="9,00" Name="BL_nodes" ProjectGUID="{4C3AB78A-52CA-4276-A041-39776E52D8C8}" + RootNamespace="BL_nodes" Keyword="Win32Proj" TargetFrameworkVersion="131072" > @@ -615,6 +616,10 @@ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_checker.c" > + + @@ -623,6 +628,10 @@ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_curves.c" > + + @@ -659,6 +668,10 @@ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_rotate.c" > + + @@ -667,6 +680,10 @@ RelativePath="..\..\..\source\blender\nodes\intern\TEX_nodes\TEX_translate.c" > + + From 0039da6ed82e3e9f365f8c79ea7a25b65d57e6da Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 8 Feb 2009 09:07:36 +0000 Subject: [PATCH 169/252] == REDCODE == * Fixed ntohl dependency (and hopefully 64bit issues) * Video length detection fixed (tests for picture presence) --- extern/libredcode/codec.c | 2 +- extern/libredcode/format.c | 28 ++++++++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/extern/libredcode/codec.c b/extern/libredcode/codec.c index e0b79119e80..f47a85cbb13 100644 --- a/extern/libredcode/codec.c +++ b/extern/libredcode/codec.c @@ -64,7 +64,7 @@ struct redcode_frame_raw * redcode_decode_video_raw( /* setup the decoder decoding parameters using the current image and user parameters */ opj_setup_decoder(dinfo, ¶meters); - + /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, frame->data + frame->offset, frame->length); diff --git a/extern/libredcode/format.c b/extern/libredcode/format.c index 4677c49b8a5..2406f3bb2c7 100644 --- a/extern/libredcode/format.c +++ b/extern/libredcode/format.c @@ -1,9 +1,3 @@ -#ifdef _WIN32 -#include -#else -#include -#endif - #include #include #include @@ -11,7 +5,7 @@ struct red_reob { unsigned long len; - char head[4]; + unsigned long head; unsigned long rdvo; unsigned long rdvs; @@ -38,8 +32,15 @@ struct redcode_handle { unsigned long * rdao; unsigned long * rdas; long cfra; + long length; }; +unsigned long read_be32(unsigned long val) +{ + unsigned char * v = (unsigned char*) & val; + + return (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3]; +} static unsigned char* read_packet(FILE * fp, char * expect) { @@ -52,7 +53,7 @@ static unsigned char* read_packet(FILE * fp, char * expect) head[4] = 0; - len = ntohl(len); + len = read_be32(len); if (strcmp(expect, head) != 0) { fprintf(stderr, "Read: %s, expect: %s\n", head, expect); @@ -79,7 +80,7 @@ static unsigned long * read_index_packet(FILE * fp, char * expect) } for (i = 2; i < rv[0]/4; i++) { - rv[i] = ntohl(rv[i]); + rv[i] = read_be32(rv[i]); } return rv; } @@ -109,6 +110,7 @@ struct redcode_handle * redcode_open(const char * fname) { struct redcode_handle * rv = NULL; struct red_reob * reob = NULL; + int i; FILE * fp = fopen(fname, "rb"); @@ -136,6 +138,12 @@ struct redcode_handle * redcode_open(const char * fname) return NULL; } + for (i = 0; i < (rv->rdvo[0] - 8)/4; i++) { + if (rv->rdvo[i + 2]) { + rv->length = i; + } + } + return rv; } @@ -162,7 +170,7 @@ void redcode_close(struct redcode_handle * handle) long redcode_get_length(struct redcode_handle * handle) { - return handle->rdvo[0]/4; + return handle->length; } struct redcode_frame * redcode_read_video_frame( From 270b724b8d653e75827a10bd236d82325ce700d3 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 8 Feb 2009 19:13:29 +0000 Subject: [PATCH 170/252] == REDCODE == Fixed 64bit issues. sizeof(unsigned long) = 8 on 64 bit machines, shame on me... --- extern/libredcode/format.c | 54 +++++++++++++++++++------------------- extern/libredcode/format.h | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/extern/libredcode/format.c b/extern/libredcode/format.c index 2406f3bb2c7..cf8f9d5faa7 100644 --- a/extern/libredcode/format.c +++ b/extern/libredcode/format.c @@ -4,38 +4,38 @@ #include "format.h" struct red_reob { - unsigned long len; - unsigned long head; + unsigned int len; + unsigned int head; - unsigned long rdvo; - unsigned long rdvs; - unsigned long rdao; - unsigned long rdas; + unsigned int rdvo; + unsigned int rdvs; + unsigned int rdao; + unsigned int rdas; - unsigned long unknown1; - unsigned long unknown2; - unsigned long totlen; + unsigned int unknown1; + unsigned int unknown2; + unsigned int totlen; - unsigned long avgv; - unsigned long avgs; + unsigned int avgv; + unsigned int avgs; - unsigned long unknown3; - unsigned long unknown4; - unsigned long unknown5; + unsigned int unknown3; + unsigned int unknown4; + unsigned int unknown5; }; struct redcode_handle { FILE * fp; struct red_reob * reob; - unsigned long * rdvo; - unsigned long * rdvs; - unsigned long * rdao; - unsigned long * rdas; + unsigned int * rdvo; + unsigned int * rdvs; + unsigned int * rdao; + unsigned int * rdas; long cfra; long length; }; -unsigned long read_be32(unsigned long val) +unsigned int read_be32(unsigned int val) { unsigned char * v = (unsigned char*) & val; @@ -44,7 +44,7 @@ unsigned long read_be32(unsigned long val) static unsigned char* read_packet(FILE * fp, char * expect) { - unsigned long len; + unsigned int len; char head[5]; unsigned char * rv; @@ -70,9 +70,9 @@ static unsigned char* read_packet(FILE * fp, char * expect) return rv; } -static unsigned long * read_index_packet(FILE * fp, char * expect) +static unsigned int * read_index_packet(FILE * fp, char * expect) { - unsigned long * rv = (unsigned long*) read_packet(fp, expect); + unsigned int * rv = (unsigned int*) read_packet(fp, expect); int i; if (!rv) { @@ -92,14 +92,14 @@ static struct red_reob * read_reob(FILE * fp) return (struct red_reob *) read_index_packet(fp, "REOB"); } -static unsigned long * read_index(FILE * fp, unsigned long i, char * expect) +static unsigned int * read_index(FILE * fp, unsigned int i, char * expect) { fseek(fp, i, SEEK_SET); - return (unsigned long*) read_index_packet(fp, expect); + return (unsigned int*) read_index_packet(fp, expect); } -static unsigned char * read_data(FILE * fp, unsigned long i, char * expect) +static unsigned char * read_data(FILE * fp, unsigned int i, char * expect) { fseek(fp, i, SEEK_SET); @@ -190,7 +190,7 @@ struct redcode_frame * redcode_read_video_frame( rv = (struct redcode_frame*) calloc(1, sizeof(struct redcode_frame)); rv->offset = 12+8; - rv->length = *(unsigned long*)data - rv->offset; + rv->length = *(unsigned int*)data - rv->offset; rv->data = data; return rv; @@ -213,7 +213,7 @@ struct redcode_frame * redcode_read_audio_frame( rv = (struct redcode_frame*) calloc(1, sizeof(struct redcode_frame)); rv->offset = 24+8; - rv->length = *(unsigned long*)data - rv->offset; + rv->length = *(unsigned int*)data - rv->offset; rv->data = data; return rv; diff --git a/extern/libredcode/format.h b/extern/libredcode/format.h index e09ea8a3b64..b2c6b2d885b 100644 --- a/extern/libredcode/format.h +++ b/extern/libredcode/format.h @@ -3,8 +3,8 @@ struct redcode_handle; struct redcode_frame { - unsigned long length; - unsigned long offset; + unsigned int length; + unsigned int offset; unsigned char * data; }; From 7877fb2f83e58d2bc828a1cdc34148b8939703a3 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 8 Feb 2009 19:28:12 +0000 Subject: [PATCH 171/252] == Sequencer == Fixed proxy scale problems in transform effect --- source/blender/src/seqeffects.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/source/blender/src/seqeffects.c b/source/blender/src/seqeffects.c index 58554fbfeba..a72feeb60c4 100644 --- a/source/blender/src/seqeffects.c +++ b/source/blender/src/seqeffects.c @@ -924,18 +924,18 @@ static void free_gammacross(Sequence * seq) static void do_gammacross_effect_byte(float facf0, float facf1, int x, int y, - char *rect1, - char *rect2, - char *out) + unsigned char *rect1, + unsigned char *rect2, + unsigned char *out) { int fac1, fac2, col; int xo; - char *rt1, *rt2, *rt; + unsigned char *rt1, *rt2, *rt; xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; + rt1= (unsigned char *)rect1; + rt2= (unsigned char *)rect2; + rt= (unsigned char *)out; fac2= (int)(256.0*facf0); fac1= 256-fac2; @@ -1994,6 +1994,9 @@ static void do_transform(Sequence * seq,float facf0, int x, int y, float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py; TransformVars *scale; + struct RenderData *rd = &G.scene->r; + + scale = (TransformVars *)seq->effectdata; xo = x; yo = y; @@ -2017,6 +2020,9 @@ static void do_transform(Sequence * seq,float facf0, int x, int y, s= sin(rad); c= cos(rad); + tx *= (rd->size / 100.0f); + ty *= (rd->size / 100.0f); + for (yi = 0; yi < yo; yi++) { for (xi = 0; xi < xo; xi++) { //tranlate point From ecf5250cf39db6093b8069f710bda9adae1fbd8b Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 8 Feb 2009 19:54:11 +0000 Subject: [PATCH 172/252] == Sequencer == Fix for the transform fix. It's getting late... --- source/blender/src/seqeffects.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/src/seqeffects.c b/source/blender/src/seqeffects.c index a72feeb60c4..6b25499fe6b 100644 --- a/source/blender/src/seqeffects.c +++ b/source/blender/src/seqeffects.c @@ -2007,8 +2007,10 @@ static void do_transform(Sequence * seq,float facf0, int x, int y, //Factor translate if(!scale->percent){ - tx = scale->xIni+(xo / 2.0f) + (scale->xFin-(xo / 2.0f) - scale->xIni+(xo / 2.0f)) * facf0; - ty = scale->yIni+(yo / 2.0f) + (scale->yFin-(yo / 2.0f) - scale->yIni+(yo / 2.0f)) * facf0; + float rd_s = (rd->size / 100.0f); + + tx = scale->xIni * rd_s+(xo / 2.0f) + (scale->xFin * rd_s -(xo / 2.0f) - scale->xIni * rd_s +(xo / 2.0f)) * facf0; + ty = scale->yIni * rd_s+(yo / 2.0f) + (scale->yFin * rd_s -(yo / 2.0f) - scale->yIni * rd_s +(yo / 2.0f)) * facf0; }else{ tx = xo*(scale->xIni/100.0f)+(xo / 2.0f) + (xo*(scale->xFin/100.0f)-(xo / 2.0f) - xo*(scale->xIni/100.0f)+(xo / 2.0f)) * facf0; ty = yo*(scale->yIni/100.0f)+(yo / 2.0f) + (yo*(scale->yFin/100.0f)-(yo / 2.0f) - yo*(scale->yIni/100.0f)+(yo / 2.0f)) * facf0; @@ -2020,8 +2022,6 @@ static void do_transform(Sequence * seq,float facf0, int x, int y, s= sin(rad); c= cos(rad); - tx *= (rd->size / 100.0f); - ty *= (rd->size / 100.0f); for (yi = 0; yi < yo; yi++) { for (xi = 0; xi < xo; xi++) { From 41a7b23c4100240bb35cadd57f13972d422c1269 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 9 Feb 2009 04:18:30 +0000 Subject: [PATCH 173/252] - Py seq API - Added an option for seq_strip.update() to run update_changed_seq_and_deps and new_tstripdata - Render stamp sequencer option wasn't ignoring muted strips. --- source/blender/python/api2_2x/sceneSequence.c | 14 +++++++++++--- source/blender/src/editseq.c | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index 8775ae9dc63..afcc8e0588d 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -102,7 +102,7 @@ returns None if notfound.\nIf 'name' is not specified, it returns a list of all /* Python BPy_Sequence methods table: */ /*****************************************************************************/ static PyObject *Sequence_copy(BPy_Sequence * self); -static PyObject *Sequence_update(BPy_Sequence * self); +static PyObject *Sequence_update(BPy_Sequence * self, PyObject *args); static PyObject *Sequence_new(BPy_Sequence * self, PyObject * args); static PyObject *Sequence_remove(BPy_Sequence * self, PyObject * args); static PyObject *Sequence_rebuildProxy(BPy_Sequence * self); @@ -121,7 +121,7 @@ static PyMethodDef BPy_Sequence_methods[] = { "() - Return a copy of the sequence containing the same objects."}, {"copy", (PyCFunction) Sequence_copy, METH_NOARGS, "() - Return a copy of the sequence containing the same objects."}, - {"update", (PyCFunction) Sequence_update, METH_NOARGS, + {"update", (PyCFunction) Sequence_update, METH_VARARGS, "() - Force and update of the sequence strip"}, {"rebuildProxy", (PyCFunction) Sequence_rebuildProxy, METH_VARARGS, "() - Rebuild the active strip's Proxy."}, @@ -587,8 +587,16 @@ static PyObject *Sequence_copy(BPy_Sequence * self) Py_RETURN_NONE; } -static PyObject *Sequence_update(BPy_Sequence * self) +static PyObject *Sequence_update(BPy_Sequence * self, PyObject *args) { + int data= 0; + if (!PyArg_ParseTuple(args, "|i:update", &data)) + return NULL; + + if (data) { + update_changed_seq_and_deps(self->seq, 1, 1); + new_tstripdata(self->seq); + } calc_sequence(self->seq); calc_sequence_disp(self->seq); Py_RETURN_NONE; diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index d16e3f28671..76e44e5c24f 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -183,7 +183,7 @@ Sequence *get_forground_frame_seq(int frame) if(!ed) return NULL; for (seq=ed->seqbasep->first; seq; seq= seq->next) { - if(seq->startdisp > frame || seq->enddisp <= frame) + if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame) continue; /* only use elements you can see - not */ if (ELEM6(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_MOVIE_AND_HD_SOUND, SEQ_COLOR)) { From 227c84f64ecbdb82fe5a73a71d542efa0076a69f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 10 Feb 2009 02:43:35 +0000 Subject: [PATCH 174/252] dpx/cineon was using the OUTPUT settings when loading DPX - white point, blackpoint, gamma, log. Allow DPX's with different color channel types to load, even if they are unsupported. Saving log DPX's is broken, the header will always be written with log off because dpxCreate is called before the image presets are set. However there is no access to image presets before running dpxCreate() so log data is written but the header always sets it off. Made a fix for this but couldn't test because it seems loading log images is also broken. Enable verbose DPX output when '-d' debug flag is used. --- .../blender/imbuf/intern/cineon/cineon_dpx.c | 9 ++---- source/blender/imbuf/intern/cineon/dpxlib.c | 32 ++++++++++++++++++- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index 514d6b5522b..203eb8fe314 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -56,7 +56,6 @@ static void cineon_conversion_parameters(LogImageByteConversionParameters *param static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags) { - LogImageByteConversionParameters conversion; ImBuf *ibuf; LogImageFile *image; int x, y; @@ -64,7 +63,7 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int int width, height, depth; float *frow; - cineon_conversion_parameters(&conversion); + logImageSetVerbose((G.f & G_DEBUG) ? 1:0); image = logImageOpenFromMem(mem, size, use_cineon); @@ -85,15 +84,13 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int return NULL; } - logImageSetByteConversion(image, &conversion); - ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags, 0); row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c"); frow = ibuf->rect_float+width*height*4; for (y = 0; y < height; y++) { - logImageGetRowBytes(image, row, y); + logImageGetRowBytes(image, row, y); /* checks image->params.doLogarithm and convert */ upix = row; frow -= width*4; @@ -143,7 +140,7 @@ static int imb_save_dpx_cineon(ImBuf *buf, char *filename, int use_cineon, int f } } - logImageSetVerbose(0); + logImageSetVerbose((G.f & G_DEBUG) ? 1:0); logImage = logImageCreate(filename, use_cineon, width, height, depth); if (!logImage) return 0; diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index 8a9adc73cdc..37e7ef3fc33 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -477,19 +477,49 @@ intern_dpxOpen(int mode, const char* bytestuff, int bufsize) { logImageGetByteConversionDefaults(&dpx->params); /* The SMPTE define this code: + * 0 - User-defined + * 1 - Printing density * 2 - Linear * 3 - Logarithmic + * 4 - Unspecified video + * 5 - SMPTE 240M + * 6 - CCIR 709-1 + * 7 - CCIR 601-2 system B or G + * 8 - CCIR 601-2 system M + * 9 - NTSC composite video + * 10 - PAL composite video + * 11 - Z linear + * 12 - homogeneous * * Note that transfer_characteristics is U8, don't need * check the byte order. */ + switch (header.imageInfo.channel[0].transfer_characteristics) { - case 2: + case 1: + case 2: /* linear */ dpx->params.doLogarithm= 0; break; + case 3: dpx->params.doLogarithm= 1; break; + + /* TODO - Unsupported, but for now just load them, + * colors may look wrong, but can solve color conversion later + */ + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + if (verbose) d_printf("Un-supported Transfer Characteristics: %d using linear color conversion\n", header.imageInfo.channel[0].transfer_characteristics); + dpx->params.doLogarithm= 0; + break; default: if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics); dpxClose(dpx); From fec8107281dcf4fc751805efd0521bf248e6ef03 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 11 Feb 2009 08:16:42 +0000 Subject: [PATCH 175/252] Once a linked image was selected, from a texture there was no way to switch to a local image because the dropdown was blocked with a linked library error message. Remove linked library checking from this image selector, this isn't quite correct since the texture could be linked too, however there is no access to the texture data (or other users) when this button is drawn. --- source/blender/src/buttons_shading.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 4ca1c13ddb2..98b78d54fff 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1126,9 +1126,10 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser, IMAnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), NULL, &iuser->menunr); uiBlockBeginAlign(block); + uiClearButLock(); /* no way to check if the image user is libdata or not, so assume its not, otherwise we cant select linked images - ANNOYING */ but= uiDefButS(block, MENU, imagechanged, strp, 10,155,23,20, &iuser->menunr, 0, 0, 0, 0, "Selects an existing Image or Movie"); uiButSetFunc(but, image_browse_cb, ima_pp, iuser); - + uiSetButLock(ima && (ima->id.lib!=NULL), ERROR_LIBDATA_MESSAGE); MEM_freeN(strp); /* name + options, or only load */ From c12149cf260e48713e48e452f51f739d60ecce69 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 12 Feb 2009 01:46:38 +0000 Subject: [PATCH 176/252] According to Amir Ebrahimi, fbx vertex color is supposed to be between 0.0 and 1.0 rather then 0-255 At the moment I dont have a way to test this. --- release/scripts/export_fbx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/export_fbx.py b/release/scripts/export_fbx.py index 6f964118964..730776bf1b8 100644 --- a/release/scripts/export_fbx.py +++ b/release/scripts/export_fbx.py @@ -1446,13 +1446,13 @@ def write(filename, batch_objects = None, \ for f in me.faces: for col in f.col: if i==-1: - file.write('%i,%i,%i,255' % (col[0], col[1], col[2])) + file.write('%.4f,%.4f,%.4f,1' % (col[0]/255.0, col[1]/255.0, col[2]/255.0)) i=0 else: if i==7: file.write('\n\t\t\t\t') i=0 - file.write(',%i,%i,%i,255' % (col[0], col[1], col[2])) + file.write(',%.4f,%.4f,%.4f,1' % (col[0]/255.0, col[1]/255.0, col[2]/255.0)) i+=1 ii+=1 # One more Color From 64d2984aa0b9687c277f8ca7a4e8622ec92758a4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 12 Feb 2009 16:27:19 +0000 Subject: [PATCH 177/252] add some more modifier types and access to shrink wrap target object (but no other shrink wrap settings) --- source/blender/python/api2_2x/Modifier.c | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/source/blender/python/api2_2x/Modifier.c b/source/blender/python/api2_2x/Modifier.c index dde21b13722..b43c810b435 100644 --- a/source/blender/python/api2_2x/Modifier.c +++ b/source/blender/python/api2_2x/Modifier.c @@ -982,6 +982,41 @@ static int displace_setter( BPy_Modifier *self, int type, PyObject *value ) } } +static PyObject *shrinkwrap_getter( BPy_Modifier * self, int type ) +{ + ShrinkwrapModifierData *md = (ShrinkwrapModifierData *)(self->md); + + switch( type ) { + case EXPP_MOD_OBJECT: + return Object_CreatePyObject( md->target ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +static int shrinkwrap_setter( BPy_Modifier *self, int type, PyObject *value ) +{ + ShrinkwrapModifierData *md = (ShrinkwrapModifierData *)(self->md); + + switch( type ) { + case EXPP_MOD_OBJECT: { /* Only object for now */ + Object *ob_new=NULL; + if (value == Py_None) { + md->target = NULL; + } else if (BPy_Object_Check( value )) { + ob_new = ((( BPy_Object * )value)->object); + md->target = ob_new; + } else { + return EXPP_ReturnIntError( PyExc_TypeError, + "Expected an Object or None value" ); + } + return 0; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } +} + /* static PyObject *uvproject_getter( BPy_Modifier * self, int type ) { @@ -1062,6 +1097,8 @@ static PyObject *Modifier_getData( BPy_Modifier * self, PyObject * key ) return edgesplit_getter( self, setting ); case eModifierType_Displace: return displace_getter( self, setting ); + case eModifierType_Shrinkwrap: + return shrinkwrap_getter( self, setting ); /*case eModifierType_UVProject: return uvproject_getter( self, setting );*/ case eModifierType_Hook: @@ -1132,6 +1169,8 @@ static int Modifier_setData( BPy_Modifier * self, PyObject * key, return edgesplit_setter( self, key_int, arg ); case eModifierType_Displace: return displace_setter( self, key_int, arg ); + case eModifierType_Shrinkwrap: + return shrinkwrap_setter( self, key_int, arg ); /*case eModifierType_UVProject: return uvproject_setter( self, key_int, arg );*/ case eModifierType_Hook: @@ -1550,6 +1589,22 @@ static PyObject *M_Modifier_TypeDict( void ) PyInt_FromLong( eModifierType_Cast ) ); PyConstant_Insert( d, "DISPLACE", PyInt_FromLong( eModifierType_Displace ) ); + PyConstant_Insert( d, "MESHDEFORM", + PyInt_FromLong( eModifierType_MeshDeform ) ); + PyConstant_Insert( d, "PARTICLESYSTEM", + PyInt_FromLong( eModifierType_ParticleSystem ) ); + PyConstant_Insert( d, "PARTICLEINSTANCE", + PyInt_FromLong( eModifierType_ParticleInstance ) ); + PyConstant_Insert( d, "EXPLODE", + PyInt_FromLong( eModifierType_Explode ) ); + PyConstant_Insert( d, "CLOTH", + PyInt_FromLong( eModifierType_Cloth ) ); + PyConstant_Insert( d, "BEVEL", + PyInt_FromLong( eModifierType_Bevel ) ); + PyConstant_Insert( d, "SHRINKWRAP", + PyInt_FromLong( eModifierType_Shrinkwrap ) ); + PyConstant_Insert( d, "SHRINKWRAP", + PyInt_FromLong( eModifierType_Shrinkwrap ) ); } return S; } From b052ae4cdbfea85d50827efd10a5a4e953836463 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 13 Feb 2009 06:24:15 +0000 Subject: [PATCH 178/252] [#18209] 3 VSE crash bugs with .blends (all left click and move mouse over Metastrip/Blend Mode related) Workaround for a bug where dragging the playhead over a metastrip with blending on it could segfault blender. Tried to figure out why the imbuf rect is not set, but for now a NULL check stops the crash. --- source/blender/src/sequence.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 219768b2776..3c3c7c7b30a 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2111,6 +2111,14 @@ static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra) } } +/* Bug: 18209 + * when dragging the mouse over a metastrip, on mouse-up for some unknown + * reason in some cases the metastrips TStripElem->ibuf->rect is NULL, + * This should be fixed but I had a look and couldnt work out why its + * happening so for now workaround with a NULL check - campbell */ + +#define SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND + static TStripElem* do_build_seq_array_recursively( ListBase *seqbasep, int cfra, int chanshown) { @@ -2277,7 +2285,14 @@ static TStripElem* do_build_seq_array_recursively( !se2->ibuf_comp->rect_float) { IMB_rect_from_float(se2->ibuf); } - + +#ifdef SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND + if (se2->ibuf->rect==NULL && se2->ibuf->rect_float==NULL) { + printf("ERROR: sequencer se2->ibuf missing buffer\n"); + } else if (se1->ibuf->rect==NULL && se1->ibuf->rect_float==NULL) { + printf("ERROR: sequencer se1->ibuf missing buffer\n"); + } else { +#endif /* bad hack, to fix crazy input ordering of those two effects */ @@ -2299,6 +2314,10 @@ static TStripElem* do_build_seq_array_recursively( se2->ibuf_comp); } +#ifdef SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND + } +#endif + IMB_cache_limiter_insert(se2->ibuf_comp); IMB_cache_limiter_ref(se2->ibuf_comp); IMB_cache_limiter_touch(se2->ibuf_comp); From 915baae622233e89ae721ef2562732564e58fb27 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 15 Feb 2009 19:07:27 +0000 Subject: [PATCH 179/252] BGE bug #18137 fixed: When two actors collide in this blend file the blender crashes. --- source/gameengine/Ketsji/KX_TouchSensor.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 1935a0bde39..849972955af 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -100,8 +100,8 @@ m_eventmgr(eventmgr) m_colliders = new CListValue(); KX_ClientObjectInfo *client_info = gameobj->getClientInfo(); - client_info->m_gameobject = gameobj; - client_info->m_auxilary_info = NULL; + //client_info->m_gameobject = gameobj; + //client_info->m_auxilary_info = NULL; client_info->m_sensors.push_back(this); m_physCtrl = dynamic_cast(gameobj->GetPhysicsController()); @@ -143,8 +143,8 @@ void KX_TouchSensor::ReParent(SCA_IObject* parent) // m_solidHandle = m_sumoObj->getObjectHandle(); KX_ClientObjectInfo *client_info = gameobj->getClientInfo(); - client_info->m_gameobject = gameobj; - client_info->m_auxilary_info = NULL; + //client_info->m_gameobject = gameobj; + //client_info->m_auxilary_info = NULL; client_info->m_sensors.push_back(this); SCA_ISensor::ReParent(parent); @@ -354,7 +354,7 @@ PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self, if (spc) { KX_ClientObjectInfo* cl_inf = static_cast(spc->getNewClientInfo()); - if (m_touchedpropname == ((char*)cl_inf->m_auxilary_info)) { + if (NULL != cl_inf->m_auxilary_info && m_touchedpropname == ((char*)cl_inf->m_auxilary_info)) { newList->Add(m_colliders->GetValue(i)->AddRef()); } } From c3d74547befb549cb3104d39797519a32afb2f35 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 15 Feb 2009 23:26:00 +0000 Subject: [PATCH 180/252] SCons: * giving compileflags, cc_compileflags and cxx_compileflags to BlenderLib() now actually overrides any other setting (so there's no unclarity when ie. conflicting options are being specified in REL_CFLAGS et al). These are set after either release or debug flags, but before any *_WARN flags (so those stay maintained). * add cxx_compileflags for GE parts on win32-vc to have better performance. * NOTE: if platform maintainers (OSX and Linux) could check and do the same for their systems. Not vital, but probably very, very much welcomed by GE users. --- extern/bullet2/src/SConscript | 2 +- source/gameengine/BlenderRoutines/SConscript | 3 ++- source/gameengine/Expressions/SConscript | 7 ++++++- source/gameengine/GameLogic/SConscript | 7 ++++++- source/gameengine/GamePlayer/common/SConscript | 7 ++++--- source/gameengine/GamePlayer/ghost/SConscript | 8 +++++--- source/gameengine/Ketsji/KXNetwork/SConscript | 8 +++++++- source/gameengine/Ketsji/SConscript | 12 ++++++------ source/gameengine/Physics/Bullet/SConscript | 8 ++++---- source/gameengine/Physics/common/SConscript | 7 ++++++- .../Rasterizer/RAS_OpenGLRasterizer/SConscript | 7 ++++++- source/gameengine/Rasterizer/SConscript | 10 +++++----- source/gameengine/SceneGraph/SConscript | 7 ++++++- source/gameengine/VideoTexture/SConscript | 11 ++++++----- tools/Blender.py | 6 +++--- 15 files changed, 73 insertions(+), 37 deletions(-) diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 203407569b1..48e30cdf58a 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -10,7 +10,7 @@ cflags = [] if env['OURPLATFORM']=='win32-vc': defs += ' WIN32 NDEBUG _WINDOWS _LIB' #cflags += ['/MT', '/W3', '/GX', '/O2', '/Op'] - cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6'] + cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6', '/O3'] elif env['OURPLATFORM']=='win32-mingw': defs += ' NDEBUG' cflags += ['-O2'] diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index 78adbc83d9b..7a1bf4d9ad6 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -25,5 +25,6 @@ incs += ' ' + env['BF_OPENGL_INC'] cxxflags = [] if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/GR') + cxxflags.append ('/O2') -env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , compileflags=cxxflags) +env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , cxx_compileflags=cxxflags) diff --git a/source/gameengine/Expressions/SConscript b/source/gameengine/Expressions/SConscript index 809ac31371e..3d855d40623 100644 --- a/source/gameengine/Expressions/SConscript +++ b/source/gameengine/Expressions/SConscript @@ -6,4 +6,9 @@ sources = env.Glob('*.cpp') incs ='. #source/kernel/gen_system #intern/string #intern/moto/include' incs += ' ' + env['BF_PYTHON_INC'] -env.BlenderLib ( 'bf_expressions', sources, Split(incs), [], libtype=['game','player'], priority = [45,125] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_expressions', sources, Split(incs), [], libtype=['game','player'], priority = [45,125], cxx_compileflags=cxxflags) diff --git a/source/gameengine/GameLogic/SConscript b/source/gameengine/GameLogic/SConscript index b4e2159dc22..ebf225f728f 100644 --- a/source/gameengine/GameLogic/SConscript +++ b/source/gameengine/GameLogic/SConscript @@ -17,4 +17,9 @@ if env['WITH_BF_SDL']: else: defs += ' DISABLE_SDL' -env.BlenderLib ( 'bf_logic', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[30, 110] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_logic', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[30, 110], cxx_compileflags=cxxflags ) diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index 30f20a670d3..c9bda78d905 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -67,8 +67,9 @@ incs += Split(env['BF_SOLID_INC']) incs += Split(env['BF_PNG_INC']) incs += Split(env['BF_ZLIB_INC']) -cflags=[] +cxxflags = [] if env['OURPLATFORM']=='win32-vc': - cflags = ['/GR'] + cxxflags.append ('/GR') + cxxflags.append ('/O2') -env.BlenderLib (libname='gp_common', sources=source_files, includes=incs, defines = [], libtype='player', priority=5, compileflags=cflags) +env.BlenderLib (libname='gp_common', sources=source_files, includes=incs, defines = [], libtype='player', priority=5, cxx_compileflags=cxxflags) diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 4f1324b3938..0785ce4bd0d 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -45,12 +45,14 @@ incs = ['.', incs += Split(env['BF_PYTHON_INC']) incs += Split(env['BF_SOLID_INC']) -cflags = [] + +cxxflags = [] if env['OURPLATFORM']=='win32-vc': - cflags = ['/GR'] + cxxflags.append ('/GR') + cxxflags.append ('/O2') defs = '' if env['WITH_BF_FFMPEG']: defs += ' WITH_FFMPEG' -env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = Split(defs), libtype='player',priority=0, compileflags=cflags) +env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = Split(defs), libtype='player',priority=0, cxx_compileflags=cxxflags) diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript index 2297b96c19e..2476ed1f275 100644 --- a/source/gameengine/Ketsji/KXNetwork/SConscript +++ b/source/gameengine/Ketsji/KXNetwork/SConscript @@ -9,4 +9,10 @@ incs += ' #source/gameengine/Network' incs += ' ' + env['BF_PYTHON_INC'] -env.BlenderLib ( 'kx_network', Split(sources), Split(incs), defines=[],libtype=['game2', 'player'], priority=[5, 155] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + + +env.BlenderLib ( 'kx_network', Split(sources), Split(incs), defines=[],libtype=['game2', 'player'], priority=[5, 155], cxx_compileflags=cxxflags ) diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index f5c620b583f..e9e68f14df8 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -34,11 +34,6 @@ incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/includ incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' 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') - incs += ' ' + env['BF_SOLID_INC'] incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_BULLET_INC'] @@ -47,4 +42,9 @@ incs += ' ' + env['BF_OPENGL_INC'] if env['WITH_BF_SDL']: incs += ' ' + env['BF_SDL_INC'] -env.BlenderLib ( 'bf_ketsji', sources, Split(incs), [], libtype=['game','player'], priority=[25, 72], compileflags = cflags ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_ketsji', sources, Split(incs), [], libtype=['game','player'], priority=[25, 72], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript index 0936d45197a..0d5bf4933d8 100644 --- a/source/gameengine/Physics/Bullet/SConscript +++ b/source/gameengine/Physics/Bullet/SConscript @@ -7,9 +7,9 @@ incs = '. ../common #source/kernel/gen_system #intern/string #intern/moto/includ incs += ' ' + env['BF_BULLET_INC'] -cflags = [] +cxxflags = [] if env['OURPLATFORM']=='win32-vc': - cflags.append('/GR') - cflags.append('/O2') + cxxflags.append ('/GR') + cxxflags.append ('/O2') -env.BlenderLib ( 'bf_bullet', Split(sources), Split(incs), [], libtype=['game','player'], priority=[15,90] ) +env.BlenderLib ( 'bf_bullet', Split(sources), Split(incs), [], libtype=['game','player'], priority=[15,90], cxx_compileflags=cxxflags ) diff --git a/source/gameengine/Physics/common/SConscript b/source/gameengine/Physics/common/SConscript index 91c5101675e..474536e1f76 100644 --- a/source/gameengine/Physics/common/SConscript +++ b/source/gameengine/Physics/common/SConscript @@ -5,4 +5,9 @@ sources = 'PHY_IMotionState.cpp PHY_IPhysicsController.cpp PHY_IPhysicsEnvironme incs = '. ../Dummy #intern/moto/include' -env.BlenderLib ( 'bf_common', Split(sources), Split(incs), [], libtype=['game', 'game2','player'], priority=[20, 35, 95] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_common', Split(sources), Split(incs), [], libtype=['game', 'game2','player'], priority=[20, 35, 95], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index 8d46528f7f0..6731da9a776 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -6,4 +6,9 @@ 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'] -env.BlenderLib ( 'bf_oglrasterizer', Split(sources), Split(incs), [], libtype=['game','player'], priority=[40, 120] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_oglrasterizer', Split(sources), Split(incs), [], libtype=['game','player'], priority=[40, 120], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript index a024f7e0ee6..a16a04b8514 100644 --- a/source/gameengine/Rasterizer/SConscript +++ b/source/gameengine/Rasterizer/SConscript @@ -7,9 +7,9 @@ sources = env.Glob('*.cpp') 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'] +cxxflags = [] if env['OURPLATFORM']=='win32-vc': - cflags = [] - cflags.append('/Ox') - env.BlenderLib ( 'bf_rasterizer', sources, Split(incs), [], libtype=['game','player'], priority=[35,115], compileflags = cflags ) -else: - env.BlenderLib ( 'bf_rasterizer', sources, Split(incs), [], libtype=['game','player'], priority=[35,115] ) + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_rasterizer', sources, Split(incs), [], libtype=['game','player'], priority=[35,115], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/SceneGraph/SConscript b/source/gameengine/SceneGraph/SConscript index 23c1c24c297..8ebf9c0b850 100644 --- a/source/gameengine/SceneGraph/SConscript +++ b/source/gameengine/SceneGraph/SConscript @@ -6,4 +6,9 @@ sources = env.Glob('*.cpp') #'SG_BBox.cpp SG_Controller.cpp SG_IObject.cpp SG_No incs = '. #intern/moto/include' -env.BlenderLib ( 'bf_scenegraph', sources, Split(incs), [], libtype=['game','player'], priority=[50,130] ) +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + +env.BlenderLib ( 'bf_scenegraph', sources, Split(incs), [], libtype=['game','player'], priority=[50,130], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/VideoTexture/SConscript b/source/gameengine/VideoTexture/SConscript index f3fe0dab6ad..28737ed06e5 100644 --- a/source/gameengine/VideoTexture/SConscript +++ b/source/gameengine/VideoTexture/SConscript @@ -15,11 +15,12 @@ incs += ' #source/blender/gpu #source/kernel/gen_system #intern/string #intern/m incs += ' #intern/guardedalloc #intern/SoundSystem' incs += ' #extern/glew/include' -cflags = [] defs = '' -if env['OURPLATFORM'] == 'win32-vc': - cflags.append('/GR') - cflags.append('/Ox') +cxxflags = [] +if env['OURPLATFORM']=='win32-vc': + cxxflags.append ('/GR') + cxxflags.append ('/O2') + incs += ' ' + env['BF_PYTHON_INC'] #incs += ' ' + env['BF_OPENGL_INC'] @@ -29,4 +30,4 @@ if env['WITH_BF_FFMPEG']: incs += ' ' + env['BF_FFMPEG_INC'] defs += ' __STDC_CONSTANT_MACROS' -env.BlenderLib ( 'bf_videotex', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], compileflags = cflags ) +env.BlenderLib ( 'bf_videotex', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], cxx_compileflags = cxxflags ) diff --git a/tools/Blender.py b/tools/Blender.py index 1c54e98f177..9c978fccf49 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -434,11 +434,11 @@ class BlenderEnvironment(SConsEnvironment): lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS']) lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS']) if compileflags: - lenv.Append(CFLAGS = compileflags) + lenv.Replace(CFLAGS = compileflags) if cc_compileflags: - lenv.Append(CCFLAGS = cc_compileflags) + lenv.Replace(CCFLAGS = cc_compileflags) if cxx_compileflags: - lenv.Append(CXXFLAGS = cxx_compileflags) + lenv.Replace(CXXFLAGS = cxx_compileflags) lenv.Append(CFLAGS = lenv['C_WARN']) lenv.Append(CCFLAGS = lenv['CC_WARN']) lenv.Append(CXXFLAGS = lenv['CXX_WARN']) From 25ab5159511f75d1dc2048f805978dfb7c51e1a4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 Feb 2009 03:43:56 +0000 Subject: [PATCH 181/252] bugfix [#18003] Rev-17473: Scene sets doesn't work in links --- source/blender/blenloader/intern/readfile.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6579d2cd4c1..dc9c97cb3f5 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8816,6 +8816,9 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) expand_doit(fd, mainvar, sce->camera); expand_doit(fd, mainvar, sce->world); + if(sce->set) + expand_doit(fd, mainvar, sce->set); + if(sce->nodetree) expand_nodetree(fd, mainvar, sce->nodetree); From e5a5399c33738c297946b7d89a26b657531f8843 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 Feb 2009 04:11:20 +0000 Subject: [PATCH 182/252] [#17991] Anim rendered in BMP format won't play back fix from Sebastian Kochman (raiq) - [#18022] --- source/blender/quicktime/apple/quicktime_import.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/quicktime/apple/quicktime_import.c b/source/blender/quicktime/apple/quicktime_import.c index 5a3c76b9d6f..1f3071f114c 100644 --- a/source/blender/quicktime/apple/quicktime_import.c +++ b/source/blender/quicktime/apple/quicktime_import.c @@ -159,6 +159,7 @@ int anim_is_quicktime (char *name) BLI_testextensie(name, ".avi") || // wouldnt be appropriate ;) BLI_testextensie(name, ".tga") || BLI_testextensie(name, ".png") || + BLI_testextensie(name, ".bmp") || BLI_testextensie(name, ".jpg") || BLI_testextensie(name, ".wav") || BLI_testextensie(name, ".zip") || From def36ce180d740f48c27fe6994a67fc85b3305b0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 Feb 2009 04:32:49 +0000 Subject: [PATCH 183/252] fix for [#17972] Saving/Loading Radiance HDR changes colors removed HDR loop that loaded 8bit color channels (which was incorrect) and added a call to IMB_rect_from_float at the end. This also means that char buffers wont be created if they are not needed. --- source/blender/imbuf/intern/radiance_hdr.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index b4e384ada72..d00e34cfdbe 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -180,7 +180,6 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) int width=0, height=0; int x, y; unsigned char* ptr; - unsigned char* rect; char oriY[80], oriX[80]; if (imb_is_a_hdr((void*)mem)) @@ -201,7 +200,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) ptr++; if (flags & IB_test) ibuf = IMB_allocImBuf(width, height, 32, 0, 0); - else ibuf = IMB_allocImBuf(width, height, 32, IB_rect|IB_rectfloat, 0); + else ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect)|IB_rectfloat, 0); if (ibuf==NULL) return NULL; ibuf->ftype = RADHDR; @@ -211,7 +210,6 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) /* read in and decode the actual data */ sline = (RGBE*)MEM_mallocN(sizeof(RGBE)*width, "radhdr_read_tmpscan"); - rect = (unsigned char*)ibuf->rect; rect_float = (float *)ibuf->rect_float; for (y=0;y 1.f) ? 255 : (255.f*fcol[RED]))); - *rect++ = (unsigned char)((fcol[GRN] < 0.f) ? 0 : ((fcol[GRN] > 1.f) ? 255 : (255.f*fcol[GRN]))); - *rect++ = (unsigned char)((fcol[BLU] < 0.f) ? 0 : ((fcol[BLU] > 1.f) ? 255 : (255.f*fcol[BLU]))); - *rect++ = 255; } } MEM_freeN(sline); if (oriY[0]=='-') IMB_flipy(ibuf); + + if (flags & IB_rect) { + IMB_rect_from_float(ibuf); + } + return ibuf; } //else printf("Data not found!\n"); From 28245a754e6b50aa21db49f27b6ae0ac25295270 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 Feb 2009 14:41:36 +0000 Subject: [PATCH 184/252] python api bugfix, forgot to remove the cast from short to long when making x,y aspect floats. --- source/blender/python/api2_2x/sceneRender.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index 4e1051176fd..a0087689885 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -1889,10 +1889,10 @@ static PyObject *RenderData_getFloatAttr( BPy_RenderData *self, void *type ) param = self->renderContext->bake_biasdist; break; case EXPP_RENDER_ATTR_ASPECTX: - param = (long)self->renderContext->xasp; + param = self->renderContext->xasp; break; case EXPP_RENDER_ATTR_ASPECTY: - param = (long)self->renderContext->yasp; + param = self->renderContext->yasp; break; default: return EXPP_ReturnPyObjError( PyExc_RuntimeError, From f6b0b76fea40394059e575b844e5bf71f255e35f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Feb 2009 03:13:57 +0000 Subject: [PATCH 185/252] [#18159] Path -> toggle cyclic -> toggle cyclic again == path corrupted was not recalculating the knots when the cyclic flag was disabled so the endpoint flag was being ignored until recalculating (extrude for eg). Also removed unneeded re-allocation of curve knots which are always reallocated by makeknots. Fixed another bug with which recalculating knots with the Python surface api. (mixed up u/v args to makeknots(..) ) --- source/blender/python/api2_2x/SurfNurb.c | 2 +- source/blender/src/editcurve.c | 59 ++++-------------------- 2 files changed, 11 insertions(+), 50 deletions(-) diff --git a/source/blender/python/api2_2x/SurfNurb.c b/source/blender/python/api2_2x/SurfNurb.c index 65bd04de14d..deee6c07793 100644 --- a/source/blender/python/api2_2x/SurfNurb.c +++ b/source/blender/python/api2_2x/SurfNurb.c @@ -482,7 +482,7 @@ static int SurfNurb_setCyclicV( BPy_SurfNurb * self, PyObject * value ) self->nurb->flagv |= CU_CYCLIC; else self->nurb->flagv &= ~CU_CYCLIC; - makeknots( self->nurb, 2, self->nurb->flagu >> 1 ); + makeknots( self->nurb, 2, self->nurb->flagv >> 1 ); return 0; } diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index c26c44103c0..594ff816ec1 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -3065,8 +3065,8 @@ void makecyclicNurb() Nurb *nu; BezTriple *bezt; BPoint *bp; - float *fp; - int a, b, cyclmode=0; + + int a, cyclmode=0; for(nu= editNurb.first; nu; nu= nu->next) { if( nu->pntsu>1 || nu->pntsv>1) { @@ -3075,8 +3075,7 @@ void makecyclicNurb() bp= nu->bp; while(a--) { if( bp->f1 & SELECT ) { - if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC; - else nu->flagu |= CU_CYCLIC; + nu->flagu ^= CU_CYCLIC; break; } bp++; @@ -3087,8 +3086,7 @@ void makecyclicNurb() bezt= nu->bezt; while(a--) { if( BEZSELECTED_HIDDENHANDLES(bezt) ) { - if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC; - else nu->flagu |= CU_CYCLIC; + nu->flagu ^= CU_CYCLIC; break; } bezt++; @@ -3101,19 +3099,8 @@ void makecyclicNurb() bp= nu->bp; while(a--) { if( bp->f1 & SELECT ) { - if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC; - else { - nu->flagu |= CU_CYCLIC; - nu->flagu &= ~2; /* endpoint flag, fixme */ - fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN"); - b= (nu->orderu+nu->pntsu); - memcpy(fp, nu->knotsu, sizeof(float)*b); - MEM_freeN(nu->knotsu); - nu->knotsu= fp; - - makeknots(nu, 1, 0); /* 1==u 0==uniform */ - - } + nu->flagu ^= CU_CYCLIC; + makeknots(nu, 1, nu->flagu>>1); /* 1==u type is ignored for cyclic curves */ break; } bp++; @@ -3131,38 +3118,12 @@ void makecyclicNurb() if( bp->f1 & SELECT) { if(cyclmode==1 && nu->pntsu>1) { - if(nu->flagu & CU_CYCLIC) nu->flagu &= ~CU_CYCLIC; - else { - nu->flagu |= CU_CYCLIC; - if (check_valid_nurb_u(nu)) { - fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN"); - b= (nu->orderu+nu->pntsu); - if (nu->knotsu) { /* null if check_valid_nurb_u failed before but is valid now */ - memcpy(fp, nu->knotsu, sizeof(float)*b); - MEM_freeN(nu->knotsu); - } - nu->knotsu= fp; - - makeknots(nu, 1, 0); /* 1==u 0==uniform */ - } - } + nu->flagu ^= CU_CYCLIC; + makeknots(nu, 1, nu->flagu>>1); /* 1==u type is ignored for cyclic curves */ } if(cyclmode==2 && nu->pntsv>1) { - if(nu->flagv & 1) nu->flagv--; - else { - nu->flagv++; - if (check_valid_nurb_v(nu)) { - fp= MEM_mallocN(sizeof(float)*KNOTSV(nu), "makecyclicN"); - b= (nu->orderv+nu->pntsv); - if (nu->knotsv) { /* null if check_valid_nurb_v failed before but is valid now */ - memcpy(fp, nu->knotsv, sizeof(float)*b); - MEM_freeN(nu->knotsv); - } - nu->knotsv= fp; - - makeknots(nu, 2, 0); /* 2==v 0==uniform */ - } - } + nu->flagv ^= CU_CYCLIC; + makeknots(nu, 2, nu->flagv>>1); /* 2==v type is ignored for cyclic curves */ } break; } From 7a9688179580e3b1008941f339bdc906fa544360 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Feb 2009 03:56:16 +0000 Subject: [PATCH 186/252] disable texture clamping while painting. --- source/blender/gpu/intern/gpu_draw.c | 5 +++++ source/blender/src/editface.c | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 84bed5ccdbd..3c1c280a727 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -167,6 +167,8 @@ static int smaller_pow2(int num) static int is_pow2_limit(int num) { /* take texture clamping into account */ + if (G.f & G_TEXTUREPAINT) + return 1; if (U.glreslimit != 0 && num > U.glreslimit) return 0; @@ -175,6 +177,9 @@ static int is_pow2_limit(int num) static int smaller_pow2_limit(int num) { + if (G.f & G_TEXTUREPAINT) + return 1; + /* take texture clamping into account */ if (U.glreslimit != 0 && num > U.glreslimit) return U.glreslimit; diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index 9872469030a..f6a0b88cbc8 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -51,6 +51,7 @@ #include "DNA_space_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" +#include "DNA_userdef_types.h" #include "DNA_view3d_types.h" #include "BKE_brush.h" @@ -1321,6 +1322,10 @@ void set_texturepaint() /* toggle */ if(G.f & G_TEXTUREPAINT) { G.f &= ~G_TEXTUREPAINT; + + if (U.glreslimit != 0) + GPU_free_images(); + GPU_paint_set_mipmap(1); } else if (me) { @@ -1328,7 +1333,10 @@ void set_texturepaint() /* toggle */ if(me->mtface==NULL) make_tfaces(me); - + + if (U.glreslimit != 0) + GPU_free_images(); + brush_check_exists(&G.scene->toolsettings->imapaint.brush); GPU_paint_set_mipmap(0); } From 21925c6f47bebba547e30ee81a199dd761912b60 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Feb 2009 04:43:12 +0000 Subject: [PATCH 187/252] uninitialized variable used in mesh_foreachScreenVert__mapFunc --- source/blender/src/drawobject.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 551ce874db8..ad9120e42e7 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -1196,15 +1196,18 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co { struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; EditVert *eve = EM_get_vert_for_index(index); - short s[2]; if (eve->h==0) { + short s[2]= {IS_CLIPPED, 0}; if (data->clipVerts) { view3d_project_short_clip(curarea, co, s, data->pmat, data->vmat); } else { view3d_project_short_noclip(curarea, co, s, data->pmat); } - + + if (s[0]==IS_CLIPPED) + return; + data->func(data->userData, eve, s[0], s[1], index); } } From 7d2582de09935c7050665a738eaca9097f3d0870 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Feb 2009 05:49:51 +0000 Subject: [PATCH 188/252] more uninitialized variables and auto-complete could copy a string over its self. --- source/blender/blenloader/intern/writefile.c | 2 +- source/blender/src/drawobject.c | 10 ++++++---- source/blender/src/interface.c | 9 +++++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index e06e7eb2d85..92d847d4782 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2032,7 +2032,7 @@ static void write_global(WriteData *wd) fg.subversion= BLENDER_SUBVERSION; fg.minversion= BLENDER_MINVERSION; fg.minsubversion= BLENDER_MINSUBVERSION; - + fg.pads= 0; /* prevent mem checkers from complaining */ writestruct(wd, GLOB, "FileGlobal", 1, &fg); } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index ad9120e42e7..43991194658 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -1096,14 +1096,15 @@ void lattice_foreachScreenVert(void (*func)(void *userData, BPoint *bp, int x, i float *co = dl?dl->verts:NULL; BPoint *bp = editLatt->def; float pmat[4][4], vmat[4][4]; - short s[2]; + short s[2] = {IS_CLIPPED, 0}; view3d_get_object_project_mat(curarea, G.obedit, pmat, vmat); for (i=0; ihide==0) { view3d_project_short_clip(curarea, dl?co:bp->vec, s, pmat, vmat); - func(userData, bp, s[0], s[1]); + if (s[0] != IS_CLIPPED) + func(userData, bp, s[0], s[1]); } } } @@ -1303,7 +1304,7 @@ void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, i void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData) { float pmat[4][4], vmat[4][4]; - short s[2]; + short s[2] = {IS_CLIPPED, 0}; Nurb *nu; int i; @@ -1339,7 +1340,8 @@ void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, if(bp->hide==0) { view3d_project_short_clip(curarea, bp->vec, s, pmat, vmat); - func(userData, nu, bp, NULL, -1, s[0], s[1]); + if (s[0] != IS_CLIPPED) + func(userData, nu, bp, NULL, -1, s[0], s[1]); } } } diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 7417218f253..40640c01998 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -6083,12 +6083,13 @@ void autocomplete_do_name(AutoComplete *autocpl, const char *name) } void autocomplete_end(AutoComplete *autocpl, char *autoname) -{ +{ if(autocpl->truncate[0]) BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen); - else - BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen); - + else { + if (autoname != autocpl->startname) /* dont copy a string over its self */ + BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen); + } MEM_freeN(autocpl->truncate); MEM_freeN(autocpl); } From 92d4ef0939c82e5654f899fe8e55e7a2cccbf6a0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Feb 2009 07:01:49 +0000 Subject: [PATCH 189/252] Accept negative indices's for ListValues scene.getObjectList()[-1] works like a python sequence. removed some STR_String creation that was only used to do comparisons, in a simple expressions benchmark this made logic use 4% less overall. --- source/gameengine/Expressions/InputParser.cpp | 19 ++++++++----------- source/gameengine/Expressions/ListValue.cpp | 10 +++++++--- .../gameengine/Expressions/PyObjectPlus.cpp | 12 +++++++----- source/gameengine/Ketsji/KX_TouchSensor.cpp | 2 +- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index 32a9de32e21..c3869d8f89b 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -272,32 +272,29 @@ void CParser::NextSym() || ((ch >= 'A') && (ch <= 'Z'))) { // reserved word? int start; - STR_String funstr; start = chcount; CharRep(); GrabString(start); - funstr = const_as_string; - funstr.Upper(); - if (funstr == STR_String("SUM")) { + if (!strcasecmp(const_as_string, "SUM")) { sym = sumsym; } - else if (funstr == STR_String("NOT")) { + else if (!strcasecmp(const_as_string, "NOT")) { sym = opsym; opkind = OPnot; } - else if (funstr == STR_String("AND")) { + else if (!strcasecmp(const_as_string, "AND")) { sym = opsym; opkind = OPand; } - else if (funstr == STR_String("OR")) { + else if (!strcasecmp(const_as_string, "OR")) { sym = opsym; opkind = OPor; } - else if (funstr == STR_String("IF")) { + else if (!strcasecmp(const_as_string, "IF")) sym = ifsym; - } else if (funstr == STR_String("WHOMADE")) { + else if (!strcasecmp(const_as_string, "WHOMADE")) sym = whocodedsym; - } else if (funstr == STR_String("FALSE")) { + else if (!strcasecmp(const_as_string, "FALSE")) { sym = constsym; constkind = booltype; boolvalue = false; - } else if (funstr == STR_String("TRUE")) { + } else if (!strcasecmp(const_as_string, "TRUE")) { sym = constsym; constkind = booltype; boolvalue = true; } else { sym = idsym; diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 9ffdbb1223c..b7236afdee4 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -34,7 +34,12 @@ Py_ssize_t listvalue_bufferlen(PyObject* list) PyObject* listvalue_buffer_item(PyObject* list,Py_ssize_t index) { - if (index >= 0 && index < ((CListValue*) list)->GetCount()) + int count = ((CListValue*) list)->GetCount(); + + if (index < 0) + index = count+index; + + if (index >= 0 && index < count) { PyObject* pyobj = ((CListValue*) list)->GetValue(index)->ConvertValueToPython(); if (pyobj) @@ -64,8 +69,7 @@ PyObject* listvalue_mapping_subscript(PyObject* list,PyObject* pyindex) } PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */ - STR_String index_str(PyString_AsString(pyindex_str)); - PyErr_Format(PyExc_KeyError, "'%s' not in list", index_str.Ptr()); + PyErr_Format(PyExc_KeyError, "'%s' not in list", PyString_AsString(pyindex_str)); Py_DECREF(pyindex_str); return NULL; } diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 8fd99c8d267..19f458b69a6 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -94,7 +94,7 @@ PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods ------------------------------*/ PyMethodDef PyObjectPlus::Methods[] = { - {"isA", (PyCFunction) sPy_isA, METH_VARARGS}, + {"isA", (PyCFunction) sPy_isA, METH_O}, {NULL, NULL} /* Sentinel */ }; @@ -688,19 +688,21 @@ bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent for (P = Ps[i=0]; P != NULL; P = Ps[i++]) { - if (STR_String(P->tp_name) == STR_String(mytypename) ) + if (strcmp(P->tp_name, mytypename)==0) return true; } return false; } -PyObject *PyObjectPlus::Py_isA(PyObject *args) // Python wrapper for isA +PyObject *PyObjectPlus::Py_isA(PyObject *value) // Python wrapper for isA { char *mytypename; - if (!PyArg_ParseTuple(args, "s", &mytypename)) + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "expected a string"); return NULL; - if(isA(mytypename)) + } + if(isA(PyString_AsString(value))) Py_RETURN_TRUE; else Py_RETURN_FALSE; diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 849972955af..0000d5793b6 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -199,7 +199,7 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll { if (client_info->m_auxilary_info) { - found = (m_touchedpropname == STR_String((char*)client_info->m_auxilary_info)); + found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info)); } } else { From c597863783e1001dca599e6dcbc28048f0ef4ce1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Feb 2009 10:34:51 +0000 Subject: [PATCH 190/252] "object" and "objectLastCreated" attribute for actuators, deprecates getObject/setObject() & getLastCreatedObject() also removed some warnings --- .../Converter/BL_ShapeActionActuator.h | 2 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 37 ++++++++++++++-- .../gameengine/Ketsji/KX_ParentActuator.cpp | 36 +++++++++++++++- source/gameengine/Ketsji/KX_ParentActuator.h | 1 + .../Ketsji/KX_SCA_AddObjectActuator.cpp | 42 ++++++++++++++++++- .../Ketsji/KX_SCA_AddObjectActuator.h | 15 +++---- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 38 ++++++++++++++++- source/gameengine/Ketsji/KX_TrackToActuator.h | 1 + source/gameengine/PyDoc/KX_CameraActuator.py | 3 +- source/gameengine/PyDoc/KX_ParentActuator.py | 3 ++ .../PyDoc/KX_SCA_AddObjectActuator.py | 4 ++ source/gameengine/PyDoc/KX_TrackToActuator.py | 2 + 12 files changed, 167 insertions(+), 17 deletions(-) diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index b521c0d98a6..47ceb9aa995 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -169,8 +169,8 @@ protected: short m_playtype; short m_priority; struct bAction *m_action; - STR_String m_propname; STR_String m_framepropname; + STR_String m_propname; vector m_blendshape; }; diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 98dd9ab3e68..4ac097eb575 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -398,9 +398,9 @@ PyParentObject KX_CameraActuator::Parents[] = { }; PyMethodDef KX_CameraActuator::Methods[] = { + // ---> deprecated (all) {"setObject",(PyCFunction) KX_CameraActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"getObject",(PyCFunction) KX_CameraActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, - // ---> deprecated {"setMin" ,(PyCFunction) KX_CameraActuator::sPySetMin, METH_VARARGS, (PY_METHODCHAR)SetMin_doc}, {"getMin" ,(PyCFunction) KX_CameraActuator::sPyGetMin, METH_NOARGS, (PY_METHODCHAR)GetMin_doc}, {"setMax" ,(PyCFunction) KX_CameraActuator::sPySetMax, METH_VARARGS, (PY_METHODCHAR)SetMax_doc}, @@ -421,14 +421,40 @@ PyAttributeDef KX_CameraActuator::Attributes[] = { }; PyObject* KX_CameraActuator::_getattr(const STR_String& attr) { - PyObject* object = _getattr_self(Attributes, this, attr); + PyObject* object; + + if (attr == "object") { + if (!m_ob) Py_RETURN_NONE; + else return m_ob->AddRef(); + } + + object = _getattr_self(Attributes, this, attr); if (object != NULL) return object; _getattr_up(SCA_IActuator); } int KX_CameraActuator::_setattr(const STR_String& attr, PyObject* value) { - int ret = _setattr_self(Attributes, this, attr, value); + int ret; + + if (attr == "object") { + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true)) + return 1; // ConvertPythonToGameObject sets the error + + if (m_ob != NULL) + m_ob->UnregisterActuator(this); + + m_ob = (SCA_IObject*)gameobj; + + if (m_ob) + m_ob->RegisterActuator(this); + + return 0; + } + + ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) return ret; return SCA_IActuator::_setattr(attr, value); @@ -442,6 +468,9 @@ const char KX_CameraActuator::GetObject_doc[] = PyObject* KX_CameraActuator::PyGetObject(PyObject* self, PyObject* args) { int ret_name_only = 1; + + ShowDeprecationWarning("getObject()", "the object property"); + if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) return NULL; @@ -462,6 +491,8 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* value) { KX_GameObject *gameobj; + ShowDeprecationWarning("setObject()", "the object property"); + if (!ConvertPythonToGameObject(value, &gameobj, true)) return NULL; // ConvertPythonToGameObject sets the error diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 89549ca6b57..c7ac52e571a 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -166,15 +166,44 @@ PyParentObject KX_ParentActuator::Parents[] = { }; PyMethodDef KX_ParentActuator::Methods[] = { + // ---> deprecated (all) {"setObject", (PyCFunction) KX_ParentActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"getObject", (PyCFunction) KX_ParentActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, {NULL,NULL} //Sentinel }; -PyObject* KX_ParentActuator::_getattr(const STR_String& attr) { +PyObject* KX_ParentActuator::_getattr(const STR_String& attr) { + + if (attr == "object") { + if (!m_ob) Py_RETURN_NONE; + else return m_ob->AddRef(); + } + _getattr_up(SCA_IActuator); } +int KX_ParentActuator::_setattr(const STR_String& attr, PyObject* value) { + + if (attr == "object") { + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true)) + return 1; // ConvertPythonToGameObject sets the error + + if (m_ob != NULL) + m_ob->UnregisterActuator(this); + + m_ob = (SCA_IObject*)gameobj; + + if (m_ob) + m_ob->RegisterActuator(this); + + return 0; + } + + return SCA_IActuator::_setattr(attr, value); +} + /* 1. setObject */ const char KX_ParentActuator::SetObject_doc[] = "setObject(object)\n" @@ -183,6 +212,8 @@ const char KX_ParentActuator::SetObject_doc[] = PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* value) { KX_GameObject *gameobj; + ShowDeprecationWarning("setObject()", "the object property"); + if (!ConvertPythonToGameObject(value, &gameobj, true)) return NULL; // ConvertPythonToGameObject sets the error @@ -206,6 +237,9 @@ const char KX_ParentActuator::GetObject_doc[] = PyObject* KX_ParentActuator::PyGetObject(PyObject* self, PyObject* args) { int ret_name_only = 1; + + ShowDeprecationWarning("getObject()", "the object property"); + if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) return NULL; diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index e2b30ba2d0f..e082b4fc209 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -77,6 +77,7 @@ class KX_ParentActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject* value); /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_ParentActuator,SetObject); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 5777f54b799..ab65c93529e 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -188,9 +188,7 @@ PyParentObject KX_SCA_AddObjectActuator::Parents[] = { NULL }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { - {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, (PY_METHODCHAR)SetTime_doc}, - {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_NOARGS, (PY_METHODCHAR)GetTime_doc}, {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_NOARGS, (PY_METHODCHAR)GetLinearVelocity_doc}, {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, (PY_METHODCHAR)SetLinearVelocity_doc}, @@ -199,15 +197,50 @@ PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { {"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"}, + // ---> deprecated + {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, + {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, + {NULL,NULL} //Sentinel }; PyObject* KX_SCA_AddObjectActuator::_getattr(const STR_String& attr) { + if (attr == "object") { + if (!m_OriginalObject) Py_RETURN_NONE; + else return m_OriginalObject->AddRef(); + } + else if (attr == "objectLastCreated") { + if (!m_OriginalObject) Py_RETURN_NONE; + else return m_lastCreatedObject->AddRef(); + } + _getattr_up(SCA_IActuator); } +int KX_SCA_AddObjectActuator::_setattr(const STR_String& attr, PyObject* value) { + + if (attr == "object") { + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true)) + return 1; // ConvertPythonToGameObject sets the error + + if (m_OriginalObject != NULL) + m_OriginalObject->UnregisterActuator(this); + + m_OriginalObject = (SCA_IObject*)gameobj; + + if (m_OriginalObject) + m_OriginalObject->RegisterActuator(this); + + return 0; + } + + return SCA_IActuator::_setattr(attr, value); +} + /* 1. setObject */ const char KX_SCA_AddObjectActuator::SetObject_doc[] = "setObject(object)\n" @@ -218,6 +251,8 @@ PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self, PyObject* value) { KX_GameObject *gameobj; + ShowDeprecationWarning("setObject()", "the object property"); + if (!ConvertPythonToGameObject(value, &gameobj, true)) return NULL; // ConvertPythonToGameObject sets the error @@ -277,6 +312,9 @@ const char KX_SCA_AddObjectActuator::GetObject_doc[] = PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self, PyObject* args) { int ret_name_only = 1; + + ShowDeprecationWarning("getObject()", "the object property"); + if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) return NULL; diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 278d4180284..035f44f16c9 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -60,13 +60,16 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator /// Linear velocity upon creation of the object. MT_Vector3 m_linear_velocity; + /// Apply the velocity locally + bool m_localLinvFlag; /// Angular velocity upon creation of the object. MT_Vector3 m_angular_velocity; - /// Apply the velocity locally - bool m_localLinvFlag; - bool m_localAngvFlag; + bool m_localAngvFlag; + + + SCA_IObject* m_lastCreatedObject; @@ -107,10 +110,8 @@ public: virtual bool Update(); - virtual PyObject* - _getattr( - const STR_String& attr - ); + virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject* value); SCA_IObject* GetLastCreatedObject( diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index acc4a6ab5d7..515349fbba8 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -456,12 +456,15 @@ PyParentObject KX_TrackToActuator::Parents[] = { PyMethodDef KX_TrackToActuator::Methods[] = { - {"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, - {"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, {"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc}, {"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_VARARGS, (PY_METHODCHAR)GetTime_doc}, {"setUse3D", (PyCFunction) KX_TrackToActuator::sPySetUse3D, METH_VARARGS, (PY_METHODCHAR)SetUse3D_doc}, {"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_VARARGS, (PY_METHODCHAR)GetUse3D_doc}, + + // ---> deprecated + {"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, + {"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, + {NULL,NULL} //Sentinel }; @@ -469,10 +472,36 @@ PyMethodDef KX_TrackToActuator::Methods[] = { PyObject* KX_TrackToActuator::_getattr(const STR_String& attr) { + if (attr == "object") { + if (!m_object) Py_RETURN_NONE; + else return m_object->AddRef(); + } + _getattr_up(SCA_IActuator); } +int KX_TrackToActuator::_setattr(const STR_String& attr, PyObject* value) { + int ret; + + if (attr == "object") { + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true)) + return 1; // ConvertPythonToGameObject sets the error + + if (m_object != NULL) + m_object->UnregisterActuator(this); + m_object = (SCA_IObject*)gameobj; + + if (m_object) + m_object->RegisterActuator(this); + + return 0; + } + + return SCA_IActuator::_setattr(attr, value); +} /* 1. setObject */ const char KX_TrackToActuator::SetObject_doc[] = @@ -483,6 +512,8 @@ PyObject* KX_TrackToActuator::PySetObject(PyObject* self, PyObject* value) { KX_GameObject *gameobj; + ShowDeprecationWarning("setObject()", "the object property"); + if (!ConvertPythonToGameObject(value, &gameobj, true)) return NULL; // ConvertPythonToGameObject sets the error @@ -506,6 +537,9 @@ const char KX_TrackToActuator::GetObject_doc[] = PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args) { int ret_name_only = 1; + + ShowDeprecationWarning("getObject()", "the object property"); + if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) return NULL; diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index 445132a6094..c9cae905240 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -73,6 +73,7 @@ class KX_TrackToActuator : public SCA_IActuator /* Python part */ virtual PyObject* _getattr(const STR_String& attr); + virtual int _setattr(const STR_String& attr, PyObject* value); /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_TrackToActuator,SetObject); diff --git a/source/gameengine/PyDoc/KX_CameraActuator.py b/source/gameengine/PyDoc/KX_CameraActuator.py index c4d5c9bcbfc..6ffc55a5854 100644 --- a/source/gameengine/PyDoc/KX_CameraActuator.py +++ b/source/gameengine/PyDoc/KX_CameraActuator.py @@ -14,7 +14,8 @@ class KX_CameraActuator(SCA_IActuator): @type height: float @ivar xy: axis this actuator is tracking, true=X, false=Y @type xy: boolean - + @ivar object: the object this actuator tracks. + @type object: KX_GameObject or None @author: snail """ def getObject(name_only = 1): diff --git a/source/gameengine/PyDoc/KX_ParentActuator.py b/source/gameengine/PyDoc/KX_ParentActuator.py index 6d6e0937257..7b5625ec82d 100644 --- a/source/gameengine/PyDoc/KX_ParentActuator.py +++ b/source/gameengine/PyDoc/KX_ParentActuator.py @@ -5,6 +5,9 @@ from SCA_IActuator import * class KX_ParentActuator(SCA_IActuator): """ The parent actuator can set or remove an objects parent object. + + @ivar object: the object this actuator sets the parent too. + @type object: KX_GameObject or None """ def setObject(object): """ diff --git a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py index c3b2e947ddb..56068fa641a 100644 --- a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py +++ b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py @@ -5,6 +5,10 @@ from SCA_IActuator import * class KX_SCA_AddObjectActuator(SCA_IActuator): """ Edit Object Actuator (in Add Object Mode) + @ivar object: the object this actuator adds. + @type object: KX_GameObject or None + @ivar objectLastCreated: the last added object from this actuator (read only). + @type objectLastCreated: KX_GameObject or None @warning: An Add Object actuator will be ignored if at game start, the linked object doesn't exist (or is empty) or the linked object is in an active layer. diff --git a/source/gameengine/PyDoc/KX_TrackToActuator.py b/source/gameengine/PyDoc/KX_TrackToActuator.py index 948302991b7..730ab21166b 100644 --- a/source/gameengine/PyDoc/KX_TrackToActuator.py +++ b/source/gameengine/PyDoc/KX_TrackToActuator.py @@ -13,6 +13,8 @@ class KX_TrackToActuator(SCA_IActuator): C{ERROR: GameObject I{OBName} no object in EditObjectActuator I{ActuatorName}} + @ivar object: the object this actuator tracks. + @type object: KX_GameObject or None """ def setObject(object): """ From cdec2b3d15ab0448e4df70496285ed95681e5972 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 Feb 2009 13:42:07 +0000 Subject: [PATCH 191/252] BGE Python API Use 'const char *' rather then the C++ 'STR_String' type for the attribute identifier of python attributes. Each attribute and method access from python was allocating and freeing the string. A simple test with getting an attribute a loop shows this speeds up attribute lookups a bit over 2x. --- .../Converter/BL_ActionActuator.cpp | 8 +- .../gameengine/Converter/BL_ActionActuator.h | 4 +- .../Converter/BL_BlenderDataConversion.cpp | 2 +- .../Converter/BL_ShapeActionActuator.cpp | 8 +- .../Converter/BL_ShapeActionActuator.h | 4 +- source/gameengine/Expressions/ListValue.cpp | 2 +- source/gameengine/Expressions/ListValue.h | 2 +- .../gameengine/Expressions/PyObjectPlus.cpp | 18 ++-- source/gameengine/Expressions/PyObjectPlus.h | 18 ++-- source/gameengine/Expressions/Value.cpp | 15 +-- source/gameengine/Expressions/Value.h | 6 +- .../GameLogic/SCA_2DFilterActuator.cpp | 2 +- .../GameLogic/SCA_2DFilterActuator.h | 2 +- .../GameLogic/SCA_ANDController.cpp | 2 +- .../gameengine/GameLogic/SCA_ANDController.h | 2 +- .../GameLogic/SCA_ActuatorSensor.cpp | 4 +- .../gameengine/GameLogic/SCA_ActuatorSensor.h | 4 +- .../gameengine/GameLogic/SCA_AlwaysSensor.cpp | 2 +- .../gameengine/GameLogic/SCA_AlwaysSensor.h | 2 +- .../gameengine/GameLogic/SCA_DelaySensor.cpp | 4 +- source/gameengine/GameLogic/SCA_DelaySensor.h | 4 +- .../GameLogic/SCA_ExpressionController.h | 2 +- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 4 +- source/gameengine/GameLogic/SCA_ILogicBrick.h | 4 +- source/gameengine/GameLogic/SCA_IObject.cpp | 2 +- source/gameengine/GameLogic/SCA_IObject.h | 2 +- source/gameengine/GameLogic/SCA_ISensor.cpp | 8 +- source/gameengine/GameLogic/SCA_ISensor.h | 4 +- .../GameLogic/SCA_JoystickSensor.cpp | 14 +-- .../gameengine/GameLogic/SCA_JoystickSensor.h | 4 +- .../GameLogic/SCA_KeyboardSensor.cpp | 4 +- .../gameengine/GameLogic/SCA_KeyboardSensor.h | 4 +- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 4 +- source/gameengine/GameLogic/SCA_MouseSensor.h | 4 +- .../GameLogic/SCA_NANDController.cpp | 2 +- .../gameengine/GameLogic/SCA_NANDController.h | 2 +- .../GameLogic/SCA_NORController.cpp | 2 +- .../gameengine/GameLogic/SCA_NORController.h | 2 +- .../gameengine/GameLogic/SCA_ORController.cpp | 2 +- .../gameengine/GameLogic/SCA_ORController.h | 2 +- .../GameLogic/SCA_PropertyActuator.cpp | 4 +- .../GameLogic/SCA_PropertyActuator.h | 4 +- .../GameLogic/SCA_PropertySensor.cpp | 4 +- .../gameengine/GameLogic/SCA_PropertySensor.h | 4 +- .../GameLogic/SCA_PythonController.cpp | 35 ++++--- .../GameLogic/SCA_PythonController.h | 4 +- .../GameLogic/SCA_RandomActuator.cpp | 8 +- .../gameengine/GameLogic/SCA_RandomActuator.h | 4 +- .../gameengine/GameLogic/SCA_RandomSensor.cpp | 8 +- .../gameengine/GameLogic/SCA_RandomSensor.h | 4 +- .../GameLogic/SCA_XNORController.cpp | 2 +- .../gameengine/GameLogic/SCA_XNORController.h | 2 +- .../GameLogic/SCA_XORController.cpp | 2 +- .../gameengine/GameLogic/SCA_XORController.h | 2 +- source/gameengine/Ketsji/BL_Shader.cpp | 2 +- source/gameengine/Ketsji/BL_Shader.h | 2 +- source/gameengine/Ketsji/BL_Texture.cpp | 2 +- .../KXNetwork/KX_NetworkMessageActuator.cpp | 2 +- .../KXNetwork/KX_NetworkMessageActuator.h | 2 +- .../KXNetwork/KX_NetworkMessageSensor.cpp | 2 +- .../KXNetwork/KX_NetworkMessageSensor.h | 2 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 4 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 4 +- source/gameengine/Ketsji/KX_CDActuator.cpp | 2 +- source/gameengine/Ketsji/KX_CDActuator.h | 2 +- source/gameengine/Ketsji/KX_Camera.cpp | 40 ++++---- source/gameengine/Ketsji/KX_Camera.h | 4 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 8 +- source/gameengine/Ketsji/KX_CameraActuator.h | 4 +- .../Ketsji/KX_ConstraintActuator.cpp | 2 +- .../gameengine/Ketsji/KX_ConstraintActuator.h | 2 +- .../Ketsji/KX_ConstraintWrapper.cpp | 14 ++- .../gameengine/Ketsji/KX_ConstraintWrapper.h | 4 +- source/gameengine/Ketsji/KX_GameActuator.cpp | 2 +- source/gameengine/Ketsji/KX_GameActuator.h | 2 +- source/gameengine/Ketsji/KX_GameObject.cpp | 38 ++++---- source/gameengine/Ketsji/KX_GameObject.h | 14 +-- source/gameengine/Ketsji/KX_IpoActuator.cpp | 2 +- source/gameengine/Ketsji/KX_IpoActuator.h | 2 +- source/gameengine/Ketsji/KX_Light.cpp | 60 ++++++------ source/gameengine/Ketsji/KX_Light.h | 4 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 4 +- source/gameengine/Ketsji/KX_MeshProxy.h | 2 +- .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 2 +- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 2 +- source/gameengine/Ketsji/KX_NearSensor.cpp | 2 +- source/gameengine/Ketsji/KX_NearSensor.h | 2 +- .../gameengine/Ketsji/KX_ObjectActuator.cpp | 2 +- source/gameengine/Ketsji/KX_ObjectActuator.h | 2 +- .../gameengine/Ketsji/KX_ParentActuator.cpp | 8 +- source/gameengine/Ketsji/KX_ParentActuator.h | 4 +- .../Ketsji/KX_PhysicsObjectWrapper.cpp | 10 +- .../Ketsji/KX_PhysicsObjectWrapper.h | 4 +- source/gameengine/Ketsji/KX_PolyProxy.cpp | 23 +++-- source/gameengine/Ketsji/KX_PolyProxy.h | 2 +- .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 4 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 4 +- source/gameengine/Ketsji/KX_RadarSensor.cpp | 2 +- source/gameengine/Ketsji/KX_RadarSensor.h | 2 +- source/gameengine/Ketsji/KX_RaySensor.cpp | 2 +- source/gameengine/Ketsji/KX_RaySensor.h | 2 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 8 +- .../Ketsji/KX_SCA_AddObjectActuator.h | 4 +- .../Ketsji/KX_SCA_DynamicActuator.cpp | 2 +- .../Ketsji/KX_SCA_DynamicActuator.h | 5 +- .../Ketsji/KX_SCA_EndObjectActuator.cpp | 2 +- .../Ketsji/KX_SCA_EndObjectActuator.h | 5 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 2 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.h | 5 +- source/gameengine/Ketsji/KX_Scene.cpp | 23 +++-- source/gameengine/Ketsji/KX_Scene.h | 6 +- source/gameengine/Ketsji/KX_SceneActuator.cpp | 2 +- source/gameengine/Ketsji/KX_SceneActuator.h | 2 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 2 +- source/gameengine/Ketsji/KX_SoundActuator.h | 2 +- source/gameengine/Ketsji/KX_StateActuator.cpp | 5 +- source/gameengine/Ketsji/KX_StateActuator.h | 2 +- source/gameengine/Ketsji/KX_TouchSensor.cpp | 2 +- source/gameengine/Ketsji/KX_TouchSensor.h | 2 +- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 8 +- source/gameengine/Ketsji/KX_TrackToActuator.h | 4 +- .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 4 +- source/gameengine/Ketsji/KX_VehicleWrapper.h | 4 +- source/gameengine/Ketsji/KX_VertexProxy.cpp | 96 ++++++++++--------- source/gameengine/Ketsji/KX_VertexProxy.h | 4 +- .../Ketsji/KX_VisibilityActuator.cpp | 5 +- .../gameengine/Ketsji/KX_VisibilityActuator.h | 2 +- 127 files changed, 392 insertions(+), 403 deletions(-) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 65d6892fa6d..22c6c95b158 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -1035,8 +1035,8 @@ PyAttributeDef BL_ActionActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* BL_ActionActuator::_getattr(const STR_String& attr) { - if (attr == "action") +PyObject* BL_ActionActuator::_getattr(const char *attr) { + if (!strcmp(attr, "action")) return PyString_FromString(m_action->id.name+2); PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) @@ -1044,8 +1044,8 @@ PyObject* BL_ActionActuator::_getattr(const STR_String& attr) { _getattr_up(SCA_IActuator); } -int BL_ActionActuator::_setattr(const STR_String& attr, PyObject* value) { - if (attr == "action") +int BL_ActionActuator::_setattr(const char *attr, PyObject* value) { + if (!strcmp(attr, "action")) { if (!PyString_Check(value)) { diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 6e291106553..6161048afb8 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -110,8 +110,8 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,setChannel); - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject* value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); /* attribute check */ static int CheckFrame(void *self, const PyAttributeDef*) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 9c699b67b28..2fa3e192179 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -361,7 +361,7 @@ BL_Material* ConvertMaterial( facetex = true; if(validface && mat->mtex[0]) { MTex *tmp = mat->mtex[0]; - if(!tmp->tex || tmp->tex && !tmp->tex->ima ) + if(!tmp->tex || (tmp->tex && !tmp->tex->ima)) facetex = true; } numchan = numchan>MAXTEX?MAXTEX:numchan; diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index df0a8c4f25e..7cba6b01e1a 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -484,8 +484,8 @@ PyAttributeDef BL_ShapeActionActuator::Attributes[] = { }; -PyObject* BL_ShapeActionActuator::_getattr(const STR_String& attr) { - if (attr == "action") +PyObject* BL_ShapeActionActuator::_getattr(const char *attr) { + if (!strcmp(attr, "action")) return PyString_FromString(m_action->id.name+2); PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) @@ -493,8 +493,8 @@ PyObject* BL_ShapeActionActuator::_getattr(const STR_String& attr) { _getattr_up(SCA_IActuator); } -int BL_ShapeActionActuator::_setattr(const STR_String& attr, PyObject* value) { - if (attr == "action") +int BL_ShapeActionActuator::_setattr(const char *attr, PyObject* value) { + if (!strcmp(attr, "action")) { if (!PyString_Check(value)) { diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index 47ceb9aa995..7f2431bcfa5 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -103,8 +103,8 @@ public: KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType); - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject* value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); static int CheckBlendTime(void *self, const PyAttributeDef*) { diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index b7236afdee4..3cf22bdc9bd 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -234,7 +234,7 @@ PyMethodDef CListValue::Methods[] = { -PyObject* CListValue::_getattr(const STR_String& attr) { +PyObject* CListValue::_getattr(const char *attr) { _getattr_up(CValue); } diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h index 431f8f558a9..8c0bd767938 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/ListValue.h @@ -59,7 +59,7 @@ public: bool CheckEqual(CValue* first,CValue* second); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(CListValue,append); KX_PYMETHOD(CListValue,reverse); diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 19f458b69a6..16184b7c5f2 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -106,24 +106,24 @@ PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL}; /*------------------------------ * PyObjectPlus attributes -- attributes ------------------------------*/ -PyObject *PyObjectPlus::_getattr(const STR_String& attr) +PyObject *PyObjectPlus::_getattr(const char *attr) { - if (attr == "__doc__" && GetType()->tp_doc) + if (!strcmp(attr, "__doc__") && GetType()->tp_doc) return PyString_FromString(GetType()->tp_doc); //if (streq(attr, "type")) // return Py_BuildValue("s", (*(GetParents()))->tp_name); - return Py_FindMethod(Methods, this, const_cast(attr.ReadPtr())); + return Py_FindMethod(Methods, this, attr); } -int PyObjectPlus::_delattr(const STR_String& attr) +int PyObjectPlus::_delattr(const char *attr) { PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); return 1; } -int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) +int PyObjectPlus::_setattr(const char *attr, PyObject *value) { //return PyObject::_setattr(attr,value); //cerr << "Unknown attribute" << endl; @@ -131,12 +131,12 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) return 1; } -PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr) +PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr) { const PyAttributeDef *attrdef; for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) { - if (attr == attrdef->m_name) + if (!strcmp(attr, attrdef->m_name)) { if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) { @@ -238,7 +238,7 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel return NULL; } -int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr, PyObject *value) +int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value) { const PyAttributeDef *attrdef; void *undoBuffer = NULL; @@ -247,7 +247,7 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) { - if (attr == attrdef->m_name) + if (!strcmp(attr, attrdef->m_name)) { if (attrdef->m_access == KX_PYATTRIBUTE_RO || attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index e0e2213d984..5092c8106ec 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -97,7 +97,7 @@ static inline void Py_Fatal(const char *M) { // to be properly passed up the hierarchy. #define _getattr_up(Parent) \ PyObject *rvalue = NULL; \ - if (attr=="__methods__") { \ + if (!strcmp(attr, "__methods__")) { \ PyObject *_attr_string = NULL; \ PyMethodDef *meth = Methods; \ rvalue = Parent::_getattr(attr); \ @@ -113,7 +113,7 @@ static inline void Py_Fatal(const char *M) { } \ } \ } else { \ - rvalue = Py_FindMethod(Methods, this, const_cast(attr.ReadPtr())); \ + rvalue = Py_FindMethod(Methods, this, attr); \ if (rvalue == NULL) { \ PyErr_Clear(); \ rvalue = Parent::_getattr(attr); \ @@ -348,23 +348,23 @@ public: // Py_DECREF(this); // }; // decref method - virtual PyObject *_getattr(const STR_String& attr); // _getattr method + virtual PyObject *_getattr(const char *attr); // _getattr method static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type. { - return ((PyObjectPlus*) PyObj)->_getattr(STR_String(attr)); + return ((PyObjectPlus*) PyObj)->_getattr(attr); } - static PyObject *_getattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr); - static int _setattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr, PyObject *value); + static PyObject *_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr); + static int _setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value); - virtual int _delattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); // _setattr method + virtual int _delattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); // _setattr method static int __setattr(PyObject *PyObj, // This should be the entry in Type. char *attr, PyObject *value) { if (!value) return ((PyObjectPlus*) PyObj)->_delattr(attr); - return ((PyObjectPlus*) PyObj)->_setattr(STR_String(attr), value); + return ((PyObjectPlus*) PyObj)->_setattr(attr, value); } virtual PyObject *_repr(void); // _repr method diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index f2b5569c76e..f30dd1a71ed 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -674,9 +674,9 @@ static PyMethodDef CValueMethods[] = }; -PyObject* CValue::_getattr(const STR_String& attr) +PyObject* CValue::_getattr(const char *attr) { - CValue* resultattr = FindIdentifier(attr); + CValue* resultattr = FindIdentifier(STR_String(attr)); STR_String text; if (resultattr) { @@ -761,26 +761,27 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) } -int CValue::_delattr(const STR_String& attr) +int CValue::_delattr(const char *attr) { - if (!RemoveProperty(attr)) /* sets error */ + if (!RemoveProperty(STR_String(attr))) /* sets error */ return 1; return 0; } -int CValue::_setattr(const STR_String& attr,PyObject* pyobj) +int CValue::_setattr(const char *attr,PyObject* pyobj) { CValue* vallie = ConvertPythonToValue(pyobj); if (vallie) { - CValue* oldprop = GetProperty(attr); + STR_String attr_str = attr; + CValue* oldprop = GetProperty(attr_str); if (oldprop) { oldprop->SetValue(vallie); } else { - SetProperty(attr,vallie); + SetProperty(attr_str, vallie); } vallie->Release(); } else diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 56a4991af27..854334b892b 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -223,7 +223,7 @@ public: - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); void SpecialRelease() { @@ -250,8 +250,8 @@ public: virtual CValue* ConvertPythonToValue(PyObject* pyobj); - virtual int _delattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr,PyObject* value); + virtual int _delattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); virtual PyObject* ConvertKeysToPython( void ); diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index a70830193db..6fcb1be654c 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -114,6 +114,6 @@ PyMethodDef SCA_2DFilterActuator::Methods[] = { }; -PyObject* SCA_2DFilterActuator::_getattr(const STR_String& attr) { +PyObject* SCA_2DFilterActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h index 7ec07cf5b19..9da0500afff 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h @@ -38,7 +38,7 @@ public: virtual bool Update(); virtual CValue* GetReplica(); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; #endif diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index cfc2d25e0ae..98a3c2e96cd 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -137,7 +137,7 @@ PyMethodDef SCA_ANDController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_ANDController::_getattr(const STR_String& attr) { +PyObject* SCA_ANDController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h index 376f4a9a876..eba7e1b545a 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.h +++ b/source/gameengine/GameLogic/SCA_ANDController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index fae8d2ba5a7..dcdd7df50d4 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -161,7 +161,7 @@ PyAttributeDef SCA_ActuatorSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_ActuatorSensor::_getattr(const STR_String& attr) { +PyObject* SCA_ActuatorSensor::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) return object; @@ -180,7 +180,7 @@ int SCA_ActuatorSensor::CheckActuator(void *self, const PyAttributeDef*) return 1; } -int SCA_ActuatorSensor::_setattr(const STR_String& attr, PyObject *value) { +int SCA_ActuatorSensor::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) return ret; diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index 3d64247461c..75ee08f42d6 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -61,8 +61,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 3. setProperty */ KX_PYMETHOD_DOC(SCA_ActuatorSensor,SetActuator); diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index f9fbf2387c4..76aa328aa48 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -135,7 +135,7 @@ PyMethodDef SCA_AlwaysSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_AlwaysSensor::_getattr(const STR_String& attr) { +PyObject* SCA_AlwaysSensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); } diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h index 8bf2a8aa98e..ebe6ba80208 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h @@ -52,7 +52,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index 4c97ca98d72..802edc4b6cf 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -178,14 +178,14 @@ PyAttributeDef SCA_DelaySensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_DelaySensor::_getattr(const STR_String& attr) { +PyObject* SCA_DelaySensor::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) return object; _getattr_up(SCA_ISensor); } -int SCA_DelaySensor::_setattr(const STR_String& attr, PyObject *value) { +int SCA_DelaySensor::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) return ret; diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h index ff3afe16542..491eee61da8 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.h +++ b/source/gameengine/GameLogic/SCA_DelaySensor.h @@ -60,8 +60,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* setProperty */ KX_PYMETHOD_DOC(SCA_DelaySensor,SetDelay); diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h index f1db45a19e0..20e1eb77771 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.h +++ b/source/gameengine/GameLogic/SCA_ExpressionController.h @@ -53,7 +53,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ -// virtual PyObject* _getattr(const STR_String& attr); +// virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 8286c0829a7..70938db7c3d 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -278,7 +278,7 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) } PyObject* -SCA_ILogicBrick::_getattr(const STR_String& attr) +SCA_ILogicBrick::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) @@ -286,7 +286,7 @@ SCA_ILogicBrick::_getattr(const STR_String& attr) _getattr_up(CValue); } -int SCA_ILogicBrick::_setattr(const STR_String& attr, PyObject *value) +int SCA_ILogicBrick::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index 772bd65d577..cde1353275b 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -78,8 +78,8 @@ public: virtual bool LessComparedTo(SCA_ILogicBrick* other); - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); static class SCA_LogicManager* m_sCurrentLogicManager; diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index b0f8decee26..3afc48b719c 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -409,7 +409,7 @@ PyMethodDef SCA_IObject::Methods[] = { -PyObject* SCA_IObject::_getattr(const STR_String& attr) { +PyObject* SCA_IObject::_getattr(const char *attr) { _getattr_up(CValue); } diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 38a7ed29dca..d47353b1ac0 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -145,7 +145,7 @@ public: // const class MT_Point3& ConvertPythonPylist(PyObject* pylist); // here come the python forwarded methods - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); virtual int GetGameObjectType() {return -1;} diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 68a3a93eab0..73475b018fc 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -461,19 +461,19 @@ PyAttributeDef SCA_ISensor::Attributes[] = { }; PyObject* -SCA_ISensor::_getattr(const STR_String& attr) +SCA_ISensor::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) return object; - if (attr == "triggered") + if (!strcmp(attr, "triggered")) { int retval = 0; if (SCA_PythonController::m_sCurrentController) retval = SCA_PythonController::m_sCurrentController->IsTriggered(this); return PyInt_FromLong(retval); } - if (attr == "positive") + if (!strcmp(attr, "positive")) { int retval = IsPositiveTrigger(); return PyInt_FromLong(retval); @@ -481,7 +481,7 @@ SCA_ISensor::_getattr(const STR_String& attr) _getattr_up(SCA_ILogicBrick); } -int SCA_ISensor::_setattr(const STR_String& attr, PyObject *value) +int SCA_ISensor::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 1b57c4621e4..5ae7ced2a2a 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -141,8 +141,8 @@ public: /* Python functions: */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); //Deprecated functions -----> KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive); diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 694bca9bac5..17a8710ed48 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -343,24 +343,24 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { +PyObject* SCA_JoystickSensor::_getattr(const char *attr) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - if (attr == "axisPosition") { + if (!strcmp(attr, "axisPosition")) { if(joy) return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); else return Py_BuildValue("[iiii]", 0, 0, 0, 0); } - if (attr == "numAxis") { + if (!strcmp(attr, "numAxis")) { return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); } - if (attr == "numButtons") { + if (!strcmp(attr, "numButtons")) { return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); } - if (attr == "numHats") { + if (!strcmp(attr, "numHats")) { return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); } - if (attr == "connected") { + if (!strcmp(attr, "connected")) { return PyBool_FromLong( joy ? joy->Connected() : 0 ); } PyObject* object = _getattr_self(Attributes, this, attr); @@ -369,7 +369,7 @@ PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { _getattr_up(SCA_ISensor); } -int SCA_JoystickSensor::_setattr(const STR_String& attr, PyObject *value) +int SCA_JoystickSensor::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index fa11f1cc3d0..49d220c056d 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -121,8 +121,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* Joystick Index */ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex); diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index 981d165287b..0edc41bef7b 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -831,7 +831,7 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = { }; PyObject* -SCA_KeyboardSensor::_getattr(const STR_String& attr) +SCA_KeyboardSensor::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) @@ -839,7 +839,7 @@ SCA_KeyboardSensor::_getattr(const STR_String& attr) _getattr_up(SCA_ISensor); } -int SCA_KeyboardSensor::_setattr(const STR_String& attr, PyObject *value) +int SCA_KeyboardSensor::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index 4efbe9366cc..bc2f86327a5 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -126,8 +126,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); //Deprecated functions -----> /** 1. GetKey : check which key this sensor looks at */ diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 09b46e6443e..a96d3758d3c 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -341,7 +341,7 @@ PyAttributeDef SCA_MouseSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) +PyObject* SCA_MouseSensor::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) @@ -349,7 +349,7 @@ PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) _getattr_up(SCA_ISensor); } -int SCA_MouseSensor::_setattr(const STR_String& attr, PyObject *value) +int SCA_MouseSensor::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 82af2ce9c04..30b43fe53cc 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -109,8 +109,8 @@ class SCA_MouseSensor : public SCA_ISensor /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); //Deprecated functions -----> /* read x-coordinate */ diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index 5b869ee8298..0efa8da153a 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -137,7 +137,7 @@ PyMethodDef SCA_NANDController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_NANDController::_getattr(const STR_String& attr) { +PyObject* SCA_NANDController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h index 1193ff64f07..d88504cfc0d 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.h +++ b/source/gameengine/GameLogic/SCA_NANDController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index 2866dec0b74..fa24be9ebce 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -137,7 +137,7 @@ PyMethodDef SCA_NORController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_NORController::_getattr(const STR_String& attr) { +PyObject* SCA_NORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h index aab59e3d46c..45b639f3f3f 100644 --- a/source/gameengine/GameLogic/SCA_NORController.h +++ b/source/gameengine/GameLogic/SCA_NORController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index 2d4eb31f241..42a29e1959b 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -129,7 +129,7 @@ PyMethodDef SCA_ORController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_ORController::_getattr(const STR_String& attr) { +PyObject* SCA_ORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h index beb69aa2af9..9a6e9e75022 100644 --- a/source/gameengine/GameLogic/SCA_ORController.h +++ b/source/gameengine/GameLogic/SCA_ORController.h @@ -49,7 +49,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; #endif //__KX_ORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index 566d3b63487..644b82a92bf 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -260,14 +260,14 @@ PyAttributeDef SCA_PropertyActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_PropertyActuator::_getattr(const STR_String& attr) { +PyObject* SCA_PropertyActuator::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) return object; _getattr_up(SCA_IActuator); } -int SCA_PropertyActuator::_setattr(const STR_String& attr, PyObject *value) { +int SCA_PropertyActuator::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) return ret; diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index cdfeee4c67d..444d9285796 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -85,8 +85,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); // python wrapped methods KX_PYMETHOD_DOC(SCA_PropertyActuator,SetProperty); diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index a6f7a9cd82b..10d49769162 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -352,14 +352,14 @@ PyAttributeDef SCA_PropertySensor::Attributes[] = { }; -PyObject* SCA_PropertySensor::_getattr(const STR_String& attr) { +PyObject* SCA_PropertySensor::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) return object; _getattr_up(SCA_ISensor); /* implicit return! */ } -int SCA_PropertySensor::_setattr(const STR_String& attr, PyObject *value) { +int SCA_PropertySensor::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) return ret; diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index e625e84a36f..933de49de18 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -85,8 +85,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 1. getType */ KX_PYMETHOD_DOC(SCA_PropertySensor,GetType); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index e879481a444..2fff21f22fb 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -233,8 +233,8 @@ PyMethodDef SCA_PythonController::Methods[] = { {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc}, {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc}, {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, (PY_METHODCHAR)SCA_PythonController::GetSensor_doc}, - {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O}, //Deprecated functions ------> + {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O}, {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS}, {"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_NOARGS}, //<----- Deprecated @@ -329,25 +329,35 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) -PyObject* SCA_PythonController::_getattr(const STR_String& attr) +PyObject* SCA_PythonController::_getattr(const char *attr) { - if (attr == "script") { - return PyString_FromString(m_scriptText); - } - if (attr == "state") { + if (!strcmp(attr,"state")) { return PyInt_FromLong(m_statemask); } + if (!strcmp(attr,"script")) { + return PyString_FromString(m_scriptText); + } _getattr_up(SCA_IController); } -int SCA_PythonController::_setattr(const STR_String& attr, PyObject *value) +int SCA_PythonController::_setattr(const char *attr, PyObject *value) { - if (attr == "script") { - PyErr_SetString(PyExc_AttributeError, "script is read only, use setScript() to update the script"); + if (!strcmp(attr,"state")) { + PyErr_SetString(PyExc_AttributeError, "state is read only"); return 1; } - if (attr == "state") { - PyErr_SetString(PyExc_AttributeError, "state is read only"); + if (!strcmp(attr,"script")) { + char *scriptArg = PyString_AsString(value); + + if (scriptArg==NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string (script name)"); + return -1; + } + + /* set scripttext sets m_bModified to true, + so next time the script is needed, a reparse into byte code is done */ + this->SetScriptText(scriptArg); + return 1; } return SCA_IController::_setattr(attr, value); @@ -448,6 +458,9 @@ PyObject* SCA_PythonController::PyGetScript(PyObject* self) PyObject* SCA_PythonController::PySetScript(PyObject* self, PyObject* value) { char *scriptArg = PyString_AsString(value); + + ShowDeprecationWarning("setScript()", "the script property"); + if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "expected a string (script name)"); return NULL; diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 1918cc488d8..00c30d7f3d5 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -76,8 +76,8 @@ class SCA_PythonController : public SCA_IController static const char* sPyAddActiveActuator__doc__; static PyObject* sPyAddActiveActuator(PyObject* self, PyObject* args); - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetSensors); KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetActuators); diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 840b95d559a..7aa25d22b3f 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -369,22 +369,22 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_RandomActuator::_getattr(const STR_String& attr) { +PyObject* SCA_RandomActuator::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) return object; - if (attr == "seed") { + if (!strcmp(attr, "seed")) { return PyInt_FromLong(m_base->GetSeed()); } _getattr_up(SCA_IActuator); } -int SCA_RandomActuator::_setattr(const STR_String& attr, PyObject *value) +int SCA_RandomActuator::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) return ret; - if (attr == "seed") { + if (!strcmp(attr, "seed")) { if (PyInt_Check(value)) { int ival = PyInt_AsLong(value); m_base->SetSeed(ival); diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index de8faaf9c72..0d404fa8a9f 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -96,8 +96,8 @@ class SCA_RandomActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 1. setSeed */ KX_PYMETHOD_DOC(SCA_RandomActuator,SetSeed); diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 8fae0bbeaba..5a1bd10e044 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -165,22 +165,22 @@ PyAttributeDef SCA_RandomSensor::Attributes[] = { {NULL} //Sentinel }; -PyObject* SCA_RandomSensor::_getattr(const STR_String& attr) { +PyObject* SCA_RandomSensor::_getattr(const char *attr) { PyObject* object = _getattr_self(Attributes, this, attr); if (object != NULL) return object; - if (attr == "seed") { + if (!strcmp(attr,"seed")) { return PyInt_FromLong(m_basegenerator->GetSeed()); } _getattr_up(SCA_ISensor); } -int SCA_RandomSensor::_setattr(const STR_String& attr, PyObject *value) +int SCA_RandomSensor::_setattr(const char *attr, PyObject *value) { int ret = _setattr_self(Attributes, this, attr, value); if (ret >= 0) return ret; - if (attr == "seed") { + if (!strcmp(attr,"seed")) { if (PyInt_Check(value)) { int ival = PyInt_AsLong(value); m_basegenerator->SetSeed(ival); diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index 009efc32aac..d808db07536 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -60,8 +60,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 1. setSeed */ KX_PYMETHOD_DOC(SCA_RandomSensor,SetSeed); diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index 3ef7c07fe0a..b019aedc93d 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -141,7 +141,7 @@ PyMethodDef SCA_XNORController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_XNORController::_getattr(const STR_String& attr) { +PyObject* SCA_XNORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h index 4b1eaee95d8..a431a72c177 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.h +++ b/source/gameengine/GameLogic/SCA_XNORController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index 6499c62f5f2..11ffa19b8f1 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -141,7 +141,7 @@ PyMethodDef SCA_XORController::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* SCA_XORController::_getattr(const STR_String& attr) { +PyObject* SCA_XORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h index f50cd33c125..2fbc7866ecf 100644 --- a/source/gameengine/GameLogic/SCA_XORController.h +++ b/source/gameengine/GameLogic/SCA_XORController.h @@ -48,7 +48,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 80892764089..0c57b2d03a5 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -729,7 +729,7 @@ void BL_Shader::SetUniform(int uniform, const int* val, int len) } -PyObject* BL_Shader::_getattr(const STR_String& attr) +PyObject* BL_Shader::_getattr(const char *attr) { _getattr_up(PyObjectPlus); } diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 18ca8f8b4f8..52cbd0cda51 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -202,7 +202,7 @@ public: void SetUniform(int uniform, const int val); // Python interface - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); // ----------------------------------- KX_PYMETHOD_DOC( BL_Shader, setSource ); diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index f0ef84032f7..5d40ba7d75c 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -609,7 +609,7 @@ int BL_Texture::GetPow2(int n) void BL_Texture::SplitEnvMap(EnvMap *map) { - if (!map || !map->ima || map->ima && !map->ima->ok) return; + if (!map || !map->ima || (map->ima && !map->ima->ok)) return; ImBuf *ibuf= BKE_image_get_ibuf(map->ima, NULL); if (ibuf) my_envmap_split_ima(map, ibuf); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp index 85921ae75ca..a332295ad72 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp @@ -143,7 +143,7 @@ PyMethodDef KX_NetworkMessageActuator::Methods[] = { {NULL,NULL} // Sentinel }; -PyObject* KX_NetworkMessageActuator::_getattr(const STR_String& attr) { +PyObject* KX_NetworkMessageActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h index 653107699c7..96b55ef839b 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h @@ -61,7 +61,7 @@ public: /* Python interface ------------------------------------------- */ /* ------------------------------------------------------------ */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(KX_NetworkMessageActuator, SetToPropName); KX_PYMETHOD(KX_NetworkMessageActuator, SetSubject); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 8956df9c96b..cb9956d4616 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -213,7 +213,7 @@ PyMethodDef KX_NetworkMessageSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_NetworkMessageSensor::_getattr(const STR_String& attr) { +PyObject* KX_NetworkMessageSensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); // implicit return! } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 8cdfd6cdb5a..26adbc9945a 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -72,7 +72,7 @@ public: /* Python interface -------------------------------------------- */ /* ------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index f92200780d5..83148ea9a2b 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -772,12 +772,12 @@ PyParentObject KX_BlenderMaterial::Parents[] = { }; -PyObject* KX_BlenderMaterial::_getattr(const STR_String& attr) +PyObject* KX_BlenderMaterial::_getattr(const char *attr) { _getattr_up(PyObjectPlus); } -int KX_BlenderMaterial::_setattr(const STR_String& attr, PyObject *pyvalue) +int KX_BlenderMaterial::_setattr(const char *attr, PyObject *pyvalue) { return PyObjectPlus::_setattr(attr, pyvalue); } diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 6e5db1b56c1..2cf623dbd85 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -82,8 +82,8 @@ public: ); // -------------------------------- - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *pyvalue); KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader ); KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex ); diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp index a5d7f6d799a..44d073193b1 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.cpp +++ b/source/gameengine/Ketsji/KX_CDActuator.cpp @@ -199,7 +199,7 @@ PyMethodDef KX_CDActuator::Methods[] = { -PyObject* KX_CDActuator::_getattr(const STR_String& attr) +PyObject* KX_CDActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h index f46dd99b6dc..393c49083f9 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.h +++ b/source/gameengine/Ketsji/KX_CDActuator.h @@ -81,7 +81,7 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(KX_CDActuator,StartCD); KX_PYMETHOD(KX_CDActuator,PauseCD); diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index fb91c793765..809bcdba8c9 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -538,48 +538,48 @@ PyParentObject KX_Camera::Parents[] = { NULL }; -PyObject* KX_Camera::_getattr(const STR_String& attr) +PyObject* KX_Camera::_getattr(const char *attr) { - if (attr == "INSIDE") + if (!strcmp(attr, "INSIDE")) return PyInt_FromLong(INSIDE); /* new ref */ - if (attr == "OUTSIDE") + if (!strcmp(attr, "OUTSIDE")) return PyInt_FromLong(OUTSIDE); /* new ref */ - if (attr == "INTERSECT") + if (!strcmp(attr, "INTERSECT")) return PyInt_FromLong(INTERSECT); /* new ref */ - if (attr == "lens") + if (!strcmp(attr, "lens")) return PyFloat_FromDouble(GetLens()); /* new ref */ - if (attr == "near") + if (!strcmp(attr, "near")) return PyFloat_FromDouble(GetCameraNear()); /* new ref */ - if (attr == "far") + if (!strcmp(attr, "far")) return PyFloat_FromDouble(GetCameraFar()); /* new ref */ - if (attr == "frustum_culling") + if (!strcmp(attr, "frustum_culling")) return PyInt_FromLong(m_frustum_culling); /* new ref */ - if (attr == "perspective") + if (!strcmp(attr, "perspective")) return PyInt_FromLong(m_camdata.m_perspective); /* new ref */ - if (attr == "projection_matrix") + if (!strcmp(attr, "projection_matrix")) return PyObjectFrom(GetProjectionMatrix()); /* new ref */ - if (attr == "modelview_matrix") + if (!strcmp(attr, "modelview_matrix")) return PyObjectFrom(GetModelviewMatrix()); /* new ref */ - if (attr == "camera_to_world") + if (!strcmp(attr, "camera_to_world")) return PyObjectFrom(GetCameraToWorld()); /* new ref */ - if (attr == "world_to_camera") + if (!strcmp(attr, "world_to_camera")) return PyObjectFrom(GetWorldToCamera()); /* new ref */ _getattr_up(KX_GameObject); } -int KX_Camera::_setattr(const STR_String &attr, PyObject *pyvalue) +int KX_Camera::_setattr(const char *attr, PyObject *pyvalue) { if (PyInt_Check(pyvalue)) { - if (attr == "frustum_culling") + if (!strcmp(attr, "frustum_culling")) { m_frustum_culling = PyInt_AsLong(pyvalue); return 0; } - if (attr == "perspective") + if (!strcmp(attr, "perspective")) { m_camdata.m_perspective = PyInt_AsLong(pyvalue); return 0; @@ -588,19 +588,19 @@ int KX_Camera::_setattr(const STR_String &attr, PyObject *pyvalue) if (PyFloat_Check(pyvalue)) { - if (attr == "lens") + if (!strcmp(attr, "lens")) { m_camdata.m_lens = PyFloat_AsDouble(pyvalue); m_set_projection_matrix = false; return 0; } - if (attr == "near") + if (!strcmp(attr, "near")) { m_camdata.m_clipstart = PyFloat_AsDouble(pyvalue); m_set_projection_matrix = false; return 0; } - if (attr == "far") + if (!strcmp(attr, "far")) { m_camdata.m_clipend = PyFloat_AsDouble(pyvalue); m_set_projection_matrix = false; @@ -610,7 +610,7 @@ int KX_Camera::_setattr(const STR_String &attr, PyObject *pyvalue) if (PyObject_IsMT_Matrix(pyvalue, 4)) { - if (attr == "projection_matrix") + if (!strcmp(attr, "projection_matrix")) { MT_Matrix4x4 mat; if (PyMatTo(pyvalue, mat)) diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 75d574cd697..9ff9c545f2c 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -270,8 +270,8 @@ public: KX_PYMETHOD_DOC(KX_Camera, setViewport); KX_PYMETHOD_DOC(KX_Camera, setOnTop); - virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); /* lens, near, far, projection_matrix */ + virtual int _setattr(const char *attr, PyObject *pyvalue); }; diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 4ac097eb575..dc2c4c4b414 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -420,10 +420,10 @@ PyAttributeDef KX_CameraActuator::Attributes[] = { {NULL} }; -PyObject* KX_CameraActuator::_getattr(const STR_String& attr) { +PyObject* KX_CameraActuator::_getattr(const char *attr) { PyObject* object; - if (attr == "object") { + if (!strcmp(attr, "object")) { if (!m_ob) Py_RETURN_NONE; else return m_ob->AddRef(); } @@ -434,10 +434,10 @@ PyObject* KX_CameraActuator::_getattr(const STR_String& attr) { _getattr_up(SCA_IActuator); } -int KX_CameraActuator::_setattr(const STR_String& attr, PyObject* value) { +int KX_CameraActuator::_setattr(const char *attr, PyObject* value) { int ret; - if (attr == "object") { + if (!strcmp(attr, "object")) { KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true)) diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index 4acca12833c..3b08536fc21 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -120,8 +120,8 @@ private : /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject* value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); /* set object to look at */ KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject); diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index 76357e9c58f..5c08bdc94a3 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -612,7 +612,7 @@ PyMethodDef KX_ConstraintActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_ConstraintActuator::_getattr(const STR_String& attr) { +PyObject* KX_ConstraintActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 28b9b1e6a0b..132b8a7328a 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -142,7 +142,7 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDamp); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDamp); diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index c9095ff34f6..9ceb4a05b06 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -92,32 +92,30 @@ PyParentObject KX_ConstraintWrapper::Parents[] = { NULL }; -PyObject* KX_ConstraintWrapper::_getattr(const STR_String& attr) +PyObject* KX_ConstraintWrapper::_getattr(const char *attr) { //here you can search for existing data members (like mass,friction etc.) _getattr_up(PyObjectPlus); } -int KX_ConstraintWrapper::_setattr(const STR_String& attr,PyObject* pyobj) +int KX_ConstraintWrapper::_setattr(const char *attr,PyObject* pyobj) { - - PyTypeObject* type = pyobj->ob_type; int result = 1; - if (type == &PyList_Type) + if (PyList_Check(pyobj)) { result = 0; } - if (type == &PyFloat_Type) + if (PyFloat_Check(pyobj)) { result = 0; } - if (type == &PyInt_Type) + if (PyInt_Check(pyobj)) { result = 0; } - if (type == &PyString_Type) + if (PyString_Check(pyobj)) { result = 0; } diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h index 79fb3dc21aa..36606d2d67b 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h @@ -35,8 +35,8 @@ class KX_ConstraintWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); public: KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); virtual ~KX_ConstraintWrapper (); diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 76459e46731..a8b4e0d7d2c 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -276,7 +276,7 @@ PyObject* KX_GameActuator::PySetFile(PyObject* self, PyObject* args, PyObject* k -PyObject* KX_GameActuator::_getattr(const STR_String& attr) +PyObject* KX_GameActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index bb3448995dc..856fa0c24e9 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -77,7 +77,7 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC(KX_GameActuator,GetFile); KX_PYMETHOD_DOC(KX_GameActuator,SetFile); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 42316c6c873..521fd317305 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1124,15 +1124,15 @@ PyParentObject KX_GameObject::Parents[] = { -PyObject* KX_GameObject::_getattr(const STR_String& attr) +PyObject* KX_GameObject::_getattr(const char *attr) { if (m_pPhysicsController1) { - if (attr == "mass") + if (!strcmp(attr, "mass")) return PyFloat_FromDouble(m_pPhysicsController1->GetMass()); } - if (attr == "parent") + if (!strcmp(attr, "parent")) { KX_GameObject* parent = GetParent(); if (parent) @@ -1143,21 +1143,23 @@ PyObject* KX_GameObject::_getattr(const STR_String& attr) Py_RETURN_NONE; } - if (attr == "visible") + if (!strcmp(attr, "visible")) return PyInt_FromLong(m_bVisible); - if (attr == "position") + if (!strcmp(attr, "position")) return PyObjectFrom(NodeGetWorldPosition()); - if (attr == "orientation") + if (!strcmp(attr, "orientation")) return PyObjectFrom(NodeGetWorldOrientation()); - if (attr == "scaling") + if (!strcmp(attr, "scaling")) return PyObjectFrom(NodeGetWorldScaling()); - if (attr == "name") + if (!strcmp(attr, "name")) return PyString_FromString(m_name.ReadPtr()); - if (attr == "timeOffset") { + + if (!strcmp(attr, "timeOffset")) + { if (m_pSGNode->GetSGParent()->IsSlowParent()) { return PyFloat_FromDouble(static_cast(m_pSGNode->GetSGParent()->GetParentRelation())->GetTimeOffset()); } else { @@ -1169,10 +1171,10 @@ PyObject* KX_GameObject::_getattr(const STR_String& attr) _getattr_up(SCA_IObject); } -int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr method +int KX_GameObject::_setattr(const char *attr, PyObject *value) // _setattr method { - if (attr == "parent") { + if (!strcmp(attr, "parent")) { PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()"); return 1; } @@ -1180,7 +1182,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr if (PyInt_Check(value)) { int val = PyInt_AsLong(value); - if (attr == "visible") + if (!strcmp(attr, "visible")) { SetVisible(val != 0, false); UpdateBuckets(false); @@ -1191,7 +1193,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr if (PyFloat_Check(value)) { MT_Scalar val = PyFloat_AsDouble(value); - if (attr == "timeOffset") { + if (!strcmp(attr, "timeOffset")) { if (m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsSlowParent()) { static_cast(m_pSGNode->GetSGParent()->GetParentRelation())->SetTimeOffset(val); return 0; @@ -1199,7 +1201,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr return 0; } } - if (attr == "mass") { + if (!strcmp(attr, "mass")) { if (m_pPhysicsController1) m_pPhysicsController1->SetMass(val); return 0; @@ -1208,7 +1210,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr if (PySequence_Check(value)) { - if (attr == "orientation") + if (!strcmp(attr, "orientation")) { MT_Matrix3x3 rot; if (PyObject_IsMT_Matrix(value, 3)) @@ -1251,7 +1253,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr return 1; } - if (attr == "position") + if (!strcmp(attr, "position")) { MT_Point3 pos; if (PyVecTo(value, pos)) @@ -1263,7 +1265,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr return 1; } - if (attr == "scaling") + if (!strcmp(attr, "scaling")) { MT_Vector3 scale; if (PyVecTo(value, scale)) @@ -1278,7 +1280,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr if (PyString_Check(value)) { - if (attr == "name") + if (!strcmp(attr, "name")) { m_name = PyString_AsString(value); return 0; diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 4f26031356f..7fe3009a957 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -756,18 +756,8 @@ public: * @section Python interface functions. */ - virtual - PyObject* - _getattr( - const STR_String& attr - ); - - virtual - int - _setattr( - const STR_String& attr, - PyObject *value - ); // _setattr method + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); // _setattr method KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index f5e17118ffb..a67fbe55c37 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -457,7 +457,7 @@ PyMethodDef KX_IpoActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_IpoActuator::_getattr(const STR_String& attr) { +PyObject* KX_IpoActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index 8e5baed0530..12e1835ab49 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -141,7 +141,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC(KX_IpoActuator,Set); KX_PYMETHOD_DOC(KX_IpoActuator,SetProperty); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index e0f171e78e0..36700265260 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -172,65 +172,59 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) GPU_lamp_shadow_buffer_unbind(lamp); } -PyObject* KX_LightObject::_getattr(const STR_String& attr) +PyObject* KX_LightObject::_getattr(const char *attr) { - if (attr == "layer") + if (!strcmp(attr, "layer")) return PyInt_FromLong(m_lightobj.m_layer); - if (attr == "energy") + if (!strcmp(attr, "energy")) return PyFloat_FromDouble(m_lightobj.m_energy); - if (attr == "distance") + if (!strcmp(attr, "distance")) return PyFloat_FromDouble(m_lightobj.m_distance); - if (attr == "colour" || attr == "color") + if (!strcmp(attr, "colour") || !strcmp(attr, "color")) return Py_BuildValue("[fff]", m_lightobj.m_red, m_lightobj.m_green, m_lightobj.m_blue); - if (attr == "lin_attenuation") + if (!strcmp(attr, "lin_attenuation")) return PyFloat_FromDouble(m_lightobj.m_att1); - if (attr == "quad_attenuation") + if (!strcmp(attr, "quad_attenuation")) return PyFloat_FromDouble(m_lightobj.m_att2); - if (attr == "spotsize") + if (!strcmp(attr, "spotsize")) return PyFloat_FromDouble(m_lightobj.m_spotsize); - if (attr == "spotblend") + if (!strcmp(attr, "spotblend")) return PyFloat_FromDouble(m_lightobj.m_spotblend); - if (attr == "SPOT") + if (!strcmp(attr, "SPOT")) return PyInt_FromLong(RAS_LightObject::LIGHT_SPOT); - if (attr == "SUN") + if (!strcmp(attr, "SUN")) return PyInt_FromLong(RAS_LightObject::LIGHT_SUN); - if (attr == "NORMAL") + if (!strcmp(attr, "NORMAL")) return PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL); - if (attr == "type") + if (!strcmp(attr, "type")) return PyInt_FromLong(m_lightobj.m_type); _getattr_up(KX_GameObject); } -int KX_LightObject::_setattr(const STR_String& attr, PyObject *pyvalue) -{ - if (attr == "SPOT" || attr == "SUN" || attr == "NORMAL") - { - PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr.ReadPtr()); - return 1; - } - +int KX_LightObject::_setattr(const char *attr, PyObject *pyvalue) +{ if (PyInt_Check(pyvalue)) { int value = PyInt_AsLong(pyvalue); - if (attr == "layer") + if (!strcmp(attr, "layer")) { m_lightobj.m_layer = value; return 0; } - if (attr == "type") + if (!strcmp(attr, "type")) { if (value >= RAS_LightObject::LIGHT_SPOT && value <= RAS_LightObject::LIGHT_NORMAL) m_lightobj.m_type = (RAS_LightObject::LightType) value; @@ -241,37 +235,37 @@ int KX_LightObject::_setattr(const STR_String& attr, PyObject *pyvalue) if (PyFloat_Check(pyvalue)) { float value = PyFloat_AsDouble(pyvalue); - if (attr == "energy") + if (!strcmp(attr, "energy")) { m_lightobj.m_energy = value; return 0; } - if (attr == "distance") + if (!strcmp(attr, "distance")) { m_lightobj.m_distance = value; return 0; } - if (attr == "lin_attenuation") + if (!strcmp(attr, "lin_attenuation")) { m_lightobj.m_att1 = value; return 0; } - if (attr == "quad_attenuation") + if (!strcmp(attr, "quad_attenuation")) { m_lightobj.m_att2 = value; return 0; } - if (attr == "spotsize") + if (!strcmp(attr, "spotsize")) { m_lightobj.m_spotsize = value; return 0; } - if (attr == "spotblend") + if (!strcmp(attr, "spotblend")) { m_lightobj.m_spotblend = value; return 0; @@ -280,7 +274,7 @@ int KX_LightObject::_setattr(const STR_String& attr, PyObject *pyvalue) if (PySequence_Check(pyvalue)) { - if (attr == "colour" || attr == "color") + if (!strcmp(attr, "colour") || !strcmp(attr, "color")) { MT_Vector3 color; if (PyVecTo(pyvalue, color)) @@ -294,6 +288,12 @@ int KX_LightObject::_setattr(const STR_String& attr, PyObject *pyvalue) } } + if (!strcmp(attr, "SPOT") || !strcmp(attr, "SUN") || !strcmp(attr, "NORMAL")) + { + PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr); + return 1; + } + return KX_GameObject::_setattr(attr, pyvalue); } diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index e5dbf0b7f4a..47edd09b5b9 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -63,8 +63,8 @@ public: void UnbindShadowBuffer(class RAS_IRasterizer *ras); void Update(); - virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); /* lens, near, far, projection_matrix */ + virtual int _setattr(const char *attr, PyObject *pyvalue); virtual bool IsLight(void) { return true; } }; diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 5cc102248f2..4b949903c88 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -93,9 +93,9 @@ void KX_MeshProxy::SetMeshModified(bool v) PyObject* -KX_MeshProxy::_getattr(const STR_String& attr) +KX_MeshProxy::_getattr(const char *attr) { - if (attr == "materials") + if (!strcmp(attr, "materials")) { PyObject *materials = PyList_New(0); list::iterator mit = m_meshobj->GetFirstMaterial(); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 3335c349673..34f60a54a3a 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -53,7 +53,7 @@ public: virtual CValue* GetReplica(); // stuff for python integration - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); KX_PYMETHOD(KX_MeshProxy,GetMaterialName); KX_PYMETHOD(KX_MeshProxy,GetTextureName); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 28279b9a6b8..3dd70cbb1b8 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -331,7 +331,7 @@ PyMethodDef KX_MouseFocusSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_MouseFocusSensor::_getattr(const STR_String& attr) { +PyObject* KX_MouseFocusSensor::_getattr(const char *attr) { _getattr_up(SCA_MouseSensor); } diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index 6731444699b..704198ce5a3 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -87,7 +87,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRayTarget); KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRaySource); diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index bae87c28123..7ef544618f8 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -320,7 +320,7 @@ PyMethodDef KX_NearSensor::Methods[] = { PyObject* -KX_NearSensor::_getattr(const STR_String& attr) +KX_NearSensor::_getattr(const char *attr) { _getattr_up(KX_TouchSensor); } diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index 3f7078ef9fd..58c7cc7da91 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -79,7 +79,7 @@ public: virtual void RegisterSumo(KX_TouchEventManager *touchman); virtual void UnregisterSumo(KX_TouchEventManager* touchman); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 98e73d4f0d7..e04f73a65e5 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -332,7 +332,7 @@ PyMethodDef KX_ObjectActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_ObjectActuator::_getattr(const STR_String& attr) { +PyObject* KX_ObjectActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); }; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index aa686f41233..0331c67617c 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -153,7 +153,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce); KX_PYMETHOD(KX_ObjectActuator,SetForce); diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index c7ac52e571a..5a908186235 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -172,9 +172,9 @@ PyMethodDef KX_ParentActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_ParentActuator::_getattr(const STR_String& attr) { +PyObject* KX_ParentActuator::_getattr(const char *attr) { - if (attr == "object") { + if (!strcmp(attr, "object")) { if (!m_ob) Py_RETURN_NONE; else return m_ob->AddRef(); } @@ -182,9 +182,9 @@ PyObject* KX_ParentActuator::_getattr(const STR_String& attr) { _getattr_up(SCA_IActuator); } -int KX_ParentActuator::_setattr(const STR_String& attr, PyObject* value) { +int KX_ParentActuator::_setattr(const char *attr, PyObject* value) { - if (attr == "object") { + if (!strcmp(attr, "object")) { KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true)) diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index e082b4fc209..c974001c0d0 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -76,8 +76,8 @@ class KX_ParentActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject* value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_ParentActuator,SetObject); diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index da4f05ced7c..246c63feb21 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -142,23 +142,21 @@ PyParentObject KX_PhysicsObjectWrapper::Parents[] = { NULL }; -PyObject* KX_PhysicsObjectWrapper::_getattr(const STR_String& attr) +PyObject* KX_PhysicsObjectWrapper::_getattr(const char *attr) { _getattr_up(PyObjectPlus); } -int KX_PhysicsObjectWrapper::_setattr(const STR_String& attr,PyObject* pyobj) +int KX_PhysicsObjectWrapper::_setattr(const char *attr,PyObject *pyobj) { - PyTypeObject* type = pyobj->ob_type; int result = 1; - - if (type == &PyInt_Type) + if (PyInt_Check(pyobj)) { result = 0; } - if (type == &PyString_Type) + if (PyString_Check(pyobj)) { result = 0; } diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h index 3dbd1be9323..95560698896 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h @@ -36,8 +36,8 @@ class KX_PhysicsObjectWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); public: KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); virtual ~KX_PhysicsObjectWrapper(); diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index bb9072b34dc..1c9e2a49c11 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -77,18 +77,17 @@ PyMethodDef KX_PolyProxy::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* -KX_PolyProxy::_getattr(const STR_String& attr) +PyObject* KX_PolyProxy::_getattr(const char *attr) { - if (attr == "matname") + if (!strcmp(attr, "matname")) { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } - if (attr == "texture") + if (!strcmp(attr, "texture")) { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); } - if (attr == "material") + if (!strcmp(attr, "material")) { RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial(); if(polymat->GetFlag() & RAS_BLENDERMAT) @@ -104,7 +103,7 @@ KX_PolyProxy::_getattr(const STR_String& attr) return mat; } } - if (attr == "matid") + if (!strcmp(attr, "matid")) { // we'll have to scan through the material bucket of the mes and compare with // the one of the polygon @@ -119,27 +118,27 @@ KX_PolyProxy::_getattr(const STR_String& attr) } return PyInt_FromLong(matid); } - if (attr == "v1") + if (!strcmp(attr, "v1")) { return PyInt_FromLong(m_polygon->GetVertexOffset(0)); } - if (attr == "v2") + if (!strcmp(attr, "v2")) { return PyInt_FromLong(m_polygon->GetVertexOffset(1)); } - if (attr == "v3") + if (!strcmp(attr, "v3")) { return PyInt_FromLong(m_polygon->GetVertexOffset(2)); } - if (attr == "v4") + if (!strcmp(attr, "v4")) { return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0)); } - if (attr == "visible") + if (!strcmp(attr, "visible")) { return PyInt_FromLong(m_polygon->IsVisible()); } - if (attr == "collide") + if (!strcmp(attr, "collide")) { return PyInt_FromLong(m_polygon->IsCollider()); } diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h index 506e2c2a656..9b548f9490d 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.h +++ b/source/gameengine/Ketsji/KX_PolyProxy.h @@ -53,7 +53,7 @@ public: // stuff for python integration - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex) KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex) diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index c9180bf3a80..9c792a3e673 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -202,7 +202,7 @@ PyParentObject KX_PolygonMaterial::Parents[] = { NULL }; -PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) +PyObject* KX_PolygonMaterial::_getattr(const char *attr) { if (attr == "texture") return PyString_FromString(m_texturename.ReadPtr()); @@ -253,7 +253,7 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) _getattr_up(PyObjectPlus); } -int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) +int KX_PolygonMaterial::_setattr(const char *attr, PyObject *pyvalue) { if (PyFloat_Check(pyvalue)) { diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index fe116f757db..a3ef4ca51ef 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -115,8 +115,8 @@ public: KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial); KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram); - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *pyvalue); }; #endif // __KX_POLYGONMATERIAL_H__ diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 244e9b75d8e..1321b862463 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -229,7 +229,7 @@ PyMethodDef KX_RadarSensor::Methods[] = { {NULL,NULL,NULL,NULL} //Sentinel }; -PyObject* KX_RadarSensor::_getattr(const STR_String& attr) { +PyObject* KX_RadarSensor::_getattr(const char *attr) { _getattr_up(KX_TouchSensor); } diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index 7272b219e37..f8f80725145 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -81,7 +81,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD_DOC(KX_RadarSensor,GetConeOrigin); KX_PYMETHOD_DOC(KX_RadarSensor,GetConeTarget); diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index e24fb773eac..22611c444df 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -418,6 +418,6 @@ PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self, -PyObject* KX_RaySensor::_getattr(const STR_String& attr) { +PyObject* KX_RaySensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); } diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index 02a755fedc1..2baec12f74e 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -79,7 +79,7 @@ public: KX_PYMETHOD_DOC(KX_RaySensor,GetHitNormal); KX_PYMETHOD_DOC(KX_RaySensor,GetRayDirection); - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); }; diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index ab65c93529e..4c331b2c9d6 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -205,9 +205,9 @@ PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { }; -PyObject* KX_SCA_AddObjectActuator::_getattr(const STR_String& attr) +PyObject* KX_SCA_AddObjectActuator::_getattr(const char *attr) { - if (attr == "object") { + if (!strcmp(attr, "object")) { if (!m_OriginalObject) Py_RETURN_NONE; else return m_OriginalObject->AddRef(); } @@ -219,9 +219,9 @@ PyObject* KX_SCA_AddObjectActuator::_getattr(const STR_String& attr) _getattr_up(SCA_IActuator); } -int KX_SCA_AddObjectActuator::_setattr(const STR_String& attr, PyObject* value) { +int KX_SCA_AddObjectActuator::_setattr(const char *attr, PyObject* value) { - if (attr == "object") { + if (!strcmp(attr, "object")) { KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true)) diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 035f44f16c9..18298cbcb0c 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -110,8 +110,8 @@ public: virtual bool Update(); - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject* value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); SCA_IObject* GetLastCreatedObject( diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index 176ccf1a84a..e8d9a7f07c8 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -87,7 +87,7 @@ PyMethodDef KX_SCA_DynamicActuator::Methods[] = { -PyObject* KX_SCA_DynamicActuator::_getattr(const STR_String& attr) +PyObject* KX_SCA_DynamicActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h index de2fab68d15..a82cddd66a7 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h @@ -64,10 +64,7 @@ class KX_SCA_DynamicActuator : public SCA_IActuator virtual bool Update(); - virtual PyObject* - _getattr( - const STR_String& attr - ); + virtual PyObject* _getattr(const char *attr); /* 1. setOperation */ KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,setOperation); diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index ec29448907f..443921d22b0 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -128,7 +128,7 @@ PyMethodDef KX_SCA_EndObjectActuator::Methods[] = { }; -PyObject* KX_SCA_EndObjectActuator::_getattr(const STR_String& attr) +PyObject* KX_SCA_EndObjectActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h index add9c05b000..12118743f0a 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h @@ -64,10 +64,7 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* - _getattr( - const STR_String& attr - ); + virtual PyObject* _getattr(const char *attr); }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 261d9ec8f0c..ccc3b8fdb18 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -91,7 +91,7 @@ PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { -PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const STR_String& attr) +PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 1da154cc222..0ba60650683 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -69,10 +69,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator virtual bool Update(); - virtual PyObject* - _getattr( - const STR_String& attr - ); + virtual PyObject* _getattr(const char *attr); void InstantReplaceMesh(); /* 1. setMesh */ diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 476a931355f..49babedd467 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1544,28 +1544,28 @@ PyParentObject KX_Scene::Parents[] = { NULL }; -PyObject* KX_Scene::_getattr(const STR_String& attr) +PyObject* KX_Scene::_getattr(const char *attr) { - if (attr == "name") + if (!strcmp(attr, "name")) return PyString_FromString(GetName()); - if (attr == "active_camera") + if (!strcmp(attr, "active_camera")) { KX_Camera *camera = GetActiveCamera(); camera->AddRef(); return (PyObject*) camera; } - if (attr == "suspended") + if (!strcmp(attr, "suspended")) return PyInt_FromLong(m_suspend); - if (attr == "activity_culling") + if (!strcmp(attr, "activity_culling")) return PyInt_FromLong(m_activity_culling); - if (attr == "activity_culling_radius") + if (!strcmp(attr, "activity_culling_radius")) return PyFloat_FromDouble(m_activity_box_radius); - PyObject* value = PyDict_GetItemString(m_attrlist, const_cast(attr.ReadPtr())); + PyObject* value = PyDict_GetItemString(m_attrlist, attr); if (value) { Py_INCREF(value); @@ -1575,16 +1575,15 @@ PyObject* KX_Scene::_getattr(const STR_String& attr) _getattr_up(PyObjectPlus); } -int KX_Scene::_delattr(const STR_String &attr) +int KX_Scene::_delattr(const char *attr) { - PyDict_DelItemString(m_attrlist, const_cast(attr.ReadPtr())); + PyDict_DelItemString(m_attrlist, attr); return 0; } -int KX_Scene::_setattr(const STR_String &attr, PyObject *pyvalue) +int KX_Scene::_setattr(const char *attr, PyObject *pyvalue) { - - if (!PyDict_SetItemString(m_attrlist, const_cast(attr.ReadPtr()), pyvalue)) + if (!PyDict_SetItemString(m_attrlist, attr, pyvalue)) return 0; return PyObjectPlus::_setattr(attr, pyvalue); diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 5f7e1167e27..ecc0fd51d73 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -564,9 +564,9 @@ public: KX_PYMETHOD_DOC(KX_Scene, setSceneViewport); */ - virtual PyObject* _getattr(const STR_String& attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ - virtual int _setattr(const STR_String &attr, PyObject *pyvalue); - virtual int _delattr(const STR_String &attr); + virtual PyObject* _getattr(const char *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ + virtual int _setattr(const char *attr, PyObject *pyvalue); + virtual int _delattr(const char *attr); /** * Sets the time the scene was suspended diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 35484699b17..a5f49f97d4b 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -270,7 +270,7 @@ PyMethodDef KX_SceneActuator::Methods[] = -PyObject* KX_SceneActuator::_getattr(const STR_String& attr) +PyObject* KX_SceneActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index 55aaf629d7c..af11af955bf 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -92,7 +92,7 @@ class KX_SceneActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); /* 1. set */ /* Removed */ diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index afa5af3bc04..ba60ea81739 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -287,7 +287,7 @@ PyMethodDef KX_SoundActuator::Methods[] = { -PyObject* KX_SoundActuator::_getattr(const STR_String& attr) +PyObject* KX_SoundActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index 5a9edbc4c5e..68d5b792729 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -80,7 +80,7 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); KX_PYMETHOD(KX_SoundActuator,SetFilename); KX_PYMETHOD(KX_SoundActuator,GetFilename); diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index e360c4bac1f..7237d6ced1e 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -146,10 +146,7 @@ KX_StateActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* -KX_StateActuator::_getattr( - const STR_String& attr - ) +PyObject* KX_StateActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); }; diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h index 8698e51b2c1..023b8993d7c 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.h +++ b/source/gameengine/Ketsji/KX_StateActuator.h @@ -73,7 +73,7 @@ class KX_StateActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC(KX_StateActuator,SetOperation); KX_PYMETHOD_DOC(KX_StateActuator,SetMask); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 0000d5793b6..6528ec466ce 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -261,7 +261,7 @@ PyMethodDef KX_TouchSensor::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* KX_TouchSensor::_getattr(const STR_String& attr) { +PyObject* KX_TouchSensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 8fbb1c676ba..e07f89f0a31 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -106,7 +106,7 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); /* 1. setProperty */ KX_PYMETHOD_DOC(KX_TouchSensor,SetProperty); diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 515349fbba8..f9f804cfc66 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -470,9 +470,9 @@ PyMethodDef KX_TrackToActuator::Methods[] = { -PyObject* KX_TrackToActuator::_getattr(const STR_String& attr) +PyObject* KX_TrackToActuator::_getattr(const char *attr) { - if (attr == "object") { + if (!strcmp(attr, "object")) { if (!m_object) Py_RETURN_NONE; else return m_object->AddRef(); } @@ -480,10 +480,10 @@ PyObject* KX_TrackToActuator::_getattr(const STR_String& attr) _getattr_up(SCA_IActuator); } -int KX_TrackToActuator::_setattr(const STR_String& attr, PyObject* value) { +int KX_TrackToActuator::_setattr(const char *attr, PyObject* value) { int ret; - if (attr == "object") { + if (!strcmp(attr, "object")) { KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true)) diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index c9cae905240..392e55402f1 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -72,8 +72,8 @@ class KX_TrackToActuator : public SCA_IActuator virtual bool Update(double curtime, bool frame); /* Python part */ - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject* value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_TrackToActuator,SetObject); diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 028f96f6c5b..057e10f195a 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -322,13 +322,13 @@ PyParentObject KX_VehicleWrapper::Parents[] = { NULL }; -PyObject* KX_VehicleWrapper::_getattr(const STR_String& attr) +PyObject* KX_VehicleWrapper::_getattr(const char *attr) { //here you can search for existing data members (like mass,friction etc.) _getattr_up(PyObjectPlus); } -int KX_VehicleWrapper::_setattr(const STR_String& attr,PyObject* pyobj) +int KX_VehicleWrapper::_setattr(const char *attr,PyObject* pyobj) { PyTypeObject* type = pyobj->ob_type; diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h index b98369d401a..cad926ce85a 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.h +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h @@ -12,8 +12,8 @@ class PHY_IMotionState; class KX_VehicleWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *value); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); std::vector m_motionStates; diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 25205714308..eddd110ee81 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -79,15 +79,43 @@ PyMethodDef KX_VertexProxy::Methods[] = { }; PyObject* -KX_VertexProxy::_getattr(const STR_String& attr) +KX_VertexProxy::_getattr(const char *attr) { - if (attr == "XYZ") + + if (attr[1]=='\0') { // Group single letters + // pos + if (attr[0]=='x') + return PyFloat_FromDouble(m_vertex->getXYZ()[0]); + if (attr[0]=='y') + return PyFloat_FromDouble(m_vertex->getXYZ()[1]); + if (attr[0]=='z') + return PyFloat_FromDouble(m_vertex->getXYZ()[2]); + + // Col + if (attr[0]=='r') + return PyFloat_FromDouble(m_vertex->getRGBA()[0]/255.0); + if (attr[0]=='g') + return PyFloat_FromDouble(m_vertex->getRGBA()[1]/255.0); + if (attr[0]=='b') + return PyFloat_FromDouble(m_vertex->getRGBA()[2]/255.0); + if (attr[0]=='a') + return PyFloat_FromDouble(m_vertex->getRGBA()[3]/255.0); + + // UV + if (attr[0]=='u') + return PyFloat_FromDouble(m_vertex->getUV1()[0]); + if (attr[0]=='v') + return PyFloat_FromDouble(m_vertex->getUV1()[1]); + } + + + if (!strcmp(attr, "XYZ")) return PyObjectFrom(MT_Vector3(m_vertex->getXYZ())); - if (attr == "UV") + if (!strcmp(attr, "UV")) return PyObjectFrom(MT_Point2(m_vertex->getUV1())); - if (attr == "colour" || attr == "color") + if (!strcmp(attr, "color") || !strcmp(attr, "colour")) { const unsigned char *colp = m_vertex->getRGBA(); MT_Vector4 color(colp[0], colp[1], colp[2], colp[3]); @@ -95,43 +123,19 @@ KX_VertexProxy::_getattr(const STR_String& attr) return PyObjectFrom(color); } - if (attr == "normal") + if (!strcmp(attr, "normal")) { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } - - // pos - if (attr == "x") - return PyFloat_FromDouble(m_vertex->getXYZ()[0]); - if (attr == "y") - return PyFloat_FromDouble(m_vertex->getXYZ()[1]); - if (attr == "z") - return PyFloat_FromDouble(m_vertex->getXYZ()[2]); - - // Col - if (attr == "r") - return PyFloat_FromDouble(m_vertex->getRGBA()[0]/255.0); - if (attr == "g") - return PyFloat_FromDouble(m_vertex->getRGBA()[1]/255.0); - if (attr == "b") - return PyFloat_FromDouble(m_vertex->getRGBA()[2]/255.0); - if (attr == "a") - return PyFloat_FromDouble(m_vertex->getRGBA()[3]/255.0); - - // UV - if (attr == "u") - return PyFloat_FromDouble(m_vertex->getUV1()[0]); - if (attr == "v") - return PyFloat_FromDouble(m_vertex->getUV1()[1]); - + _getattr_up(SCA_IObject); } -int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) +int KX_VertexProxy::_setattr(const char *attr, PyObject *pyvalue) { if (PySequence_Check(pyvalue)) { - if (attr == "XYZ") + if (!strcmp(attr, "XYZ")) { MT_Point3 vec; if (PyVecTo(pyvalue, vec)) @@ -143,7 +147,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 1; } - if (attr == "UV") + if (!strcmp(attr, "UV")) { MT_Point2 vec; if (PyVecTo(pyvalue, vec)) @@ -155,7 +159,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 1; } - if (attr == "colour" || attr == "color") + if (!strcmp(attr, "color") || !strcmp(attr, "colour")) { MT_Vector4 vec; if (PyVecTo(pyvalue, vec)) @@ -167,7 +171,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 1; } - if (attr == "normal") + if (!strcmp(attr, "normal")) { MT_Vector3 vec; if (PyVecTo(pyvalue, vec)) @@ -185,7 +189,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) float val = PyFloat_AsDouble(pyvalue); // pos MT_Point3 pos(m_vertex->getXYZ()); - if (attr == "x") + if (!strcmp(attr, "x")) { pos.x() = val; m_vertex->SetXYZ(pos); @@ -193,7 +197,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 0; } - if (attr == "y") + if (!strcmp(attr, "y")) { pos.y() = val; m_vertex->SetXYZ(pos); @@ -201,7 +205,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 0; } - if (attr == "z") + if (!strcmp(attr, "z")) { pos.z() = val; m_vertex->SetXYZ(pos); @@ -211,7 +215,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) // uv MT_Point2 uv = m_vertex->getUV1(); - if (attr == "u") + if (!strcmp(attr, "u")) { uv[0] = val; m_vertex->SetUV(uv); @@ -219,7 +223,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 0; } - if (attr == "v") + if (!strcmp(attr, "v")) { uv[1] = val; m_vertex->SetUV(uv); @@ -229,7 +233,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) // uv MT_Point2 uv2 = m_vertex->getUV2(); - if (attr == "u2") + if (!strcmp(attr, "u2")) { uv[0] = val; m_vertex->SetUV2(uv); @@ -237,7 +241,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) return 0; } - if (attr == "v2") + if (!strcmp(attr, "v2")) { uv[1] = val; m_vertex->SetUV2(uv); @@ -249,28 +253,28 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) unsigned int icol = *((const unsigned int *)m_vertex->getRGBA()); unsigned char *cp = (unsigned char*) &icol; val *= 255.0; - if (attr == "r") + if (!strcmp(attr, "r")) { cp[0] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); return 0; } - if (attr == "g") + if (!strcmp(attr, "g")) { cp[1] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); return 0; } - if (attr == "b") + if (!strcmp(attr, "b")) { cp[2] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); return 0; } - if (attr == "a") + if (!strcmp(attr, "a")) { cp[3] = (unsigned char) val; m_vertex->SetRGBA(icol); diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index e154ea11b40..72949268e6d 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -54,8 +54,8 @@ public: // stuff for python integration - virtual PyObject* _getattr(const STR_String& attr); - virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *pyvalue); KX_PYMETHOD(KX_VertexProxy,GetXYZ); KX_PYMETHOD(KX_VertexProxy,SetXYZ); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index 4b0db5a7953..0a4aaa0dffe 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -126,10 +126,7 @@ KX_VisibilityActuator::Methods[] = { {NULL,NULL} //Sentinel }; -PyObject* -KX_VisibilityActuator::_getattr( - const STR_String& attr - ) +PyObject* KX_VisibilityActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); }; diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index d1b85ab998c..323280de8cb 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -67,7 +67,7 @@ class KX_VisibilityActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const STR_String& attr); + virtual PyObject* _getattr(const char *attr); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC(KX_VisibilityActuator,SetVisible); From d3e7b37fff6d2644c5b931ba38777550faad7011 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 19 Feb 2009 23:13:41 +0000 Subject: [PATCH 192/252] BGE API Cleanup: distinction between array and list of values in KX_PYATTRIBUTE macros. Fix compilation problem under Windows with strcasecmp: define it as stricmp --- source/gameengine/Expressions/InputParser.cpp | 3 ++ source/gameengine/Expressions/PyObjectPlus.h | 32 +++++++++++++++---- .../GameLogic/SCA_JoystickSensor.cpp | 4 +-- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 2 +- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index c3869d8f89b..a60e1ee59dc 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -38,6 +38,9 @@ // cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc... #include "IfExpr.h" +#if defined(WIN32) || defined(WIN64) +#define strcasecmp _stricmp +#endif /* Def WIN32 or Def WIN64 */ #define NUM_PRIORITY 6 ////////////////////////////////////////////////////////////////////// diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 5092c8106ec..5ba894ef23a 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -283,10 +283,17 @@ typedef struct KX_PYATTRIBUTE_DEF { #define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, ((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} } +// SHORT_LIST +#define KX_PYATTRIBUTE_SHORT_LIST_RW(name,min,max,clamp,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} } +#define KX_PYATTRIBUTE_SHORT_LIST_RO(name,object,field,length) \ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \ @@ -296,10 +303,17 @@ typedef struct KX_PYATTRIBUTE_DEF { #define KX_PYATTRIBUTE_INT_RO(name,object,field) \ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, ((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} } +// INT_LIST +#define KX_PYATTRIBUTE_INT_LIST_RW(name,min,max,clamp,object,field,length) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } +#define KX_PYATTRIBUTE_INT_LIST_RO(name,object,field,length) \ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } // always clamp for float @@ -310,11 +324,11 @@ typedef struct KX_PYATTRIBUTE_DEF { #define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, {NULL, NULL, NULL, ((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } @@ -323,6 +337,10 @@ typedef struct KX_PYATTRIBUTE_DEF { #define KX_PYATTRIBUTE_STRING_RO(name,object,field) \ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } +//Multiple integer +#define KX_PYATTRIBUTE_MINT_RW_CHECK(name,min,max,clamp,object,field,length,function) \ + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + /*------------------------------ * PyObjectPlus ------------------------------*/ diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 17a8710ed48..c2d90c830cf 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -331,8 +331,8 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = { KX_PYATTRIBUTE_SHORT_RW("index",0,JOYINDEX_MAX-1,true,SCA_JoystickSensor,m_joyindex), KX_PYATTRIBUTE_INT_RW("threshold",0,32768,true,SCA_JoystickSensor,m_precision), KX_PYATTRIBUTE_INT_RW("button",0,100,false,SCA_JoystickSensor,m_button), - KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("axis",0,3,true,SCA_JoystickSensor,m_axis,2,CheckAxis), - KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("hat",0,12,true,SCA_JoystickSensor,m_hat,2,CheckHat), + KX_PYATTRIBUTE_INT_LIST_RW_CHECK("axis",0,3,true,SCA_JoystickSensor,m_axis,2,CheckAxis), + KX_PYATTRIBUTE_INT_LIST_RW_CHECK("hat",0,12,true,SCA_JoystickSensor,m_hat,2,CheckHat), // dummy attributes will just be read-only in _setattr // you still need to defined them in _getattr KX_PYATTRIBUTE_DUMMY("axisPosition"), diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index a96d3758d3c..73f784b7e92 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -337,7 +337,7 @@ PyMethodDef SCA_MouseSensor::Methods[] = { PyAttributeDef SCA_MouseSensor::Attributes[] = { KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",KX_MOUSESENSORMODE_NODEF,KX_MOUSESENSORMODE_MAX-1,true,SCA_MouseSensor,m_mousemode,UpdateHotkey), - KX_PYATTRIBUTE_SHORT_ARRAY_RO("position",SCA_MouseSensor,m_x,2), + KX_PYATTRIBUTE_SHORT_LIST_RO("position",SCA_MouseSensor,m_x,2), { NULL } //Sentinel }; From 95f91f2a4634a7b42d7ddca02cc2f4702141ae80 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 19 Feb 2009 23:15:27 +0000 Subject: [PATCH 193/252] MSVC9 project files: reactivate VideoTexture module in BGE; it that was disabled for some reason. --- .../gameengine/blenderhook/KX_blenderhook.vcproj | 5 +++-- projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj b/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj index 64f6b92ef29..8e027fd1854 100644 --- a/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj +++ b/projectfiles_vc9/gameengine/blenderhook/KX_blenderhook.vcproj @@ -4,6 +4,7 @@ Version="9,00" Name="KX_blenderhook" ProjectGUID="{8154A59A-CAED-403D-AB94-BC4E7C032666}" + RootNamespace="KX_blenderhook" TargetFrameworkVersion="131072" > @@ -43,7 +44,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenloader;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\ketsji;..\..\..\source\gameengine\network;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Physics\Sumo;..\..\..\source\gameengine\Physics\common;..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include;..\..\..\source\blender\gpu" - PreprocessorDefinitions="WIN32;_LIB;_DEBUG;WITH_GLEXT" + PreprocessorDefinitions="WIN32;_LIB;_DEBUG;WITH_GLEXT;WITH_FFMPEG" BasicRuntimeChecks="3" RuntimeLibrary="1" DefaultCharIsUnsigned="true" @@ -119,7 +120,7 @@ Name="VCCLCompilerTool" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\extern\solid\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\source\blender;..\..\..\source\blender\misc;..\..\..\source\blender\imbuf;..\..\..\source\blender\blenlib;..\..\..\source\blender\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\blenloader;..\..\..\source\blender\blenkernel;..\..\..\source\kernel\gen_system;..\..\..\source\gameengine\ketsji;..\..\..\source\gameengine\network;..\..\..\source\gameengine\rasterizer;..\..\..\source\gameengine\Converter;..\..\..\source\gameengine\gamelogic;..\..\..\source\gameengine\scenegraph;..\..\..\source\gameengine\expressions;..\..\..\source\gameengine\Physics\Sumo;..\..\..\source\gameengine\Physics\common;..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\source\gameengine\Physics\Sumo\Fuzzics\include;..\..\..\source\blender\gpu" - PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT" + PreprocessorDefinitions="NDEBUG;WIN32;_LIB;USE_SUMO_SOLID;WITH_GLEXT;WITH_FFMPEG" StringPooling="true" BasicRuntimeChecks="0" RuntimeLibrary="0" diff --git a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj index ab0b05c208c..b539b64d374 100644 --- a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj +++ b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj @@ -45,7 +45,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\ghost\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\openal\include;..\..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\blender\include;..\..\..\..\source\blender\imbuf;..\..\..\..\source\blender\blenlib;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenloader;..\..\..\..\source\blender\readblenfile;..\..\..\..\source\blender\render\extern\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Physics;..\..\..\..\source\gameengine\network;..\..\..\..\source\gameengine\rasterizer;..\..\..\..\source\gameengine\converter;..\..\..\..\source\gameengine\gamelogic;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\scenegraph;..\..\..\..\source\gameengine\Physics\Ode;..\..\..\..\source\gameengine\soundsystem;..\..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\..\source\gameengine\gameplayer\common;..\..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\..\source\gameengine\gameplayer\common\windows;..\..\..\..\source\sumo\include;..\..\..\..\source\sumo\fuzzics\include;..\..\..\..\source\blender\gpu;..\..\..\..\..\build\msvc_9\intern\guardedalloc\include" - PreprocessorDefinitions="WIN32,_CONSOLE,dSINGLE, _DEBUG" + PreprocessorDefinitions="WIN32,_CONSOLE,dSINGLE, _DEBUG;WITH_FFMPEG" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" @@ -138,7 +138,7 @@ Name="VCCLCompilerTool" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\build\msvc_9\intern\ghost\include;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\openal\include;..\..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\..\..\build\msvc_9\intern\SoundSystem\include;..\..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\source\blender\include;..\..\..\..\source\blender\imbuf;..\..\..\..\source\blender\blenlib;..\..\..\..\source\blender\blenkernel;..\..\..\..\source\blender\makesdna;..\..\..\..\source\blender\blenloader;..\..\..\..\source\blender\readblenfile;..\..\..\..\source\blender\render\extern\include;..\..\..\..\source\kernel\gen_system;..\..\..\..\source\kernel\gen_messaging;..\..\..\..\source\gameengine\ketsji;..\..\..\..\source\gameengine\Physics;..\..\..\..\source\gameengine\network;..\..\..\..\source\gameengine\rasterizer;..\..\..\..\source\gameengine\converter;..\..\..\..\source\gameengine\gamelogic;..\..\..\..\source\gameengine\expressions;..\..\..\..\source\gameengine\scenegraph;..\..\..\..\source\gameengine\Physics\Ode;..\..\..\..\source\gameengine\soundsystem;..\..\..\..\source\gameengine\ketsji\kxnetwork;..\..\..\..\source\gameengine\gameplayer\common;..\..\..\..\source\gameengine\soundsystem\snd_openal;..\..\..\..\source\gameengine\network\loopbacknetwork;..\..\..\..\source\gameengine\rasterizer\ras_openglrasterizer;..\..\..\..\source\gameengine\gameplayer\common\windows;..\..\..\..\source\sumo\include;..\..\..\..\source\sumo\fuzzics\include;..\..\..\..\source\blender\gpu;..\..\..\..\..\build\msvc_9\intern\guardedalloc\include" - PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE;WITH_FFMPEG" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" From 7260e8fe294d77533dc7f41303419b492fc0de98 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Feb 2009 03:02:39 +0000 Subject: [PATCH 194/252] bugfix [#17941] Attempting to change path of audio to relative fails. --- source/blender/blenlib/intern/bpath.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index e23c2658399..ac0c4bf4efd 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -339,9 +339,9 @@ void BLI_bpathIterator_step( struct BPathIterator *bpi) { bSound *snd = (bSound *)bpi->data; bpi->lib = snd->id.lib ? snd->id.lib->filename : NULL; - bpi->path = snd->sample->name; + bpi->path = snd->name; bpi->name = snd->id.name+2; - bpi->len = sizeof(snd->sample->name); + bpi->len = sizeof(snd->name); /* we are done, advancing to the next item, this type worked fine */ break; From f87a399978e81e96a711347b1dee66dbbbd362d5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Feb 2009 04:42:46 +0000 Subject: [PATCH 195/252] [#18058] Black dots appear when blender renders with multi-thread and material nodes Without thread locking the function that allocates new threads, black dots appear in renders. This wont affect composite nodes, Ton/Brecht - this is possibly too many lock/unlocks but I timed the render from the bug report and it didn't make a noticeable difference. --- source/blender/blenkernel/intern/node.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 978b47b651f..9a78f8ea02a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1999,19 +1999,23 @@ static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread) { ListBase *lb= &ntree->threadstack[thread]; bNodeThreadStack *nts; - + + /* for material shading this is called quite a lot (perhaps too much locking unlocking) + * however without locking we get bug #18058 - Campbell */ + BLI_lock_thread(LOCK_CUSTOM1); + for(nts=lb->first; nts; nts=nts->next) { if(!nts->used) { nts->used= 1; + BLI_unlock_thread(LOCK_CUSTOM1); return nts; } } - nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack"); nts->stack= MEM_dupallocN(ntree->stack); nts->used= 1; BLI_addtail(lb, nts); - + BLI_unlock_thread(LOCK_CUSTOM1); return nts; } From a3b684d69878eaff3e0ad475264485419e0c029f Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sat, 21 Feb 2009 12:15:57 +0000 Subject: [PATCH 196/252] [#18277] Segfault crash by editing mesh with subsurf+ParticleInstance modifiers particleInstanceModifier_applyModifier uses getVertCo,which is not implemented by ccgDM. getVertCo was used to simply perform a min/max, so it was fixed to use the apropriate min/max dm->getMinMax(dm, min_r, max_r); Maybe the fact ccgDM doesn't implements getVertCo/getVertNo is a bug, since it implements every other DM function and its strange those are left out. --- source/blender/blenkernel/intern/modifier.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 6bdd395a2ac..566a139f72c 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6380,20 +6380,11 @@ static DerivedMesh * particleInstanceModifier_applyModifier( psys->lattice=psys_get_lattice(ob, psys); if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)){ - float co[3]; - for(i=0; i< totvert; i++){ - dm->getVertCo(dm,i,co); - if(i==0){ - min_co=max_co=co[track]; - } - else{ - if(co[track]max_co) - max_co=co[track]; - } - } + float min_r[3], max_r[3]; + dm->getMinMax(dm, min_r, max_r); + min_co=min_r[track]; + max_co=max_r[track]; } result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface); From 9d5c2af1d1e11d40fec6c0da96cb37de1684f13c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 21 Feb 2009 12:43:24 +0000 Subject: [PATCH 197/252] * removed typedefs that were not used (from anonymous enums and structs) * Missed some cases of using a 'char *' as an attribute * replace BGE's Py_Return macro with Pythons Py_RETURN_NONE * other minor warnings removed --- .../Converter/BL_ShapeActionActuator.cpp | 2 +- source/gameengine/Expressions/ListValue.cpp | 2 +- .../gameengine/Expressions/PyObjectPlus.cpp | 1 - source/gameengine/Expressions/PyObjectPlus.h | 9 +-- .../GameLogic/SCA_ActuatorSensor.cpp | 2 +- .../gameengine/GameLogic/SCA_DelaySensor.cpp | 6 +- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 2 +- source/gameengine/GameLogic/SCA_ISensor.cpp | 12 ++-- .../GameLogic/SCA_KeyboardSensor.cpp | 12 ++-- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 2 +- .../GameLogic/SCA_PropertyActuator.cpp | 4 +- .../GameLogic/SCA_PropertySensor.cpp | 6 +- .../GameLogic/SCA_RandomActuator.cpp | 24 +++---- .../gameengine/GameLogic/SCA_RandomSensor.cpp | 2 +- source/gameengine/Ketsji/BL_Shader.cpp | 50 +++++++------- .../KXNetwork/KX_NetworkMessageActuator.cpp | 8 +-- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 10 +-- source/gameengine/Ketsji/KX_CDActuator.cpp | 8 +-- source/gameengine/Ketsji/KX_Camera.cpp | 8 +-- source/gameengine/Ketsji/KX_Camera.h | 2 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 8 +-- .../Ketsji/KX_ConstraintActuator.cpp | 18 ++--- source/gameengine/Ketsji/KX_GameActuator.cpp | 2 +- source/gameengine/Ketsji/KX_GameObject.cpp | 2 +- source/gameengine/Ketsji/KX_IpoActuator.cpp | 16 ++--- .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 2 +- .../gameengine/Ketsji/KX_ObjectActuator.cpp | 22 +++--- .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 68 +++++++++---------- source/gameengine/Ketsji/KX_RaySensor.cpp | 2 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 3 +- .../Ketsji/KX_SCA_DynamicActuator.cpp | 2 +- source/gameengine/Ketsji/KX_SceneActuator.cpp | 8 +-- source/gameengine/Ketsji/KX_SoundActuator.cpp | 24 +++---- source/gameengine/Ketsji/KX_StateActuator.cpp | 4 +- source/gameengine/Ketsji/KX_TouchSensor.cpp | 6 +- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 9 ++- source/gameengine/Ketsji/KX_VertexProxy.cpp | 12 ++-- .../Ketsji/KX_VisibilityActuator.cpp | 2 +- .../Physics/Sumo/Fuzzics/include/SM_Scene.h | 2 +- .../Physics/common/PHY_DynamicTypes.h | 2 +- 40 files changed, 190 insertions(+), 196 deletions(-) diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 7cba6b01e1a..2e02ee9b941 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -911,6 +911,6 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* self, printf("Invalid type for action actuator: %d\n", typeArg); /* error */ } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 3cf22bdc9bd..b8a8a1a63b2 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -429,7 +429,7 @@ PyObject* CListValue::Pyreverse(PyObject* self, { std::reverse(m_pValueArray.begin(),m_pValueArray.end()); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 16184b7c5f2..2c4fbd5a867 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -697,7 +697,6 @@ bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent PyObject *PyObjectPlus::Py_isA(PyObject *value) // Python wrapper for isA { - char *mytypename; if (!PyString_Check(value)) { PyErr_SetString(PyExc_TypeError, "expected a string"); return NULL; diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 5ba894ef23a..0fae175e3cf 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -72,9 +72,6 @@ typedef int Py_ssize_t; #define PY_METHODCHAR const char * #endif - // some basic python macros -#define Py_Return { Py_INCREF(Py_None); return Py_None;} - static inline void Py_Fatal(const char *M) { //cout << M << endl; exit(-1); @@ -394,10 +391,10 @@ public: // isA methods bool isA(PyTypeObject *T); bool isA(const char *mytypename); - PyObject *Py_isA(PyObject *args); - static PyObject *sPy_isA(PyObject *self, PyObject *args, PyObject *kwd) + PyObject *Py_isA(PyObject *value); + static PyObject *sPy_isA(PyObject *self, PyObject *value) { - return ((PyObjectPlus*)self)->Py_isA(args); + return ((PyObjectPlus*)self)->Py_isA(value); } }; diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index dcdd7df50d4..7f8dbef7758 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -221,7 +221,7 @@ PyObject* SCA_ActuatorSensor::PySetActuator(PyObject* self, PyObject* args, PyOb } else { ; /* error: bad actuator name */ } - Py_Return; + Py_RETURN_NONE; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index 802edc4b6cf..25c9888cadd 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -211,7 +211,7 @@ PyObject* SCA_DelaySensor::PySetDelay(PyObject* self, PyObject* args, PyObject* return NULL; } m_delay = delay; - Py_Return; + Py_RETURN_NONE; } const char SCA_DelaySensor::SetDuration_doc[] = @@ -233,7 +233,7 @@ PyObject* SCA_DelaySensor::PySetDuration(PyObject* self, PyObject* args, PyObjec return NULL; } m_duration = duration; - Py_Return; + Py_RETURN_NONE; } const char SCA_DelaySensor::SetRepeat_doc[] = @@ -250,7 +250,7 @@ PyObject* SCA_DelaySensor::PySetRepeat(PyObject* self, PyObject* args, PyObject* return NULL; } m_repeat = (repeat != 0); - Py_Return; + Py_RETURN_NONE; } const char SCA_DelaySensor::GetDelay_doc[] = diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 70938db7c3d..49d39f75814 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -324,7 +324,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* self, m_Execute_Ueber_Priority = priority; - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 73475b018fc..e8a072f4c46 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -264,7 +264,7 @@ PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyOb int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_pos_pulsemode = PyArgToBool(pyarg); - Py_Return; + Py_RETURN_NONE; } /** @@ -303,7 +303,7 @@ PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject* }; m_pulse_frequency = pulse_frequencyArg; - Py_Return; + Py_RETURN_NONE; } @@ -326,7 +326,7 @@ PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwd int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_invert = PyArgToBool(pyarg); - Py_Return; + Py_RETURN_NONE; } const char SCA_ISensor::GetLevel_doc[] = @@ -352,7 +352,7 @@ PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_level = PyArgToBool(pyarg); - Py_Return; + Py_RETURN_NONE; } const char SCA_ISensor::GetUseNegPulseMode_doc[] = @@ -375,7 +375,7 @@ PyObject* SCA_ISensor::PySetUseNegPulseMode(PyObject* self, PyObject* args, PyOb int pyarg = 0; if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; } m_neg_pulsemode = PyArgToBool(pyarg); - Py_Return; + Py_RETURN_NONE; } //<------Deprecated @@ -385,7 +385,7 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, "\tThe sensor is put in its initial state as if it was just activated.\n") { Init(); - Py_Return; + Py_RETURN_NONE; } /* ----------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index 0edc41bef7b..324e5eae98a 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -577,7 +577,7 @@ PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject* /* anything. It's up to the user to provide a sensible number. */ m_hotkey = keyCode; - Py_Return; + Py_RETURN_NONE; } /** 3. GetHold1 : set the first bucky bit */ @@ -609,7 +609,7 @@ PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObjec /* anything. It's up to the user to provide a sensible number. */ m_qual = keyCode; - Py_Return; + Py_RETURN_NONE; } /** 5. GetHold2 : get the second bucky bit */ @@ -641,7 +641,7 @@ PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObjec /* anything. It's up to the user to provide a sensible number. */ m_qual2 = keyCode; - Py_Return; + Py_RETURN_NONE; } @@ -682,7 +682,7 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, P if (index>0) return resultlist; } - Py_Return; + Py_RETURN_NONE; } @@ -725,7 +725,7 @@ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); if (index > 0) return resultlist; } - Py_Return; + Py_RETURN_NONE; } //<---- Deprecated @@ -770,7 +770,7 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, return PyInt_FromLong(inevent.m_status); } - Py_Return; + Py_RETURN_NONE; } /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 73f784b7e92..4f4d62f13b9 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -292,7 +292,7 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, return PyInt_FromLong(event.m_status); } - Py_Return; + Py_RETURN_NONE; } /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index 644b82a92bf..c9ace081bae 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -298,7 +298,7 @@ PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, Py } prop->Release(); - Py_Return; + Py_RETURN_NONE; } /* 2. getProperty */ @@ -328,7 +328,7 @@ PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObj if (valArg) m_exprtxt = valArg; - Py_Return; + Py_RETURN_NONE; } /* 4. getValue */ diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 10d49769162..d683c8bb3e7 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -397,7 +397,7 @@ PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject m_checktype = typeArg; } - Py_Return; + Py_RETURN_NONE; } /* 3. getProperty */ @@ -434,7 +434,7 @@ PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyOb ; /* error: bad property name */ } prop->Release(); - Py_Return; + Py_RETURN_NONE; } /* 5. getValue */ @@ -470,7 +470,7 @@ PyObject* SCA_PropertySensor::PySetValue(PyObject* self, PyObject* args, PyObjec m_checkpropval = oldval; return NULL; } - Py_Return; + Py_RETURN_NONE; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 7aa25d22b3f..d6c73f21f37 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -413,7 +413,7 @@ PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject m_base->SetSeed(seedArg); - Py_Return; + Py_RETURN_NONE; } /* 2. getSeed */ const char SCA_RandomActuator::GetSeed_doc[] = @@ -478,7 +478,7 @@ PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyOb } prop->Release(); - Py_Return; + Py_RETURN_NONE; } /* 10. getProperty */ const char SCA_RandomActuator::GetProperty_doc[] = @@ -506,7 +506,7 @@ PyObject* SCA_RandomActuator::PySetBoolConst(PyObject* self, m_distribution = KX_RANDOMACT_BOOL_CONST; m_parameter1 = (paraArg) ? 1.0 : 0.0; - Py_Return; + Py_RETURN_NONE; } /* 12. setBoolUniform, */ const char SCA_RandomActuator::SetBoolUniform_doc[] = @@ -518,7 +518,7 @@ PyObject* SCA_RandomActuator::PySetBoolUniform(PyObject* self, /* no args */ m_distribution = KX_RANDOMACT_BOOL_UNIFORM; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 13. setBoolBernouilli, */ const char SCA_RandomActuator::SetBoolBernouilli_doc[] = @@ -536,7 +536,7 @@ PyObject* SCA_RandomActuator::PySetBoolBernouilli(PyObject* self, m_distribution = KX_RANDOMACT_BOOL_BERNOUILLI; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 14. setIntConst,*/ const char SCA_RandomActuator::SetIntConst_doc[] = @@ -554,7 +554,7 @@ PyObject* SCA_RandomActuator::PySetIntConst(PyObject* self, m_distribution = KX_RANDOMACT_INT_CONST; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 15. setIntUniform,*/ const char SCA_RandomActuator::SetIntUniform_doc[] = @@ -575,7 +575,7 @@ PyObject* SCA_RandomActuator::PySetIntUniform(PyObject* self, m_parameter1 = paraArg1; m_parameter2 = paraArg2; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 16. setIntPoisson, */ const char SCA_RandomActuator::SetIntPoisson_doc[] = @@ -595,7 +595,7 @@ PyObject* SCA_RandomActuator::PySetIntPoisson(PyObject* self, m_distribution = KX_RANDOMACT_INT_POISSON; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 17. setFloatConst,*/ const char SCA_RandomActuator::SetFloatConst_doc[] = @@ -613,7 +613,7 @@ PyObject* SCA_RandomActuator::PySetFloatConst(PyObject* self, m_distribution = KX_RANDOMACT_FLOAT_CONST; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 18. setFloatUniform, */ const char SCA_RandomActuator::SetFloatUniform_doc[] = @@ -634,7 +634,7 @@ PyObject* SCA_RandomActuator::PySetFloatUniform(PyObject* self, m_parameter1 = paraArg1; m_parameter2 = paraArg2; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 19. setFloatNormal, */ const char SCA_RandomActuator::SetFloatNormal_doc[] = @@ -655,7 +655,7 @@ PyObject* SCA_RandomActuator::PySetFloatNormal(PyObject* self, m_parameter1 = paraArg1; m_parameter2 = paraArg2; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* 20. setFloatNegativeExponential, */ const char SCA_RandomActuator::SetFloatNegativeExponential_doc[] = @@ -674,7 +674,7 @@ PyObject* SCA_RandomActuator::PySetFloatNegativeExponential(PyObject* self, m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL; m_parameter1 = paraArg; enforceConstraints(); - Py_Return; + Py_RETURN_NONE; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 5a1bd10e044..5354c120f52 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -209,7 +209,7 @@ PyObject* SCA_RandomSensor::PySetSeed(PyObject* self, PyObject* args, PyObject* m_basegenerator->SetSeed(seedArg); - Py_Return; + Py_RETURN_NONE; } /* 2. getSeed */ diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 0c57b2d03a5..2a4a74d5b90 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -796,7 +796,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProg if(mShader !=0 && mOk ) { // already set... - Py_Return; + Py_RETURN_NONE; } char *v,*f; int apply=0; @@ -807,12 +807,12 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProg if( LinkProgram() ) { glUseProgramObjectARB( mShader ); mUse = apply!=0; - Py_Return; + Py_RETURN_NONE; } vertProg = 0; fragProg = 0; mUse = 0; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -827,7 +827,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" ) mShader = 0; mOk = 0; mUse = 0; - Py_Return; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" ) @@ -871,7 +871,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()") MEM_freeN(logInf); logInf=0; } - Py_Return; + Py_RETURN_NONE; } @@ -912,7 +912,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass ) return NULL; mPass = 1; - Py_Return; + Py_RETURN_NONE; } /// access functions @@ -935,7 +935,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) SetUniform( loc, (float)value ); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -959,7 +959,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)") SetUniform(loc, array, 2); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -983,7 +983,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") SetUniform(loc, array, 3); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -1008,7 +1008,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) " SetUniform(loc, array, 4); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1032,7 +1032,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" ) SetUniform(loc, (int)value); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1056,7 +1056,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)") SetUniform(loc, array, 2); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1081,7 +1081,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") SetUniform(loc, array, 3); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1104,7 +1104,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) " SetUniform(loc, array, 4); #endif } - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1144,7 +1144,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis #else SetUniform(loc, array2, 2); #endif - Py_Return; + Py_RETURN_NONE; } break; case 3: { @@ -1154,7 +1154,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis #else SetUniform(loc, array3, 3); #endif - Py_Return; + Py_RETURN_NONE; }break; case 4: { @@ -1164,7 +1164,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis #else SetUniform(loc, array4, 4); #endif - Py_Return; + Py_RETURN_NONE; }break; default: { @@ -1212,7 +1212,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 #else SetUniform(loc, array2, 2); #endif - Py_Return; + Py_RETURN_NONE; } break; case 3: { @@ -1223,7 +1223,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 #else SetUniform(loc, array3, 3); #endif - Py_Return; + Py_RETURN_NONE; }break; case 4: { @@ -1234,7 +1234,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 #else SetUniform(loc, array4, 4); #endif - Py_Return; + Py_RETURN_NONE; }break; default: { @@ -1282,7 +1282,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, #else SetUniform(loc,mat,(transp!=0)); #endif - Py_Return; + Py_RETURN_NONE; } } } @@ -1323,7 +1323,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3, #else SetUniform(loc,mat,(transp!=0)); #endif - Py_Return; + Py_RETURN_NONE; } } @@ -1346,7 +1346,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" ) mAttr=SHD_TANGENT; glUseProgramObjectARB(mShader); glBindAttribLocationARB(mShader, mAttr, "Tangent"); - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -1376,7 +1376,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" ) } if(defined) { - Py_Return; + Py_RETURN_NONE; } BL_DefUniform *uni = new BL_DefUniform(); @@ -1384,7 +1384,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" ) uni->mType = nloc; uni->mFlag = 0; mPreDef.push_back(uni); - Py_Return; + Py_RETURN_NONE; } } return NULL; diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp index a332295ad72..31f1d2dd3ee 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp @@ -162,7 +162,7 @@ PyObject* KX_NetworkMessageActuator::PySetToPropName( return NULL; } - Py_Return; + Py_RETURN_NONE; } // 2. SetSubject @@ -180,7 +180,7 @@ PyObject* KX_NetworkMessageActuator::PySetSubject( return NULL; } - Py_Return; + Py_RETURN_NONE; } // 3. SetBodyType @@ -198,7 +198,7 @@ PyObject* KX_NetworkMessageActuator::PySetBodyType( return NULL; } - Py_Return; + Py_RETURN_NONE; } // 4. SetBody @@ -216,6 +216,6 @@ PyObject* KX_NetworkMessageActuator::PySetBody( return NULL; } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 83148ea9a2b..5fa19924267 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -790,7 +790,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") spit("Fragment shaders not supported"); mModified = true; - Py_Return; + Py_RETURN_NONE; } if( !GLEW_ARB_vertex_shader) { @@ -798,14 +798,14 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") spit("Vertex shaders not supported"); mModified = true; - Py_Return; + Py_RETURN_NONE; } if(!GLEW_ARB_shader_objects) { if(!mModified) spit("GLSL not supported"); mModified = true; - Py_Return; + Py_RETURN_NONE; } else { // returns Py_None on error @@ -838,7 +838,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") } } } - Py_Return; + Py_RETURN_NONE; } PyErr_Format(PyExc_ValueError, "GLSL Error"); return NULL; @@ -910,7 +910,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.sr return NULL; } mUserDefBlend = true; - Py_Return; + Py_RETURN_NONE; } return NULL; } diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp index 44d073193b1..7d238e28add 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.cpp +++ b/source/gameengine/Ketsji/KX_CDActuator.cpp @@ -210,7 +210,7 @@ PyObject* KX_CDActuator::_getattr(const char *attr) PyObject* KX_CDActuator::PyStartCD(PyObject* self, PyObject* args, PyObject* kwds) { SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); - Py_Return; + Py_RETURN_NONE; } @@ -218,7 +218,7 @@ PyObject* KX_CDActuator::PyStartCD(PyObject* self, PyObject* args, PyObject* kwd PyObject* KX_CDActuator::PyPauseCD(PyObject* self, PyObject* args, PyObject* kwds) { SND_CDObject::Instance()->SetPlaystate(SND_MUST_PAUSE); - Py_Return; + Py_RETURN_NONE; } @@ -226,7 +226,7 @@ PyObject* KX_CDActuator::PyPauseCD(PyObject* self, PyObject* args, PyObject* kwd PyObject* KX_CDActuator::PyStopCD(PyObject* self, PyObject* args, PyObject* kwds) { SND_CDObject::Instance()->SetPlaystate(SND_MUST_STOP); - Py_Return; + Py_RETURN_NONE; } @@ -239,7 +239,7 @@ PyObject* KX_CDActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwd SND_CDObject::Instance()->SetGain(gain); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 809bcdba8c9..043070ee207 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -812,7 +812,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, setProjectionMatrix, if (PyMatTo(pymat, mat)) { SetProjectionMatrix(mat); - Py_Return; + Py_RETURN_NONE; } } @@ -837,7 +837,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, enableViewport, return NULL; } - Py_Return; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC(KX_Camera, setViewport, @@ -851,7 +851,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, setViewport, } else { return NULL; } - Py_Return; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC(KX_Camera, setOnTop, @@ -863,5 +863,5 @@ KX_PYMETHODDEF_DOC(KX_Camera, setOnTop, scene = KX_GetActiveScene(); MT_assert(scene); scene->SetCameraOnTop(this); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 9ff9c545f2c..3e93745d888 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -126,7 +126,7 @@ protected: void ExtractFrustumSphere(); public: - typedef enum { INSIDE, INTERSECT, OUTSIDE } ; + enum { INSIDE, INTERSECT, OUTSIDE } ; KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, PyTypeObject *T = &Type); virtual ~KX_Camera(); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index dc2c4c4b414..65f3aea12f9 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -530,7 +530,7 @@ PyObject* KX_CameraActuator::PySetMin(PyObject* self, if(PyArg_ParseTuple(args,"f", &min)) { m_minHeight = min; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -558,7 +558,7 @@ PyObject* KX_CameraActuator::PySetMax(PyObject* self, if(PyArg_ParseTuple(args,"f", &max)) { m_maxHeight = max; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -586,7 +586,7 @@ PyObject* KX_CameraActuator::PySetHeight(PyObject* self, if(PyArg_ParseTuple(args,"f", &height)) { m_height = height; - Py_Return; + Py_RETURN_NONE; } return NULL; } @@ -604,7 +604,7 @@ PyObject* KX_CameraActuator::PySetXY(PyObject* self, if(PyArg_ParseTuple(args,"i", &value)) { m_x = value != 0; - Py_Return; + Py_RETURN_NONE; } return NULL; } diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index 5c08bdc94a3..c0d802a9cf9 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -633,7 +633,7 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self, m_posDampTime = dampArg; if (m_posDampTime < 0) m_posDampTime = 0; - Py_Return; + Py_RETURN_NONE; } /* 3. getDamp */ const char KX_ConstraintActuator::GetDamp_doc[] = @@ -660,7 +660,7 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self, m_rotDampTime = dampArg; if (m_rotDampTime < 0) m_rotDampTime = 0; - Py_Return; + Py_RETURN_NONE; } /* 3. getRotDamp */ const char KX_ConstraintActuator::GetRotDamp_doc[] = @@ -695,7 +695,7 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self, } m_refDirection = dir/len; - Py_Return; + Py_RETURN_NONE; } /* 3. getDirection */ const char KX_ConstraintActuator::GetDirection_doc[] = @@ -730,7 +730,7 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self, m_option = option; - Py_Return; + Py_RETURN_NONE; } /* 3. getOption */ const char KX_ConstraintActuator::GetOption_doc[] = @@ -759,7 +759,7 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self, t = 0; m_activeTime = t; - Py_Return; + Py_RETURN_NONE; } /* 3. getTime */ const char KX_ConstraintActuator::GetTime_doc[] = @@ -789,7 +789,7 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self, m_property[sizeof(m_property)-1] = 0; } - Py_Return; + Py_RETURN_NONE; } /* 3. getProperty */ const char KX_ConstraintActuator::GetProperty_doc[] = @@ -829,7 +829,7 @@ PyObject* KX_ConstraintActuator::PySetMin(PyObject* self, break; } - Py_Return; + Py_RETURN_NONE; } /* 5. getDistance */ const char KX_ConstraintActuator::GetDistance_doc[] = @@ -874,7 +874,7 @@ PyObject* KX_ConstraintActuator::PySetMax(PyObject* self, break; } - Py_Return; + Py_RETURN_NONE; } /* 7. getRayLength */ const char KX_ConstraintActuator::GetRayLength_doc[] = @@ -918,7 +918,7 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self, if (IsValidMode((KX_CONSTRAINTTYPE)locrotArg)) m_locrot = locrotArg; - Py_Return; + Py_RETURN_NONE; } /* 9. getLimit */ const char KX_ConstraintActuator::GetLimit_doc[] = diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index a8b4e0d7d2c..2387dcdef3a 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -270,7 +270,7 @@ PyObject* KX_GameActuator::PySetFile(PyObject* self, PyObject* args, PyObject* k m_filename = STR_String(new_file); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 521fd317305..7d785f07ed2 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -521,7 +521,7 @@ KX_GameObject::UpdateMaterialData( { KX_BlenderMaterial *m = static_cast(poly); - if (matname_hash == NULL) + if (matname_hash == 0) { 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) diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index a67fbe55c37..ca8419666b5 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -503,7 +503,7 @@ PyObject* KX_IpoActuator::PySet(PyObject* self, ; /* error */ } - Py_Return; + Py_RETURN_NONE; } /* set property ----------------------------------------------------------- */ @@ -523,7 +523,7 @@ PyObject* KX_IpoActuator::PySetProperty(PyObject* self, m_propname = propertyName; - Py_Return; + Py_RETURN_NONE; } /* 4. setStart: */ @@ -541,7 +541,7 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self, m_startframe = startArg; - Py_Return; + Py_RETURN_NONE; } /* 5. getStart: */ const char KX_IpoActuator::GetStart_doc[] = @@ -566,7 +566,7 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self, m_endframe = endArg; - Py_Return; + Py_RETURN_NONE; } /* 7. getEnd: */ const char KX_IpoActuator::GetEnd_doc[] = @@ -594,7 +594,7 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, if (m_ipo_as_force) m_ipo_add = false; - Py_Return; + Py_RETURN_NONE; } /* 7. getIpoAsForce: */ const char KX_IpoActuator::GetIpoAsForce_doc[] = @@ -622,7 +622,7 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self, if (m_ipo_add) m_ipo_as_force = false; - Py_Return; + Py_RETURN_NONE; } /* 7. getIpoAsForce: */ const char KX_IpoActuator::GetIpoAdd_doc[] = @@ -651,7 +651,7 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self, m_type = (IpoActType) typeArg; } - Py_Return; + Py_RETURN_NONE; } /* 9. getType: */ const char KX_IpoActuator::GetType_doc[] = @@ -679,7 +679,7 @@ PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self, m_ipo_local = PyArgToBool(boolArg); - Py_Return; + Py_RETURN_NONE; } /* 11. getForceIpoActsLocal: */ const char KX_IpoActuator::GetForceIpoActsLocal_doc[] = diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 3dd70cbb1b8..bd15d3cffbe 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -347,7 +347,7 @@ PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self, { return m_hitObject->AddRef(); } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index e04f73a65e5..9a620998538 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -365,7 +365,7 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self, m_force.setValue(vecArg); m_bitLocalFlag.Force = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 4. getTorque */ @@ -394,7 +394,7 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, m_torque.setValue(vecArg); m_bitLocalFlag.Torque = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 6. getDLoc */ @@ -423,7 +423,7 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, m_dloc.setValue(vecArg); m_bitLocalFlag.DLoc = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 8. getDRot */ @@ -452,7 +452,7 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, m_drot.setValue(vecArg); m_bitLocalFlag.DRot = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 10. getLinearVelocity */ @@ -480,7 +480,7 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, m_linear_velocity.setValue(vecArg); m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } @@ -508,7 +508,7 @@ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, m_angular_velocity.setValue(vecArg); m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle); UpdateFuzzyFlags(); - Py_Return; + Py_RETURN_NONE; } /* 13. setDamping */ @@ -520,7 +520,7 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, return NULL; } m_damping = damping; - Py_Return; + Py_RETURN_NONE; } /* 13. getVelocityDamping */ @@ -551,7 +551,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, m_drot[0] = vecArg[0]; m_dloc[0] = vecArg[1]; m_bitLocalFlag.Torque = PyArgToBool(bToggle); - Py_Return; + Py_RETURN_NONE; } /* 6. getForceLimitY */ @@ -578,7 +578,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, m_drot[1] = vecArg[0]; m_dloc[1] = vecArg[1]; m_bitLocalFlag.DLoc = PyArgToBool(bToggle); - Py_Return; + Py_RETURN_NONE; } /* 6. getForceLimitZ */ @@ -605,7 +605,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, m_drot[2] = vecArg[0]; m_dloc[2] = vecArg[1]; m_bitLocalFlag.DRot = PyArgToBool(bToggle); - Py_Return; + Py_RETURN_NONE; } /* 4. getPID */ @@ -629,7 +629,7 @@ PyObject* KX_ObjectActuator::PySetPID(PyObject* self, return NULL; } m_torque.setValue(vecArg); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 9c792a3e673..52c5b013e65 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -204,15 +204,15 @@ PyParentObject KX_PolygonMaterial::Parents[] = { PyObject* KX_PolygonMaterial::_getattr(const char *attr) { - if (attr == "texture") + if (!strcmp(attr, "texture")) return PyString_FromString(m_texturename.ReadPtr()); - if (attr == "material") + if (!strcmp(attr, "material")) return PyString_FromString(m_materialname.ReadPtr()); - if (attr == "tface") + if (!strcmp(attr, "tface")) return PyCObject_FromVoidPtr(m_tface, NULL); - if (attr == "gl_texture") + if (!strcmp(attr, "gl_texture")) { Image *ima = m_tface->tpage; int bind = 0; @@ -222,32 +222,32 @@ PyObject* KX_PolygonMaterial::_getattr(const char *attr) return PyInt_FromLong(bind); } - if (attr == "tile") + if (!strcmp(attr, "tile")) return PyInt_FromLong(m_tile); - if (attr == "tilexrep") + if (!strcmp(attr, "tilexrep")) return PyInt_FromLong(m_tilexrep); - if (attr == "tileyrep") + if (!strcmp(attr, "tileyrep")) return PyInt_FromLong(m_tileyrep); - if (attr == "drawingmode") + if (!strcmp(attr, "drawingmode")) return PyInt_FromLong(m_drawingmode); - if (attr == "transparent") + if (!strcmp(attr, "transparent")) return PyInt_FromLong(m_alpha); - if (attr == "zsort") + if (!strcmp(attr, "zsort")) return PyInt_FromLong(m_zsort); - if (attr == "lightlayer") + if (!strcmp(attr, "lightlayer")) return PyInt_FromLong(m_lightlayer); - if (attr == "triangle") + if (!strcmp(attr, "triangle")) // deprecated, triangle/quads shouldn't have been a material property return 0; - if (attr == "diffuse") + if (!strcmp(attr, "diffuse")) return PyObjectFrom(m_diffuse); - if (attr == "shininess") + if (!strcmp(attr, "shininess")) return PyFloat_FromDouble(m_shininess); - if (attr == "specular") + if (!strcmp(attr, "specular")) return PyObjectFrom(m_specular); - if (attr == "specularity") + if (!strcmp(attr, "specularity")) return PyFloat_FromDouble(m_specularity); _getattr_up(PyObjectPlus); @@ -258,13 +258,13 @@ int KX_PolygonMaterial::_setattr(const char *attr, PyObject *pyvalue) if (PyFloat_Check(pyvalue)) { float value = PyFloat_AsDouble(pyvalue); - if (attr == "shininess") + if (!strcmp(attr, "shininess")) { m_shininess = value; return 0; } - if (attr == "specularity") + if (!strcmp(attr, "specularity")) { m_specularity = value; return 0; @@ -274,50 +274,50 @@ int KX_PolygonMaterial::_setattr(const char *attr, PyObject *pyvalue) if (PyInt_Check(pyvalue)) { int value = PyInt_AsLong(pyvalue); - if (attr == "tile") + if (!strcmp(attr, "tile")) { m_tile = value; return 0; } - if (attr == "tilexrep") + if (!strcmp(attr, "tilexrep")) { m_tilexrep = value; return 0; } - if (attr == "tileyrep") + if (!strcmp(attr, "tileyrep")) { m_tileyrep = value; return 0; } - if (attr == "drawingmode") + if (!strcmp(attr, "drawingmode")) { m_drawingmode = value; return 0; } - if (attr == "transparent") + if (!strcmp(attr, "transparent")) { m_alpha = value; return 0; } - if (attr == "zsort") + if (!strcmp(attr, "zsort")) { m_zsort = value; return 0; } - if (attr == "lightlayer") + if (!strcmp(attr, "lightlayer")) { m_lightlayer = value; return 0; } // This probably won't work... - if (attr == "triangle") + if (!strcmp(attr, "triangle")) { // deprecated, triangle/quads shouldn't have been a material property return 0; @@ -331,13 +331,13 @@ int KX_PolygonMaterial::_setattr(const char *attr, PyObject *pyvalue) MT_Vector3 value; if (PyVecTo(pyvalue, value)) { - if (attr == "diffuse") + if (!strcmp(attr, "diffuse")) { m_diffuse = value; return 0; } - if (attr == "specular") + if (!strcmp(attr, "specular")) { m_specular = value; return 0; @@ -354,12 +354,12 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(mat PyObject *material; if (PyArg_ParseTuple(args, "O", &material)) { - if (m_pymaterial) + if (m_pymaterial) { Py_DECREF(m_pymaterial); - + } m_pymaterial = material; Py_INCREF(m_pymaterial); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -375,7 +375,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rast Image *ima = (Image*)tface->tpage; GPU_update_image_time(ima, rasty->GetTime()); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -388,7 +388,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)") { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); GPU_set_tpage(tface); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -404,7 +404,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)") if (rasty && cachingInfo) { DefaultActivate(rasty, *cachingInfo); - Py_Return; + Py_RETURN_NONE; } } diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index 22611c444df..b8ebce28814 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -353,7 +353,7 @@ PyObject* KX_RaySensor::PyGetHitObject(PyObject* self, { return m_hitObject->AddRef(); } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 4c331b2c9d6..017ab5d6c97 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -210,8 +210,7 @@ PyObject* KX_SCA_AddObjectActuator::_getattr(const char *attr) if (!strcmp(attr, "object")) { if (!m_OriginalObject) Py_RETURN_NONE; else return m_OriginalObject->AddRef(); - } - else if (attr == "objectLastCreated") { + } else if (!strcmp(attr, "objectLastCreated")) { if (!m_OriginalObject) Py_RETURN_NONE; else return m_lastCreatedObject->AddRef(); } diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index e8d9a7f07c8..1aba05c1d83 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -115,7 +115,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation, return NULL; } m_dyn_operation= dyn_operation; - Py_Return; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index a5f49f97d4b..8e33177cf3a 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -295,7 +295,7 @@ PyObject* KX_SceneActuator::PySetUseRestart(PyObject* self, m_restart = boolArg != 0; - Py_Return; + Py_RETURN_NONE; } @@ -333,7 +333,7 @@ PyObject* KX_SceneActuator::PySetScene(PyObject* self, /* Scene switch is done by name. */ m_nextSceneName = scene_name; - Py_Return; + Py_RETURN_NONE; } @@ -368,7 +368,7 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, m_camera = (KX_Camera*) cam; if (m_camera) m_camera->RegisterActuator(this); - Py_Return; + Py_RETURN_NONE; } PyErr_Clear(); @@ -388,7 +388,7 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, m_camera->RegisterActuator(this); } - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index ba60ea81739..37604518486 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -302,7 +302,7 @@ PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObje if (!PyArg_ParseTuple(args, "s", &soundName)) return NULL; - Py_Return; + Py_RETURN_NONE; } @@ -332,7 +332,7 @@ PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObjec // To start the sound you must activate the actuator. // This function is to restart the sound. m_soundObject->StartSound(); - Py_Return; + Py_RETURN_NONE; } @@ -342,7 +342,7 @@ PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObjec if (m_soundObject) // unfortunately, openal does not implement pause correctly, it is equivalent to a stop m_soundObject->PauseSound(); - Py_Return; + Py_RETURN_NONE; } @@ -351,7 +351,7 @@ PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject { if (m_soundObject) m_soundObject->StopSound(); - Py_Return; + Py_RETURN_NONE; } @@ -365,7 +365,7 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* if (m_soundObject) m_soundObject->SetGain(gain); - Py_Return; + Py_RETURN_NONE; } @@ -389,7 +389,7 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* if (m_soundObject) m_soundObject->SetPitch(pitch); - Py_Return; + Py_RETURN_NONE; } @@ -413,7 +413,7 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P if (m_soundObject) m_soundObject->SetRollOffFactor(rollofffactor); - Py_Return; + Py_RETURN_NONE; } @@ -437,7 +437,7 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec if (m_soundObject) m_soundObject->SetLoopMode(looping); - Py_Return; + Py_RETURN_NONE; } @@ -465,7 +465,7 @@ PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObje if (m_soundObject) m_soundObject->SetPosition(pos); - Py_Return; + Py_RETURN_NONE; } @@ -483,7 +483,7 @@ PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObje if (m_soundObject) m_soundObject->SetVelocity(vel); - Py_Return; + Py_RETURN_NONE; } @@ -507,7 +507,7 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO if (m_soundObject) m_soundObject->SetOrientation(ori); - Py_Return; + Py_RETURN_NONE; } PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* kwds) @@ -523,7 +523,7 @@ PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* m_type = (KX_SOUNDACT_TYPE) typeArg; } - Py_Return; + Py_RETURN_NONE; } PyObject* KX_SoundActuator::PyGetType(PyObject* self, PyObject* args, PyObject* kwds) diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index 7237d6ced1e..cd5c5d29ab1 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -173,7 +173,7 @@ KX_StateActuator::PySetOperation(PyObject* self, m_operation = oper; - Py_Return; + Py_RETURN_NONE; } /* set mask ---------------------------------------------------------- */ @@ -198,7 +198,7 @@ KX_StateActuator::PySetMask(PyObject* self, m_mask = mask; - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 6528ec466ce..117adb44742 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -291,7 +291,7 @@ PyObject* KX_TouchSensor::PySetProperty(PyObject* self, } prop->Release(); - Py_Return; + Py_RETURN_NONE; } /* 2. getProperty */ const char KX_TouchSensor::GetProperty_doc[] = @@ -318,7 +318,7 @@ PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self, { return m_hitObject->AddRef(); } - Py_Return; + Py_RETURN_NONE; } const char KX_TouchSensor::GetHitObjectList_doc[] = @@ -402,7 +402,7 @@ PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject* args, PyO m_bFindMaterial = pulseArg != 0; - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index f9f804cfc66..89dfc8e57ad 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -480,9 +480,8 @@ PyObject* KX_TrackToActuator::_getattr(const char *attr) _getattr_up(SCA_IActuator); } -int KX_TrackToActuator::_setattr(const char *attr, PyObject* value) { - int ret; - +int KX_TrackToActuator::_setattr(const char *attr, PyObject* value) +{ if (!strcmp(attr, "object")) { KX_GameObject *gameobj; @@ -570,7 +569,7 @@ PyObject* KX_TrackToActuator::PySetTime(PyObject* self, PyObject* args, PyObject m_time= timeArg; - Py_Return; + Py_RETURN_NONE; } @@ -614,7 +613,7 @@ PyObject* KX_TrackToActuator::PySetUse3D(PyObject* self, PyObject* args, PyObjec m_allow3D = !(boolArg == 0); - Py_Return; + Py_RETURN_NONE; } /* eof */ diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index eddd110ee81..ab102ee547a 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -328,7 +328,7 @@ PyObject* KX_VertexProxy::PySetXYZ(PyObject*, { m_vertex->SetXYZ(vec); m_mesh->SetMeshModified(true); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -350,7 +350,7 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject*, { m_vertex->SetNormal(vec); m_mesh->SetMeshModified(true); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -374,7 +374,7 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject*, { m_vertex->SetRGBA(MT_Vector4(r, g, b, a)); m_mesh->SetMeshModified(true); - Py_Return; + Py_RETURN_NONE; } PyErr_Clear(); @@ -383,7 +383,7 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject*, { m_vertex->SetRGBA(rgba); m_mesh->SetMeshModified(true); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -406,7 +406,7 @@ PyObject* KX_VertexProxy::PySetUV(PyObject*, { m_vertex->SetUV(vec); m_mesh->SetMeshModified(true); - Py_Return; + Py_RETURN_NONE; } return NULL; @@ -434,7 +434,7 @@ PyObject* KX_VertexProxy::PySetUV2(PyObject*, m_vertex->SetUnit(unit); m_vertex->SetUV2(vec); m_mesh->SetMeshModified(true); - Py_Return; + Py_RETURN_NONE; } } return NULL; diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index 0a4aaa0dffe..ca89a63de62 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -152,7 +152,7 @@ KX_VisibilityActuator::PySetVisible(PyObject* self, m_visible = PyArgToBool(vis); - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h index 2326bdee523..3d8eef2bae0 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h @@ -46,7 +46,7 @@ #include "SM_Object.h" -typedef enum +enum { FH_RESPONSE, SENSOR_RESPONSE, /* Touch Sensors */ diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h index 09126264dcc..c5cf92b553a 100644 --- a/source/gameengine/Physics/common/PHY_DynamicTypes.h +++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h @@ -36,7 +36,7 @@ struct PHY__Vector3 }; //typedef float PHY__Vector3[4]; -typedef enum +enum { PHY_FH_RESPONSE, PHY_SENSOR_RESPONSE, /* Touch Sensors */ From 570b48aae6f074ed19a3fc58b8e2a34b38123a49 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 22 Feb 2009 10:22:49 +0000 Subject: [PATCH 198/252] BGE Py API print filename:line with ShowDeprecationWarning(). Typo in scripttemplate_gamelogic.py removed 2 unneeded typedefs --- intern/SoundSystem/openal/SND_OpenALDevice.h | 2 +- intern/SoundSystem/sdl/SND_SDLCDDevice.h | 2 +- release/scripts/scripttemplate_gamelogic.py | 5 ++- source/gameengine/Expressions/Value.cpp | 37 +++++++++++++++++++- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.h b/intern/SoundSystem/openal/SND_OpenALDevice.h index b8c64762a56..a7b97cc314f 100644 --- a/intern/SoundSystem/openal/SND_OpenALDevice.h +++ b/intern/SoundSystem/openal/SND_OpenALDevice.h @@ -32,7 +32,7 @@ #include "SND_AudioDevice.h" #include "SoundDefines.h" -typedef struct SDL_CD; +struct SDL_CD; class SND_OpenALDevice : public SND_AudioDevice { diff --git a/intern/SoundSystem/sdl/SND_SDLCDDevice.h b/intern/SoundSystem/sdl/SND_SDLCDDevice.h index 15cb1975d74..96600d53630 100644 --- a/intern/SoundSystem/sdl/SND_SDLCDDevice.h +++ b/intern/SoundSystem/sdl/SND_SDLCDDevice.h @@ -29,7 +29,7 @@ #ifndef SND_SDLCDDEVICE #define SND_SDLCDDEVICE -typedef struct SDL_CD; +struct SDL_CD; class SND_SDLCDDevice { diff --git a/release/scripts/scripttemplate_gamelogic.py b/release/scripts/scripttemplate_gamelogic.py index 7184d7e424f..01348e86d0a 100644 --- a/release/scripts/scripttemplate_gamelogic.py +++ b/release/scripts/scripttemplate_gamelogic.py @@ -11,6 +11,9 @@ import bpy script_data = \ ''' +# This script must be assigned to a python controller +# where it can access the object that owns it and the sensors/actuators that it connects to. + # GameLogic has been added to the global namespace no need to import # for keyboard event comparison @@ -50,7 +53,7 @@ def main(): 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() + print ' actuator:', actu.getName() # This runs the actuator or turns it off # note that actuators will continue to run unless explicitly turned off. diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index f30dd1a71ed..9b26cda01b3 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -859,7 +859,42 @@ void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings) void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way) { - if (!m_ignore_deprecation_warnings) + if (!m_ignore_deprecation_warnings) { printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way); + + // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno) + + PyObject *getframe, *frame; + PyObject *f_lineno, *f_code, *co_filename; + + getframe = PySys_GetObject("_getframe"); // borrowed + if (getframe) { + frame = PyObject_CallObject(getframe, NULL); + if (frame) { + f_lineno= PyObject_GetAttrString(frame, "f_lineno"); + f_code= PyObject_GetAttrString(frame, "f_code"); + if (f_lineno && f_code) { + co_filename= PyObject_GetAttrString(f_code, "co_filename"); + if (co_filename) { + + printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno)); + + Py_DECREF(f_lineno); + Py_DECREF(f_code); + Py_DECREF(co_filename); + Py_DECREF(frame); + return; + } + } + + Py_XDECREF(f_lineno); + Py_XDECREF(f_code); + Py_DECREF(frame); + } + + } + PyErr_Clear(); + printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n"); + } } From 3408d9022aecee50d7ce01c45962a2c32d7c91da Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 22 Feb 2009 15:02:23 +0000 Subject: [PATCH 199/252] SCons * chop nodes library into smaller parts to have scons/mingw not puke over long command-lines (the texture nodes pushed the limits). --- source/blender/nodes/SConscript | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index 881479387b5..b3bc11ca040 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -2,9 +2,9 @@ Import ('env') sources = env.Glob('intern/*.c') -sources += env.Glob('intern/CMP_nodes/*.c') -sources += env.Glob('intern/SHD_nodes/*.c') -sources += env.Glob('intern/TEX_nodes/*.c') +cmpsources = env.Glob('intern/CMP_nodes/*.c') +shdsources = env.Glob('intern/SHD_nodes/*.c') +texsources = env.Glob('intern/TEX_nodes/*.c') incs = '. ./intern ' incs += '#/intern/guardedalloc ../include ../blenlib ../makesdna' @@ -28,13 +28,6 @@ else: if env['WITH_BF_INTERNATIONAL']: defs += ' WITH_FREETYPE2' -if env['WITH_BF_VERSE']: - defs += ' WITH_VERSE' - incs += ' ' + env['BF_VERSE_INCLUDE'] - -if env['WITH_BF_VERSE']: - defs += ' WITH_VERSE' - if env['WITH_BF_OPENEXR']: defs += ' WITH_OPENEXR' @@ -46,4 +39,7 @@ if env['WITH_BF_QUICKTIME']: defs += ' WITH_QUICKTIME' incs += ' ' + env['BF_QUICKTIME_INC'] -env.BlenderLib ( libname = 'nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core','player'], priority = [65, 20] ) +env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [190] ) +env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [175] ) +env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [175] ) +env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [175] ) From 1c088b454d21bfd55119110fa1dc01d9543c35f8 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 22 Feb 2009 20:44:36 +0000 Subject: [PATCH 200/252] SCons * I accidently broke the scons bit by chopping the node libs into pieces. I forgot that trunk hasn't had the nice scons cleanout I did in Blender 2.5 branch. Now everything should compile again. It took a while because I tried to quickly do the same cleanup, but src/ is just not cooperating, neither is stock mingw (no @commands.txt tempfilemunge goodies) --- source/blender/nodes/CMP_node.h | 116 ++++++++++++++++---------------- source/blender/nodes/SConscript | 8 +-- source/blender/nodes/SHD_node.h | 46 ++++++------- source/blender/nodes/TEX_node.h | 64 +++++++++--------- 4 files changed, 117 insertions(+), 117 deletions(-) diff --git a/source/blender/nodes/CMP_node.h b/source/blender/nodes/CMP_node.h index 020bbdebfa2..84d311b6173 100644 --- a/source/blender/nodes/CMP_node.h +++ b/source/blender/nodes/CMP_node.h @@ -38,71 +38,71 @@ /* ****************** types array for all composite nodes ****************** */ -extern bNodeType cmp_node_rlayers; -extern bNodeType cmp_node_image; -extern bNodeType cmp_node_texture; -extern bNodeType cmp_node_value; -extern bNodeType cmp_node_rgb; -extern bNodeType cmp_node_curve_time; +bNodeType cmp_node_rlayers; +bNodeType cmp_node_image; +bNodeType cmp_node_texture; +bNodeType cmp_node_value; +bNodeType cmp_node_rgb; +bNodeType cmp_node_curve_time; -extern bNodeType cmp_node_composite; -extern bNodeType cmp_node_viewer; -extern bNodeType cmp_node_splitviewer; -extern bNodeType cmp_node_output_file; +bNodeType cmp_node_composite; +bNodeType cmp_node_viewer; +bNodeType cmp_node_splitviewer; +bNodeType cmp_node_output_file; -extern bNodeType cmp_node_curve_rgb; -extern bNodeType cmp_node_mix_rgb; -extern bNodeType cmp_node_hue_sat; -extern bNodeType cmp_node_brightcontrast; -extern bNodeType cmp_node_gamma; -extern bNodeType cmp_node_invert; -extern bNodeType cmp_node_alphaover; -extern bNodeType cmp_node_zcombine; +bNodeType cmp_node_curve_rgb; +bNodeType cmp_node_mix_rgb; +bNodeType cmp_node_hue_sat; +bNodeType cmp_node_brightcontrast; +bNodeType cmp_node_gamma; +bNodeType cmp_node_invert; +bNodeType cmp_node_alphaover; +bNodeType cmp_node_zcombine; -extern bNodeType cmp_node_normal; -extern bNodeType cmp_node_curve_vec; -extern bNodeType cmp_node_map_value; -extern bNodeType cmp_node_normalize; +bNodeType cmp_node_normal; +bNodeType cmp_node_curve_vec; +bNodeType cmp_node_map_value; +bNodeType cmp_node_normalize; -extern bNodeType cmp_node_filter; -extern bNodeType cmp_node_blur; -extern bNodeType cmp_node_dblur; -extern bNodeType cmp_node_bilateralblur; -extern bNodeType cmp_node_vecblur; -extern bNodeType cmp_node_dilateerode; -extern bNodeType cmp_node_defocus; +bNodeType cmp_node_filter; +bNodeType cmp_node_blur; +bNodeType cmp_node_dblur; +bNodeType cmp_node_bilateralblur; +bNodeType cmp_node_vecblur; +bNodeType cmp_node_dilateerode; +bNodeType cmp_node_defocus; -extern bNodeType cmp_node_valtorgb; -extern bNodeType cmp_node_rgbtobw; -extern bNodeType cmp_node_setalpha; -extern bNodeType cmp_node_idmask; -extern bNodeType cmp_node_math; -extern bNodeType cmp_node_seprgba; -extern bNodeType cmp_node_combrgba; -extern bNodeType cmp_node_sephsva; -extern bNodeType cmp_node_combhsva; -extern bNodeType cmp_node_sepyuva; -extern bNodeType cmp_node_combyuva; -extern bNodeType cmp_node_sepycca; -extern bNodeType cmp_node_combycca; -extern bNodeType cmp_node_premulkey; +bNodeType cmp_node_valtorgb; +bNodeType cmp_node_rgbtobw; +bNodeType cmp_node_setalpha; +bNodeType cmp_node_idmask; +bNodeType cmp_node_math; +bNodeType cmp_node_seprgba; +bNodeType cmp_node_combrgba; +bNodeType cmp_node_sephsva; +bNodeType cmp_node_combhsva; +bNodeType cmp_node_sepyuva; +bNodeType cmp_node_combyuva; +bNodeType cmp_node_sepycca; +bNodeType cmp_node_combycca; +bNodeType cmp_node_premulkey; -extern bNodeType cmp_node_diff_matte; -extern bNodeType cmp_node_chroma; -extern bNodeType cmp_node_channel_matte; -extern bNodeType cmp_node_color_spill; -extern bNodeType cmp_node_luma_matte; +bNodeType cmp_node_diff_matte; +bNodeType cmp_node_chroma; +bNodeType cmp_node_channel_matte; +bNodeType cmp_node_color_spill; +bNodeType cmp_node_luma_matte; -extern bNodeType cmp_node_translate; -extern bNodeType cmp_node_rotate; -extern bNodeType cmp_node_scale; -extern bNodeType cmp_node_flip; -extern bNodeType cmp_node_crop; -extern bNodeType cmp_node_displace; -extern bNodeType cmp_node_mapuv; +bNodeType cmp_node_translate; +bNodeType cmp_node_rotate; +bNodeType cmp_node_scale; +bNodeType cmp_node_flip; +bNodeType cmp_node_crop; +bNodeType cmp_node_displace; +bNodeType cmp_node_mapuv; -extern bNodeType cmp_node_glare; -extern bNodeType cmp_node_tonemap; -extern bNodeType cmp_node_lensdist; +bNodeType cmp_node_glare; +bNodeType cmp_node_tonemap; +bNodeType cmp_node_lensdist; #endif diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index b3bc11ca040..b47eebd0811 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -39,7 +39,7 @@ if env['WITH_BF_QUICKTIME']: defs += ' WITH_QUICKTIME' incs += ' ' + env['BF_QUICKTIME_INC'] -env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [190] ) -env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [175] ) -env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [175] ) -env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [175] ) +env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 200, 300] ) +env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) +env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) +env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) diff --git a/source/blender/nodes/SHD_node.h b/source/blender/nodes/SHD_node.h index d75d7c9f568..10af3f162d6 100644 --- a/source/blender/nodes/SHD_node.h +++ b/source/blender/nodes/SHD_node.h @@ -39,29 +39,29 @@ /* the type definitions array */ /* ****************** types array for all shaders ****************** */ -extern bNodeType sh_node_output; -extern bNodeType sh_node_material; -extern bNodeType sh_node_camera; -extern bNodeType sh_node_value; -extern bNodeType sh_node_rgb; -extern bNodeType sh_node_mix_rgb; -extern bNodeType sh_node_valtorgb; -extern bNodeType sh_node_rgbtobw; -extern bNodeType sh_node_texture; -extern bNodeType sh_node_normal; -extern bNodeType sh_node_geom; -extern bNodeType sh_node_mapping; -extern bNodeType sh_node_curve_vec; -extern bNodeType sh_node_curve_rgb; -extern bNodeType sh_node_math; -extern bNodeType sh_node_vect_math; -extern bNodeType sh_node_squeeze; -extern bNodeType node_dynamic_typeinfo; -extern bNodeType sh_node_material_ext; -extern bNodeType sh_node_invert; -extern bNodeType sh_node_seprgb; -extern bNodeType sh_node_combrgb; -extern bNodeType sh_node_hue_sat; +bNodeType sh_node_output; +bNodeType sh_node_material; +bNodeType sh_node_camera; +bNodeType sh_node_value; +bNodeType sh_node_rgb; +bNodeType sh_node_mix_rgb; +bNodeType sh_node_valtorgb; +bNodeType sh_node_rgbtobw; +bNodeType sh_node_texture; +bNodeType sh_node_normal; +bNodeType sh_node_geom; +bNodeType sh_node_mapping; +bNodeType sh_node_curve_vec; +bNodeType sh_node_curve_rgb; +bNodeType sh_node_math; +bNodeType sh_node_vect_math; +bNodeType sh_node_squeeze; +bNodeType node_dynamic_typeinfo; +bNodeType sh_node_material_ext; +bNodeType sh_node_invert; +bNodeType sh_node_seprgb; +bNodeType sh_node_combrgb; +bNodeType sh_node_hue_sat; #endif diff --git a/source/blender/nodes/TEX_node.h b/source/blender/nodes/TEX_node.h index c52fc757507..90e171e9cca 100644 --- a/source/blender/nodes/TEX_node.h +++ b/source/blender/nodes/TEX_node.h @@ -38,40 +38,40 @@ /* ****************** types array for all texture nodes ****************** */ -extern bNodeType tex_node_math; -extern bNodeType tex_node_mix_rgb; -extern bNodeType tex_node_valtorgb; -extern bNodeType tex_node_valtonor; -extern bNodeType tex_node_rgbtobw; -extern bNodeType tex_node_output; -extern bNodeType tex_node_viewer; -extern bNodeType tex_node_checker; -extern bNodeType tex_node_texture; -extern bNodeType tex_node_bricks; -extern bNodeType tex_node_image; -extern bNodeType tex_node_curve_rgb; -extern bNodeType tex_node_curve_time; -extern bNodeType tex_node_invert; -extern bNodeType tex_node_hue_sat; -extern bNodeType tex_node_coord; -extern bNodeType tex_node_distance; +bNodeType tex_node_math; +bNodeType tex_node_mix_rgb; +bNodeType tex_node_valtorgb; +bNodeType tex_node_valtonor; +bNodeType tex_node_rgbtobw; +bNodeType tex_node_output; +bNodeType tex_node_viewer; +bNodeType tex_node_checker; +bNodeType tex_node_texture; +bNodeType tex_node_bricks; +bNodeType tex_node_image; +bNodeType tex_node_curve_rgb; +bNodeType tex_node_curve_time; +bNodeType tex_node_invert; +bNodeType tex_node_hue_sat; +bNodeType tex_node_coord; +bNodeType tex_node_distance; -extern bNodeType tex_node_rotate; -extern bNodeType tex_node_translate; -extern bNodeType tex_node_scale; +bNodeType tex_node_rotate; +bNodeType tex_node_translate; +bNodeType tex_node_scale; -extern bNodeType tex_node_compose; -extern bNodeType tex_node_decompose; +bNodeType tex_node_compose; +bNodeType tex_node_decompose; -extern bNodeType tex_node_proc_voronoi; -extern bNodeType tex_node_proc_blend; -extern bNodeType tex_node_proc_magic; -extern bNodeType tex_node_proc_marble; -extern bNodeType tex_node_proc_clouds; -extern bNodeType tex_node_proc_wood; -extern bNodeType tex_node_proc_musgrave; -extern bNodeType tex_node_proc_noise; -extern bNodeType tex_node_proc_stucci; -extern bNodeType tex_node_proc_distnoise; +bNodeType tex_node_proc_voronoi; +bNodeType tex_node_proc_blend; +bNodeType tex_node_proc_magic; +bNodeType tex_node_proc_marble; +bNodeType tex_node_proc_clouds; +bNodeType tex_node_proc_wood; +bNodeType tex_node_proc_musgrave; +bNodeType tex_node_proc_noise; +bNodeType tex_node_proc_stucci; +bNodeType tex_node_proc_distnoise; #endif From 5488175d0bc79b07fd3fb0f279323b4f33487b5f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 23 Feb 2009 06:41:10 +0000 Subject: [PATCH 201/252] BGE Python API * fixed segfaults in CListValue.index(val) and CListValue.count(val) when the pyTypes could not be converted into a CValue. * added scene.objects to replace scene.getObjectList() * added function names to PyArg_ParseTuple() so errors will include the function names * removed cases of PyArg_ParseTuple(args,"O",&pyobj) where METH_O ensures a single argument. * Made PyObjectFrom use ugly python api rather then Py_BuildValue(), approx %40 speedup for functions that return Python vector and matrix types like ob.orientation. --- source/gameengine/Expressions/ListValue.cpp | 105 +++++------- source/gameengine/Expressions/ListValue.h | 8 +- source/gameengine/Ketsji/KX_Camera.cpp | 119 ++++++------- source/gameengine/Ketsji/KX_Camera.h | 20 +-- source/gameengine/Ketsji/KX_GameObject.cpp | 64 +++---- source/gameengine/Ketsji/KX_GameObject.h | 4 +- source/gameengine/Ketsji/KX_PyMath.cpp | 57 +++++++ source/gameengine/Ketsji/KX_PyMath.h | 14 -- source/gameengine/Ketsji/KX_PythonInit.cpp | 38 ++--- source/gameengine/Ketsji/KX_Scene.cpp | 28 ++-- source/gameengine/Ketsji/KX_Scene.h | 6 +- source/gameengine/Ketsji/KX_VertexProxy.cpp | 175 +++++++++----------- source/gameengine/Ketsji/KX_VertexProxy.h | 20 +-- 13 files changed, 315 insertions(+), 343 deletions(-) diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index b8a8a1a63b2..9acc6ad2cde 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -224,10 +224,10 @@ PyParentObject CListValue::Parents[] = { PyMethodDef CListValue::Methods[] = { - {"append", (PyCFunction)CListValue::sPyappend,METH_VARARGS}, - {"reverse", (PyCFunction)CListValue::sPyreverse,METH_VARARGS}, - {"index", (PyCFunction)CListValue::sPyindex,METH_VARARGS}, - {"count", (PyCFunction)CListValue::sPycount,METH_VARARGS}, + {"append", (PyCFunction)CListValue::sPyappend,METH_O}, + {"reverse", (PyCFunction)CListValue::sPyreverse,METH_NOARGS}, + {"index", (PyCFunction)CListValue::sPyindex,METH_O}, + {"count", (PyCFunction)CListValue::sPycount,METH_O}, {NULL,NULL} //Sentinel }; @@ -403,34 +403,17 @@ void CListValue::MergeList(CListValue *otherlist) -PyObject* CListValue::Pyappend(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* CListValue::Pyappend(PyObject* self, PyObject* value) { - - PyObject* pyobj = NULL; - if (PyArg_ParseTuple(args,"O",&pyobj)) - { - return listvalue_buffer_concat(self,pyobj); - } - else - { - return NULL; - } - - + return listvalue_buffer_concat(self, value); } -PyObject* CListValue::Pyreverse(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* CListValue::Pyreverse(PyObject* self) { std::reverse(m_pValueArray.begin(),m_pValueArray.end()); - Py_RETURN_NONE; - } @@ -452,59 +435,57 @@ bool CListValue::CheckEqual(CValue* first,CValue* second) -PyObject* CListValue::Pyindex(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* CListValue::Pyindex(PyObject* self, PyObject *value) { PyObject* result = NULL; - PyObject* pyobj = NULL; - if (PyArg_ParseTuple(args,"O",&pyobj)) - { - - CValue* checkobj = ConvertPythonToValue(pyobj); - int numelem = GetCount(); - for (int i=0;iRelease(); - } + CValue* checkobj = ConvertPythonToValue(value); + if (checkobj==NULL) + return NULL; /* ConvertPythonToValue sets the error */ + int numelem = GetCount(); + for (int i=0;iRelease(); + + if (result==NULL) { + PyErr_SetString(PyExc_ValueError, "ValueError: list.index(x): x not in CListValue"); + } return result; } -PyObject* CListValue::Pycount(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* CListValue::Pycount(PyObject* self, PyObject* value) { - int numfound = 0; - PyObject* pyobj = NULL; - if (PyArg_ParseTuple(args,"O",&pyobj)) - { - CValue* checkobj = ConvertPythonToValue(pyobj); - int numelem = GetCount(); - for (int i=0;iRelease(); + CValue* checkobj = ConvertPythonToValue(value); + + if (checkobj==NULL) { /* in this case just return that there are no items in the list */ + PyErr_Clear(); + PyInt_FromLong(0); } + int numelem = GetCount(); + for (int i=0;iRelease(); + return PyInt_FromLong(numfound); } diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h index 8c0bd767938..104e3e63283 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/ListValue.h @@ -61,10 +61,10 @@ public: virtual PyObject* _getattr(const char *attr); - KX_PYMETHOD(CListValue,append); - KX_PYMETHOD(CListValue,reverse); - KX_PYMETHOD(CListValue,index); - KX_PYMETHOD(CListValue,count); + KX_PYMETHOD_O(CListValue,append); + KX_PYMETHOD_NOARGS(CListValue,reverse); + KX_PYMETHOD_O(CListValue,index); + KX_PYMETHOD_O(CListValue,count); private: diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 043070ee207..99e2d3b7c06 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -470,15 +470,15 @@ int KX_Camera::GetViewportTop() const PyMethodDef KX_Camera::Methods[] = { KX_PYMETHODTABLE(KX_Camera, sphereInsideFrustum), - KX_PYMETHODTABLE(KX_Camera, boxInsideFrustum), - KX_PYMETHODTABLE(KX_Camera, pointInsideFrustum), - KX_PYMETHODTABLE(KX_Camera, getCameraToWorld), - KX_PYMETHODTABLE(KX_Camera, getWorldToCamera), - KX_PYMETHODTABLE(KX_Camera, getProjectionMatrix), - KX_PYMETHODTABLE(KX_Camera, setProjectionMatrix), - KX_PYMETHODTABLE(KX_Camera, enableViewport), + KX_PYMETHODTABLE_O(KX_Camera, boxInsideFrustum), + KX_PYMETHODTABLE_O(KX_Camera, pointInsideFrustum), + KX_PYMETHODTABLE_NOARGS(KX_Camera, getCameraToWorld), + KX_PYMETHODTABLE_NOARGS(KX_Camera, getWorldToCamera), + KX_PYMETHODTABLE_NOARGS(KX_Camera, getProjectionMatrix), + KX_PYMETHODTABLE_O(KX_Camera, setProjectionMatrix), + KX_PYMETHODTABLE_O(KX_Camera, enableViewport), KX_PYMETHODTABLE(KX_Camera, setViewport), - KX_PYMETHODTABLE(KX_Camera, setOnTop), + KX_PYMETHODTABLE_NOARGS(KX_Camera, setOnTop), {NULL,NULL} //Sentinel }; @@ -624,7 +624,7 @@ int KX_Camera::_setattr(const char *attr, PyObject *pyvalue) return KX_GameObject::_setattr(attr, pyvalue); } -KX_PYMETHODDEF_DOC(KX_Camera, sphereInsideFrustum, +KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, "sphereInsideFrustum(center, radius) -> Integer\n" "\treturns INSIDE, OUTSIDE or INTERSECT if the given sphere is\n" "\tinside/outside/intersects this camera's viewing frustum.\n\n" @@ -658,7 +658,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, sphereInsideFrustum, return NULL; } -KX_PYMETHODDEF_DOC(KX_Camera, boxInsideFrustum, +KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, "boxInsideFrustum(box) -> Integer\n" "\treturns INSIDE, OUTSIDE or INTERSECT if the given box is\n" "\tinside/outside/intersects this camera's viewing frustum.\n\n" @@ -683,34 +683,27 @@ KX_PYMETHODDEF_DOC(KX_Camera, boxInsideFrustum, "\t\t# Box is outside the frustum !\n" ) { - PyObject *pybox; - if (PyArg_ParseTuple(args, "O", &pybox)) + unsigned int num_points = PySequence_Size(value); + if (num_points != 8) { - unsigned int num_points = PySequence_Size(pybox); - if (num_points != 8) - { - PyErr_Format(PyExc_TypeError, "boxInsideFrustum: Expected eight (8) points, got %d", num_points); - return NULL; - } - - MT_Point3 box[8]; - for (unsigned int p = 0; p < 8 ; p++) - { - PyObject *item = PySequence_GetItem(pybox, p); /* new ref */ - bool error = !PyVecTo(item, box[p]); - Py_DECREF(item); - if (error) - return NULL; - } - - return PyInt_FromLong(BoxInsideFrustum(box)); /* new ref */ + PyErr_Format(PyExc_TypeError, "boxInsideFrustum: Expected eight (8) points, got %d", num_points); + return NULL; } - PyErr_SetString(PyExc_TypeError, "boxInsideFrustum: Expected argument: list of points."); - return NULL; + MT_Point3 box[8]; + for (unsigned int p = 0; p < 8 ; p++) + { + PyObject *item = PySequence_GetItem(value, p); /* new ref */ + bool error = !PyVecTo(item, box[p]); + Py_DECREF(item); + if (error) + return NULL; + } + + return PyInt_FromLong(BoxInsideFrustum(box)); /* new ref */ } -KX_PYMETHODDEF_DOC(KX_Camera, pointInsideFrustum, +KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, "pointInsideFrustum(point) -> Bool\n" "\treturns 1 if the given point is inside this camera's viewing frustum.\n\n" "\tpoint = The point to test (in world coordinates.)\n\n" @@ -727,7 +720,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, pointInsideFrustum, ) { MT_Point3 point; - if (PyVecArgTo(args, point)) + if (PyVecTo(value, point)) { return PyInt_FromLong(PointInsideFrustum(point)); /* new ref */ } @@ -736,7 +729,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, pointInsideFrustum, return NULL; } -KX_PYMETHODDEF_DOC(KX_Camera, getCameraToWorld, +KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getCameraToWorld, "getCameraToWorld() -> Matrix4x4\n" "\treturns the camera to world transformation matrix, as a list of four lists of four values.\n\n" "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" @@ -745,7 +738,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getCameraToWorld, return PyObjectFrom(GetCameraToWorld()); /* new ref */ } -KX_PYMETHODDEF_DOC(KX_Camera, getWorldToCamera, +KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getWorldToCamera, "getWorldToCamera() -> Matrix4x4\n" "\treturns the world to camera transformation matrix, as a list of four lists of four values.\n\n" "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" @@ -754,7 +747,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getWorldToCamera, return PyObjectFrom(GetWorldToCamera()); /* new ref */ } -KX_PYMETHODDEF_DOC(KX_Camera, getProjectionMatrix, +KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getProjectionMatrix, "getProjectionMatrix() -> Matrix4x4\n" "\treturns this camera's projection matrix, as a list of four lists of four values.\n\n" "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" @@ -763,7 +756,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, getProjectionMatrix, return PyObjectFrom(GetProjectionMatrix()); /* new ref */ } -KX_PYMETHODDEF_DOC(KX_Camera, setProjectionMatrix, +KX_PYMETHODDEF_DOC_O(KX_Camera, setProjectionMatrix, "setProjectionMatrix(MT_Matrix4x4 m) -> None\n" "\tSets this camera's projection matrix\n" "\n" @@ -805,56 +798,50 @@ KX_PYMETHODDEF_DOC(KX_Camera, setProjectionMatrix, "\tcam = co.getOwner()\n" "\tcam.setProjectionMatrix(Perspective(-1.0, 1.0, -1.0, 1.0, 0.1, 1))\n") { - PyObject *pymat; - if (PyArg_ParseTuple(args, "O", &pymat)) + MT_Matrix4x4 mat; + if (!PyMatTo(value, mat)) { - MT_Matrix4x4 mat; - if (PyMatTo(pymat, mat)) - { - SetProjectionMatrix(mat); - Py_RETURN_NONE; - } + PyErr_SetString(PyExc_TypeError, "setProjectionMatrix: Expected 4x4 list as matrix argument."); + return NULL; } - - PyErr_SetString(PyExc_TypeError, "setProjectionMatrix: Expected 4x4 list as matrix argument."); - return NULL; + + SetProjectionMatrix(mat); + Py_RETURN_NONE; } -KX_PYMETHODDEF_DOC(KX_Camera, enableViewport, +KX_PYMETHODDEF_DOC_O(KX_Camera, enableViewport, "enableViewport(viewport)\n" "Sets this camera's viewport status\n" ) { - int viewport; - if (PyArg_ParseTuple(args,"i",&viewport)) - { - if(viewport) - EnableViewport(true); - else - EnableViewport(false); - } - else { + int viewport = PyObject_IsTrue(value); + + if (viewport == -1) { + PyErr_SetString(PyExc_ValueError, "expected True/False or 0/1"); return NULL; } + if(viewport) + EnableViewport(true); + else + EnableViewport(false); + Py_RETURN_NONE; } -KX_PYMETHODDEF_DOC(KX_Camera, setViewport, +KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, setViewport, "setViewport(left, bottom, right, top)\n" "Sets this camera's viewport\n") { int left, bottom, right, top; - if (PyArg_ParseTuple(args,"iiii",&left, &bottom, &right, &top)) - { - SetViewport(left, bottom, right, top); - } else { + if (!PyArg_ParseTuple(args,"iiii:setViewport",&left, &bottom, &right, &top)) return NULL; - } + + SetViewport(left, bottom, right, top); Py_RETURN_NONE; } -KX_PYMETHODDEF_DOC(KX_Camera, setOnTop, +KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop, "setOnTop()\n" "Sets this camera's viewport on top\n") { diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 3e93745d888..efd18f99390 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -257,18 +257,18 @@ public: int GetViewportTop() const; - KX_PYMETHOD_DOC(KX_Camera, sphereInsideFrustum); - KX_PYMETHOD_DOC(KX_Camera, boxInsideFrustum); - KX_PYMETHOD_DOC(KX_Camera, pointInsideFrustum); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, sphereInsideFrustum); + KX_PYMETHOD_DOC_O(KX_Camera, boxInsideFrustum); + KX_PYMETHOD_DOC_O(KX_Camera, pointInsideFrustum); - KX_PYMETHOD_DOC(KX_Camera, getCameraToWorld); - KX_PYMETHOD_DOC(KX_Camera, getWorldToCamera); - KX_PYMETHOD_DOC(KX_Camera, getProjectionMatrix); - KX_PYMETHOD_DOC(KX_Camera, setProjectionMatrix); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, getCameraToWorld); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, getWorldToCamera); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, getProjectionMatrix); + KX_PYMETHOD_DOC_O(KX_Camera, setProjectionMatrix); - KX_PYMETHOD_DOC(KX_Camera, enableViewport); - KX_PYMETHOD_DOC(KX_Camera, setViewport); - KX_PYMETHOD_DOC(KX_Camera, setOnTop); + KX_PYMETHOD_DOC_O(KX_Camera, enableViewport); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop); virtual PyObject* _getattr(const char *attr); /* lens, near, far, projection_matrix */ virtual int _setattr(const char *attr, PyObject *pyvalue); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 7d785f07ed2..82b5fff534c 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1030,8 +1030,8 @@ PyMethodDef KX_GameObject::Methods[] = { {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS}, KX_PYMETHODTABLE(KX_GameObject, rayCastTo), KX_PYMETHODTABLE(KX_GameObject, rayCast), - KX_PYMETHODTABLE(KX_GameObject, getDistanceTo), - KX_PYMETHODTABLE(KX_GameObject, getVectTo), + KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), + KX_PYMETHODTABLE_O(KX_GameObject, getVectTo), {NULL,NULL} //Sentinel }; @@ -1136,10 +1136,7 @@ PyObject* KX_GameObject::_getattr(const char *attr) { KX_GameObject* parent = GetParent(); if (parent) - { - parent->AddRef(); - return parent; - } + return parent->AddRef(); Py_RETURN_NONE; } @@ -1297,7 +1294,7 @@ PyObject* KX_GameObject::PyApplyForce(PyObject* self, PyObject* args) int local = 0; PyObject* pyvect; - if (PyArg_ParseTuple(args, "O|i", &pyvect, &local)) { + if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) { MT_Vector3 force; if (PyVecTo(pyvect, force)) { ApplyForce(force, (local!=0)); @@ -1312,7 +1309,7 @@ PyObject* KX_GameObject::PyApplyTorque(PyObject* self, PyObject* args) int local = 0; PyObject* pyvect; - if (PyArg_ParseTuple(args, "O|i", &pyvect, &local)) { + if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) { MT_Vector3 torque; if (PyVecTo(pyvect, torque)) { ApplyTorque(torque, (local!=0)); @@ -1327,7 +1324,7 @@ PyObject* KX_GameObject::PyApplyRotation(PyObject* self, PyObject* args) int local = 0; PyObject* pyvect; - if (PyArg_ParseTuple(args, "O|i", &pyvect, &local)) { + if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) { MT_Vector3 rotation; if (PyVecTo(pyvect, rotation)) { ApplyRotation(rotation, (local!=0)); @@ -1342,7 +1339,7 @@ PyObject* KX_GameObject::PyApplyMovement(PyObject* self, PyObject* args) int local = 0; PyObject* pyvect; - if (PyArg_ParseTuple(args, "O|i", &pyvect, &local)) { + if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) { MT_Vector3 movement; if (PyVecTo(pyvect, movement)) { ApplyMovement(movement, (local!=0)); @@ -1356,7 +1353,7 @@ 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; - if (PyArg_ParseTuple(args,"|i",&local)) + if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local)) { return PyObjectFrom(GetLinearVelocity((local!=0))); } @@ -1371,7 +1368,7 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args) int local = 0; PyObject* pyvect; - if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) { + if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) { MT_Vector3 velocity; if (PyVecTo(pyvect, velocity)) { setLinearVelocity(velocity, (local!=0)); @@ -1385,7 +1382,7 @@ PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args) { // only can get the velocity if we have a physics object connected to us... int local = 0; - if (PyArg_ParseTuple(args,"|i",&local)) + if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local)) { return PyObjectFrom(GetAngularVelocity((local!=0))); } @@ -1400,7 +1397,7 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) int local = 0; PyObject* pyvect; - if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) { + if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) { MT_Vector3 velocity; if (PyVecTo(pyvect, velocity)) { setAngularVelocity(velocity, (local!=0)); @@ -1413,7 +1410,7 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args) { int visible, recursive = 0; - if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive)) + if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive)) return NULL; SetVisible(visible ? true:false, recursive ? true:false); @@ -1464,7 +1461,7 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) PyObject* pypos = NULL; - if (PyArg_ParseTuple(args, "|O", &pypos)) + if (PyArg_ParseTuple(args, "|O:getVelocity", &pypos)) { if (pypos) PyVecTo(pypos, point); @@ -1520,10 +1517,7 @@ PyObject* KX_GameObject::PyGetParent(PyObject* self) { KX_GameObject* parent = this->GetParent(); if (parent) - { - parent->AddRef(); - return parent; - } + return parent->AddRef(); Py_RETURN_NONE; } @@ -1592,7 +1586,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) { int mesh = 0; - if (!PyArg_ParseTuple(args, "|i", &mesh)) + if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh)) return NULL; // python sets a simple error if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) @@ -1638,7 +1632,7 @@ PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args) return NULL; } - if (PyArg_ParseTuple(args, "OO", &pyattach, &pyimpulse)) + if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse)) { MT_Point3 attach; MT_Vector3 impulse; @@ -1705,7 +1699,7 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args) int axis = 2; //z axis is the default float fac = 1.0; - if (PyArg_ParseTuple(args,"O|if",&pyvect,&axis, &fac)) + if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac)) { MT_Vector3 vect; if (PyVecTo(pyvect, vect)) @@ -1773,19 +1767,18 @@ PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self) return ConvertKeysToPython(); } -KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo, +KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo, "getDistanceTo(other): get distance to another point/KX_GameObject") { MT_Point3 b; - if (PyVecArgTo(args, b)) + if (PyVecTo(value, b)) { return PyFloat_FromDouble(NodeGetWorldPosition().distance(b)); } PyErr_Clear(); - PyObject *pyother; KX_GameObject *other; - if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false)) + if (ConvertPythonToGameObject(value, &other, false)) { return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition())); } @@ -1793,7 +1786,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo, return NULL; } -KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, +KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo, "getVectTo(other): get vector and the distance to another point/KX_GameObject\n" "Returns a 3-tuple with (distance,worldVector,localVector)\n") { @@ -1802,14 +1795,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, MT_Scalar distance; PyObject *returnValue; - PyObject *pyother; - if (!PyVecArgTo(args, toPoint)) + if (!PyVecTo(value, toPoint)) { PyErr_Clear(); KX_GameObject *other; - if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false)) + if (ConvertPythonToGameObject(value, &other, false)) { toPoint = other->NodeGetWorldPosition(); } else @@ -1894,7 +1886,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, float dist = 0.0f; char *propName = NULL; - if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) { + if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) { return NULL; // python sets simple error } @@ -1937,10 +1929,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); if (m_pHitObject) - { - m_pHitObject->AddRef(); - return m_pHitObject; - } + return m_pHitObject->AddRef(); + Py_RETURN_NONE; } @@ -1973,7 +1963,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, 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|Ofsiii:rayCast", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) { return NULL; // Python sets a simple error } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 7fe3009a957..d95e3751d33 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -799,8 +799,8 @@ public: KX_PYMETHOD_NOARGS(KX_GameObject,EndObject); KX_PYMETHOD_DOC(KX_GameObject,rayCastTo); KX_PYMETHOD_DOC(KX_GameObject,rayCast); - KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo); - KX_PYMETHOD_DOC(KX_GameObject,getVectTo); + KX_PYMETHOD_DOC_O(KX_GameObject,getDistanceTo); + KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo); private : diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index afb20acec2d..92f18590a7e 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -77,35 +77,92 @@ bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) { +#if 0 return Py_BuildValue("[[ffff][ffff][ffff][ffff]]", mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[1][0], mat[1][1], mat[1][2], mat[1][3], mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[3][0], mat[3][1], mat[3][2], mat[3][3]); +#else + PyObject *list = PyList_New(4); + PyObject *sublist; + int i; + + for(i=0; i < 4; i++) { + sublist = PyList_New(4); + PyList_SET_ITEM(sublist, 0, PyFloat_FromDouble(mat[i][0])); + PyList_SET_ITEM(sublist, 1, PyFloat_FromDouble(mat[i][1])); + PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][2])); + PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][3])); + PyList_SET_ITEM(list, i, sublist); + } + + return list; +#endif } PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) { +#if 0 return Py_BuildValue("[[fff][fff][fff]]", mat[0][0], mat[0][1], mat[0][2], mat[1][0], mat[1][1], mat[1][2], mat[2][0], mat[2][1], mat[2][2]); +#else + PyObject *list = PyList_New(3); + PyObject *sublist; + int i; + + for(i=0; i < 3; i++) { + sublist = PyList_New(3); + PyList_SET_ITEM(sublist, 0, PyFloat_FromDouble(mat[i][0])); + PyList_SET_ITEM(sublist, 1, PyFloat_FromDouble(mat[i][1])); + PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][2])); + PyList_SET_ITEM(list, i, sublist); + } + + return list; +#endif } PyObject* PyObjectFrom(const MT_Tuple4 &vec) { +#if 0 return Py_BuildValue("[ffff]", vec[0], vec[1], vec[2], vec[3]); +#else + PyObject *list = PyList_New(4); + PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); + PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); + PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2])); + PyList_SET_ITEM(list, 3, PyFloat_FromDouble(vec[3])); + return list; +#endif } PyObject* PyObjectFrom(const MT_Tuple3 &vec) { +#if 0 return Py_BuildValue("[fff]", vec[0], vec[1], vec[2]); +#else + PyObject *list = PyList_New(3); + PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); + PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); + PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2])); + return list; +#endif } PyObject* PyObjectFrom(const MT_Tuple2 &vec) { +#if 0 return Py_BuildValue("[ff]", vec[0], vec[1]); +#else + PyObject *list = PyList_New(2); + PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); + PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); + return list; +#endif } diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index 4e383e9b3d4..39c9c358792 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -130,20 +130,6 @@ bool PyVecTo(PyObject* pyval, T& vec) return false; } -/** - * Converts a python argument to an MT class. - * This paramater expects arguments as passed to a python method. - */ -template -bool PyVecArgTo(PyObject* args, T& vec) -{ - PyObject* pylist; - if (PyArg_ParseTuple(args,"O",&pylist)) - return PyVecTo(pylist, vec); - - return false; -} - /** * Converts an MT_Matrix4x4 to a python object. */ diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 13f141dec13..c3ae3d0ec52 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -125,10 +125,10 @@ static PyObject* gPyGetRandomFloat(PyObject*) return PyFloat_FromDouble(MT_random()); } -static PyObject* gPySetGravity(PyObject*, PyObject* args) +static PyObject* gPySetGravity(PyObject*, PyObject* value) { - MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) + MT_Vector3 vec; + if (!PyVecTo(value, vec)) return NULL; if (gp_KetsjiScene) @@ -412,7 +412,7 @@ static struct PyMethodDef game_methods[] = { METH_VARARGS, (PY_METHODCHAR)SCA_PythonController::sPyAddActiveActuator__doc__}, {"getRandomFloat",(PyCFunction) gPyGetRandomFloat, METH_NOARGS, (PY_METHODCHAR)gPyGetRandomFloat_doc.Ptr()}, - {"setGravity",(PyCFunction) gPySetGravity, METH_VARARGS, (PY_METHODCHAR)"set Gravitation"}, + {"setGravity",(PyCFunction) gPySetGravity, METH_O, (PY_METHODCHAR)"set Gravitation"}, {"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS, (PY_METHODCHAR)"get audio spectrum"}, {"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS, (PY_METHODCHAR)"stop using the audio dsp (for performance reasons)"}, {"getLogicTicRate", (PyCFunction) gPyGetLogicTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the logic tic rate"}, @@ -542,11 +542,11 @@ static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) Py_RETURN_NONE; } -static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args) +static PyObject* gPySetBackgroundColor(PyObject*, PyObject* value) { - MT_Vector4 vec = MT_Vector4(0., 0., 0.3, 0.); - if (!PyVecArgTo(args, vec)) + MT_Vector4 vec; + if (!PyVecTo(value, vec)) return NULL; if (gp_Canvas) @@ -558,11 +558,11 @@ static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args) -static PyObject* gPySetMistColor(PyObject*, PyObject* args) +static PyObject* gPySetMistColor(PyObject*, PyObject* value) { - MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) + MT_Vector3 vec; + if (!PyVecTo(value, vec)) return NULL; if (!gp_Rasterizer) { @@ -613,11 +613,11 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args) } -static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) +static PyObject* gPySetAmbientColor(PyObject*, PyObject* value) { - MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) + MT_Vector3 vec; + if (!PyVecTo(value, vec)) return NULL; if (!gp_Rasterizer) { @@ -812,9 +812,9 @@ static PyObject* gPyDrawLine(PyObject*, PyObject* args) if (!PyArg_ParseTuple(args,"OOO",&ob_from,&ob_to,&ob_color)) return NULL; - MT_Vector3 from(0., 0., 0.); - MT_Vector3 to(0., 0., 0.); - MT_Vector3 color(0., 0., 0.); + MT_Vector3 from; + MT_Vector3 to; + MT_Vector3 color; if (!PyVecTo(ob_from, from)) return NULL; if (!PyVecTo(ob_to, to)) @@ -840,9 +840,9 @@ static struct PyMethodDef rasterizer_methods[] = { METH_VARARGS, "showMouse(bool visible)"}, {"setMousePosition",(PyCFunction) gPySetMousePosition, METH_VARARGS, "setMousePosition(int x,int y)"}, - {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_VARARGS,"set Background Color (rgb)"}, - {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_VARARGS,"set Ambient Color (rgb)"}, - {"setMistColor",(PyCFunction)gPySetMistColor,METH_VARARGS,"set Mist Color (rgb)"}, + {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, + {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, + {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 49babedd467..7fcbf5b54bb 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1512,9 +1512,9 @@ double KX_Scene::getSuspendedDelta() //Python PyMethodDef KX_Scene::Methods[] = { - KX_PYMETHODTABLE(KX_Scene, getLightList), - KX_PYMETHODTABLE(KX_Scene, getObjectList), - KX_PYMETHODTABLE(KX_Scene, getName), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getLightList), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getObjectList), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getName), {NULL,NULL} //Sentinel }; @@ -1549,12 +1549,11 @@ PyObject* KX_Scene::_getattr(const char *attr) if (!strcmp(attr, "name")) return PyString_FromString(GetName()); + if (!strcmp(attr, "objects")) + return (PyObject*) m_objectlist->AddRef(); + if (!strcmp(attr, "active_camera")) - { - KX_Camera *camera = GetActiveCamera(); - camera->AddRef(); - return (PyObject*) camera; - } + return (PyObject*) GetActiveCamera()->AddRef(); if (!strcmp(attr, "suspended")) return PyInt_FromLong(m_suspend); @@ -1589,25 +1588,24 @@ int KX_Scene::_setattr(const char *attr, PyObject *pyvalue) return PyObjectPlus::_setattr(attr, pyvalue); } -KX_PYMETHODDEF_DOC(KX_Scene, getLightList, +KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, "getLightList() -> list [KX_Light]\n" "Returns a list of all lights in the scene.\n" ) { - m_lightlist->AddRef(); - return (PyObject*) m_lightlist; + return (PyObject*) m_lightlist->AddRef(); } -KX_PYMETHODDEF_DOC(KX_Scene, getObjectList, +KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList, "getObjectList() -> list [KX_GameObject]\n" "Returns a list of all game objects in the scene.\n" ) { - m_objectlist->AddRef(); - return (PyObject*) m_objectlist; + // ShowDeprecationWarning("getObjectList()", "the objects property"); // XXX Grr, why doesnt this work? + return (PyObject*) m_objectlist->AddRef(); } -KX_PYMETHODDEF_DOC(KX_Scene, getName, +KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName, "getName() -> string\n" "Returns the name of the scene.\n" ) diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index ecc0fd51d73..e4d4b6fe2cd 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -547,9 +547,9 @@ public: */ void SetNodeTree(SG_Tree* root); - KX_PYMETHOD_DOC(KX_Scene, getLightList); - KX_PYMETHOD_DOC(KX_Scene, getObjectList); - KX_PYMETHOD_DOC(KX_Scene, getName); + KX_PYMETHOD_DOC_NOARGS(KX_Scene, getLightList); + KX_PYMETHOD_DOC_NOARGS(KX_Scene, getObjectList); + KX_PYMETHOD_DOC_NOARGS(KX_Scene, getName); /* KX_PYMETHOD_DOC(KX_Scene, getActiveCamera); KX_PYMETHOD_DOC(KX_Scene, getActiveCamera); diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index ab102ee547a..1c427768b66 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -63,18 +63,18 @@ PyParentObject KX_VertexProxy::Parents[] = { }; PyMethodDef KX_VertexProxy::Methods[] = { -{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_VARARGS}, -{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_VARARGS}, -{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_VARARGS}, -{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_VARARGS}, +{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, +{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, +{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS}, +{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O}, -{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_VARARGS}, +{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, -{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_VARARGS}, -{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_VARARGS}, -{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_VARARGS}, -{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_VARARGS}, +{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, +{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, +{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS}, +{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O}, {NULL,NULL} //Sentinel }; @@ -312,130 +312,103 @@ void KX_VertexProxy::ReplicaSetName(STR_String) {}; // stuff for python integration -PyObject* KX_VertexProxy::PyGetXYZ(PyObject*, - PyObject*, - PyObject*) +PyObject* KX_VertexProxy::PyGetXYZ(PyObject*) { return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); } -PyObject* KX_VertexProxy::PySetXYZ(PyObject*, - PyObject* args, - PyObject*) +PyObject* KX_VertexProxy::PySetXYZ(PyObject*, PyObject* value) { MT_Point3 vec; - if (PyVecArgTo(args, vec)) - { - m_vertex->SetXYZ(vec); - m_mesh->SetMeshModified(true); - Py_RETURN_NONE; - } - - return NULL; + if (!PyVecTo(value, vec)) + return NULL; + + m_vertex->SetXYZ(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetNormal(PyObject*, - PyObject*, - PyObject*) +PyObject* KX_VertexProxy::PyGetNormal(PyObject*) { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } -PyObject* KX_VertexProxy::PySetNormal(PyObject*, - PyObject* args, - PyObject*) +PyObject* KX_VertexProxy::PySetNormal(PyObject*, PyObject* value) { MT_Vector3 vec; - if (PyVecArgTo(args, vec)) - { - m_vertex->SetNormal(vec); - m_mesh->SetMeshModified(true); - Py_RETURN_NONE; - } + if (!PyVecTo(value, vec)) + return NULL; - return NULL; + m_vertex->SetNormal(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetRGBA(PyObject*, - PyObject*, - PyObject*) +PyObject* KX_VertexProxy::PyGetRGBA(PyObject*) { int *rgba = (int *) m_vertex->getRGBA(); return PyInt_FromLong(*rgba); } -PyObject* KX_VertexProxy::PySetRGBA(PyObject*, - PyObject* args, - PyObject*) +PyObject* KX_VertexProxy::PySetRGBA(PyObject*, PyObject* value) { - float r, g, b, a; - if (PyArg_ParseTuple(args, "(ffff)", &r, &g, &b, &a)) - { - m_vertex->SetRGBA(MT_Vector4(r, g, b, a)); - m_mesh->SetMeshModified(true); - Py_RETURN_NONE; - } - PyErr_Clear(); - - int rgba; - if (PyArg_ParseTuple(args,"i",&rgba)) - { + if PyInt_Check(value) { + int rgba = PyInt_AsLong(value); m_vertex->SetRGBA(rgba); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } - - return NULL; -} - - -PyObject* KX_VertexProxy::PyGetUV(PyObject*, - PyObject*, - PyObject*) -{ - return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); -} - -PyObject* KX_VertexProxy::PySetUV(PyObject*, - PyObject* args, - PyObject*) -{ - MT_Point2 vec; - if (PyVecArgTo(args, vec)) - { - m_vertex->SetUV(vec); - m_mesh->SetMeshModified(true); - Py_RETURN_NONE; - } - - return NULL; -} - -PyObject* KX_VertexProxy::PyGetUV2(PyObject*, - PyObject*, - PyObject*) -{ - return PyObjectFrom(MT_Vector2(m_vertex->getUV2())); -} - -PyObject* KX_VertexProxy::PySetUV2(PyObject*, - PyObject* args, - PyObject*) -{ - MT_Point2 vec; - unsigned int unit=0; - PyObject* list=0; - if(PyArg_ParseTuple(args, "Oi", &list, &unit)) - { - if (PyVecTo(list, vec)) + else { + MT_Vector4 vec; + if (PyVecTo(value, vec)) { - m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); - m_vertex->SetUnit(unit); - m_vertex->SetUV2(vec); + m_vertex->SetRGBA(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } } + + PyErr_SetString(PyExc_TypeError, "expected a 4D vector or an int"); return NULL; } + + +PyObject* KX_VertexProxy::PyGetUV(PyObject*) +{ + return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); +} + +PyObject* KX_VertexProxy::PySetUV(PyObject*, PyObject* value) +{ + MT_Point2 vec; + if (!PyVecTo(value, vec)) + return NULL; + + m_vertex->SetUV(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; +} + +PyObject* KX_VertexProxy::PyGetUV2(PyObject*) +{ + return PyObjectFrom(MT_Vector2(m_vertex->getUV2())); +} + +PyObject* KX_VertexProxy::PySetUV2(PyObject*, PyObject* args) +{ + MT_Point2 vec; + unsigned int unit=0; + PyObject* list= NULL; + if(!PyArg_ParseTuple(args, "Oi:setUV2", &list, &unit)) + return NULL; + + if (!PyVecTo(list, vec)) + return NULL; + + m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); + m_vertex->SetUnit(unit); + m_vertex->SetUV2(vec); + m_mesh->SetMeshModified(true); + Py_RETURN_NONE; +} diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 72949268e6d..28196075904 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -57,18 +57,18 @@ public: virtual PyObject* _getattr(const char *attr); virtual int _setattr(const char *attr, PyObject *pyvalue); - KX_PYMETHOD(KX_VertexProxy,GetXYZ); - KX_PYMETHOD(KX_VertexProxy,SetXYZ); - KX_PYMETHOD(KX_VertexProxy,GetUV); - KX_PYMETHOD(KX_VertexProxy,SetUV); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); + KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV); + KX_PYMETHOD_O(KX_VertexProxy,SetUV); - KX_PYMETHOD(KX_VertexProxy,GetUV2); - KX_PYMETHOD(KX_VertexProxy,SetUV2); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV2); + KX_PYMETHOD_VARARGS(KX_VertexProxy,SetUV2); - KX_PYMETHOD(KX_VertexProxy,GetRGBA); - KX_PYMETHOD(KX_VertexProxy,SetRGBA); - KX_PYMETHOD(KX_VertexProxy,GetNormal); - KX_PYMETHOD(KX_VertexProxy,SetNormal); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetRGBA); + KX_PYMETHOD_O(KX_VertexProxy,SetRGBA); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetNormal); + KX_PYMETHOD_O(KX_VertexProxy,SetNormal); }; From 373d4fe6d3c49dae35c05d7c06df4d1d0b56f62d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 23 Feb 2009 12:17:34 +0000 Subject: [PATCH 202/252] =?UTF-8?q?[#18323]=20VRML=20import=20will=20not?= =?UTF-8?q?=20import=20colors=20if=20pervertexcolors=20set=20(comparison?= =?UTF-8?q?=20reversed)=20thanks=20to=20=EF=BB=BFEzra=20Peisach=20for=20fi?= =?UTF-8?q?xing.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- release/scripts/import_web3d.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index 28bc1a40ef0..87a259cbe56 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -1758,7 +1758,7 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): print '\tWarning: per vertex color index out of range' continue - if len(ifs_vcol) < color_index: + if color_index < len(ifs_vcol): c.r, c.g, c.b = ifs_vcol[color_index] else: #print '\tWarning: per face color index out of range' From 334da0fa57195af65c2877ee2882714efe5431f9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 23 Feb 2009 12:35:16 +0000 Subject: [PATCH 203/252] =?UTF-8?q?[#18291]=20Viewing=20muliple=20object?= =?UTF-8?q?=20UV's=20in=20the=20UV/Image=20editor=20patch=20from=EF=BB=BF?= =?UTF-8?q?=20Chris=20and=20Guillermo=20S.=20Romero.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/blender/include/blendef.h | 4 ++ source/blender/makesdna/DNA_space_types.h | 1 + source/blender/src/drawimage.c | 52 ++++++++++++++++++++--- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 60d3a589c51..dc05acc1735 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -95,6 +95,10 @@ /* This is a TESTBASELIB that can work without a 3D view */ #define TESTBASELIB_BGMODE(base) ( ((base)->flag & SELECT) && ((base)->lay & (G.vd ? G.vd->lay : G.scene->lay)) && ((base)->object->id.lib==0) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0)) +/* Test base for 2D Windows */ +/* This is added so that DNA_view3d_types.h doesn't have to be included */ +#define TESTBASE_2D(base) ( ((base)->flag & SELECT) && ((base)->lay & G.scene->lay) && (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0)) + #define BASE_SELECTABLE(base) ((base->lay & G.vd->lay) && (base->object->restrictflag & (OB_RESTRICT_SELECT|OB_RESTRICT_VIEW))==0) #define FIRSTBASE G.scene->base.first #define LASTBASE G.scene->base.last diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 226a3ecd834..735e1c4f195 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -539,6 +539,7 @@ typedef struct SpaceImaSel { #define SI_SMOOTH_UV 1<<20 #define SI_DRAW_STRETCH 1<<21 #define SI_DISPGP 1<<22 +#define SI_DRAW_OTHER 1<<23 /* SpaceIpo->flag */ #define SIPO_LOCK_VIEW 1<<0 diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index d400af3c2bf..b8409aff3bd 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -474,12 +474,13 @@ void draw_uvs_sima(void) MTFace *tface,*activetface = NULL; EditMesh *em = G.editMesh; EditFace *efa, *efa_act; - + Base *base; + char col1[4], col2[4]; float pointsize; int drawface; int lastsel, sel; - + if (!G.obedit || !CustomData_has_layer(&em->fdata, CD_MTFACE)) return; @@ -489,7 +490,47 @@ void draw_uvs_sima(void) myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); glLoadIdentity(); - + if(G.sima->flag & SI_DRAW_OTHER) { + base= FIRSTBASE; + if(base) { + MTFace *activetf; + Image *curimage; + + activetf = get_active_mtface(NULL, NULL, 1); + if (activetf) { + curimage = activetf->tpage; + glColor3ub(96, 96, 96); + while(base) { + if (TESTBASE_2D(base)) { + Object *ob; + ob = base->object; + if ((ob->type==OB_MESH) && (ob!=G.obedit)) { + Mesh *me; + me = ob->data; + if (me->mtface) { + MFace *mface; + int a; + mface= me->mface; + tface= me->mtface; + for (a=me->totface; a>0; a--, tface++, mface++) { + if (tface->tpage == curimage) { + glBegin(GL_LINE_LOOP); + glVertex2fv(tface->uv[0]); + glVertex2fv(tface->uv[1]); + glVertex2fv(tface->uv[2]); + if(mface->v4) glVertex2fv(tface->uv[3]); + glEnd(); + } + } + } + } + } + base= base->next; + } + } + } + } + if(G.sima->flag & SI_DRAWTOOL) { /* draws the grey mesh when painting */ glColor3ub(112, 112, 112); @@ -902,7 +943,7 @@ void draw_uvs_sima(void) } glLineWidth(1); - col2[0] = col2[1] = col2[2] = 128; col2[3] = 255; + col2[0] = col2[1] = col2[2] = 192; col2[3] = 255; glColor4ubv((unsigned char *)col2); if (G.f & G_DRAWEDGES) { @@ -1467,7 +1508,8 @@ static void image_panel_view_properties(short cntrl) // IMAGE_HANDLER_VIEW_PROPE uiDefButBitI(block, TOG, G_DRAWFACES, B_REDR, "Faces", 10,30,60,19, &G.f, 0, 0, 0, 0, "Displays all faces as shades in the 3d view and UV editor"); uiDefButBitI(block, TOG, G_DRAWEDGES, B_REDR, "Edges", 70, 30,60,19, &G.f, 0, 0, 0, 0, "Displays selected edges using hilights in the 3d view and UV editor"); - uiDefButBitI(block, TOG, SI_DRAWSHADOW, B_REDR, "Final Shadow", 130, 30,110,19, &G.sima->flag, 0, 0, 0, 0, "Draw the final result from the objects modifiers"); + uiDefButBitI(block, TOG, SI_DRAWSHADOW, B_REDR, "Final Shadow", 130, 30,100,19, &G.sima->flag, 0, 0, 0, 0, "Draw the final result from the objects modifiers"); + uiDefButBitI(block, TOG, SI_DRAW_OTHER, B_REDR, "Other Objs", 230, 30, 80, 19, &G.sima->flag, 0, 0, 0, 0, "Also draw all 3d view selected mesh objects that use this image"); uiDefButBitI(block, TOG, SI_DRAW_STRETCH, B_REDR, "UV Stretch", 10,0,100,19, &G.sima->flag, 0, 0, 0, 0, "Difference between UV's and the 3D coords (blue for low distortion, red is high)"); if (G.sima->flag & SI_DRAW_STRETCH) { From 57c7200a65a5fcfaa3a7c110ff3b2aecc7cde16f Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 24 Feb 2009 00:45:40 +0000 Subject: [PATCH 204/252] Merging volume embedding and transform snapping. - Volume embed is available as a transform snap option (need new icon). Not as "continuous" as stroke embed, will have to be fixed somehow. - Transform snaps work in armature edit mode (only snap to mesh, not other armatures, for now). Adding to other edit data type should be easy. - Strokes can use all the transform snap options plus volume embed. Bug fix: added small threshold to face snap (and volume embed) to prevent slipping in cracks between faces. More tweaking needed but this now takes care of all the worst cases. --- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 51 +++ source/blender/include/BIF_transform.h | 26 ++ source/blender/makesdna/DNA_scene_types.h | 1 + source/blender/src/editarmature_sketch.c | 399 +++++------------- source/blender/src/header_view3d.c | 1 + source/blender/src/transform_snap.c | 475 ++++++++++++++++++---- 7 files changed, 577 insertions(+), 377 deletions(-) diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 6a2db92d25f..092ed00fbe5 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -394,6 +394,7 @@ int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float int LineIntersectLineStrict(float v1[3], float v2[3], float v3[3], float v4[3], float vi[3], float *lambda); int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); +int RayIntersectsTriangleThreshold(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float threshold); int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint); int AxialLineIntersectsTriangle(int axis, float co1[3], float co2[3], float v0[3], float v1[3], float v2[3], float *lambda); int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 5f94df6f5eb..ad1dc1ca12c 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -3896,6 +3896,57 @@ int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], flo return 1; } +int RayIntersectsTriangleThreshold(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float threshold) +{ + float p[3], s[3], e1[3], e2[3], q[3]; + float a, f, u, v; + float du = 0, dv = 0; + + VecSubf(e1, v1, v0); + VecSubf(e2, v2, v0); + + Crossf(p, d, e2); + a = Inpf(e1, p); + if ((a > -0.000001) && (a < 0.000001)) return 0; + f = 1.0f/a; + + VecSubf(s, p1, v0); + + Crossf(q, s, e1); + *lambda = f * Inpf(e2, q); + if ((*lambda < 0.0)) return 0; + + u = f * Inpf(s, p); + v = f * Inpf(d, q); + + if (u < 0) du = u; + if (u > 1) du = u - 1; + if (v < 0) dv = v; + if (v > 1) dv = v - 1; + if (u > 0 && v > 0 && u + v > 1) + { + float t = u + v - 1; + du = u - t/2; + dv = v - t/2; + } + + VecMulf(e1, du); + VecMulf(e2, dv); + + if (Inpf(e1, e1) + Inpf(e2, e2) > threshold * threshold) + { + return 0; + } + + if(uv) { + uv[0]= u; + uv[1]= v; + } + + return 1; +} + + /* Adapted from the paper by Kasper Fauerby */ /* "Improved Collision detection and Response" */ static int getLowestRoot(float a, float b, float c, float maxR, float* root) diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index 0e3985fc52c..8a8d7dc3b4a 100644 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -86,6 +86,7 @@ struct TransInfo; struct ScrArea; struct Base; struct Scene; +struct Object; struct TransInfo * BIF_GetTransInfo(void); void BIF_setSingleAxisConstraint(float vec[3], char *text); @@ -125,5 +126,30 @@ void ManipulatorTransform(); int BIF_do_manipulator(struct ScrArea *sa); void BIF_draw_manipulator(struct ScrArea *sa); +/* Snapping */ + + +typedef struct DepthPeel +{ + struct DepthPeel *next, *prev; + + float depth; + float p[3]; + float no[3]; + struct Object *ob; + int flag; +} DepthPeel; + +struct ListBase; + +typedef enum SnapMode +{ + NOT_SELECTED = 0, + NOT_ACTIVE = 1 +} SnapMode; + +int snapObjects(int *dist, float *loc, float *no, SnapMode mode); +int peelObjects(struct ListBase *depth_peels, short mval[2]); + #endif diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index d04d3259c70..35e086b418a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -752,6 +752,7 @@ typedef struct Scene { #define SCE_SNAP_MODE_VERTEX 0 #define SCE_SNAP_MODE_EDGE 1 #define SCE_SNAP_MODE_FACE 2 +#define SCE_SNAP_MODE_VOLUME 3 /* sce->selectmode */ #define SCE_SELECT_VERTEX 1 /* for mesh */ diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 80302109b37..7314add5e7b 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -57,6 +57,8 @@ #include "BIF_generate.h" #include "BIF_interface.h" +#include "BIF_transform.h" + #include "blendef.h" #include "mydevice.h" #include "reeb.h" @@ -418,224 +420,6 @@ void BIF_setTemplate(int index) } } -/******************** PEELING *********************************/ - -typedef struct SK_DepthPeel -{ - struct SK_DepthPeel *next, *prev; - - float depth; - float p[3]; - float no[3]; - Object *ob; - int flag; -} SK_DepthPeel; - -int cmpPeel(void *arg1, void *arg2) -{ - SK_DepthPeel *p1 = arg1; - SK_DepthPeel *p2 = arg2; - int val = 0; - - if (p1->depth < p2->depth) - { - val = -1; - } - else if (p1->depth > p2->depth) - { - val = 1; - } - - return val; -} - -void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob) -{ - SK_DepthPeel *peel = MEM_callocN(sizeof(SK_DepthPeel), "DepthPeel"); - - peel->depth = depth; - peel->ob = ob; - VECCOPY(peel->p, p); - VECCOPY(peel->no, no); - - BLI_addtail(depth_peels, peel); - - peel->flag = 0; -} - -int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels) -{ - int retval = 0; - int totvert = dm->getNumVerts(dm); - int totface = dm->getNumFaces(dm); - - if (totvert > 0) { - float imat[4][4]; - float timat[3][3]; /* transpose inverse matrix for normals */ - float ray_start_local[3], ray_normal_local[3]; - int test = 1; - - Mat4Invert(imat, obmat); - - Mat3CpyMat4(timat, imat); - Mat3Transp(timat); - - VECCOPY(ray_start_local, ray_start); - VECCOPY(ray_normal_local, ray_normal); - - Mat4MulVecfl(imat, ray_start_local); - Mat4Mul3Vecfl(imat, ray_normal_local); - - - /* If number of vert is more than an arbitrary limit, - * test against boundbox first - * */ - if (totface > 16) { - struct BoundBox *bb = object_get_boundbox(ob); - test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local); - } - - if (test == 1) { - MVert *verts = dm->getVertArray(dm); - MFace *faces = dm->getFaceArray(dm); - int i; - - for( i = 0; i < totface; i++) { - MFace *f = faces + i; - float lambda; - int result; - - - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL); - - if (result) { - float location[3], normal[3]; - float intersect[3]; - float new_depth; - - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - VECCOPY(location, intersect); - - if (f->v4) - CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); - else - CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - Mat3MulVecfl(timat, normal); - Normalize(normal); - - addDepthPeel(depth_peels, new_depth, location, normal, ob); - } - - if (f->v4 && result == 0) - { - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL); - - if (result) { - float location[3], normal[3]; - float intersect[3]; - float new_depth; - - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - VECCOPY(location, intersect); - - if (f->v4) - CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); - else - CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - Mat3MulVecfl(timat, normal); - Normalize(normal); - - addDepthPeel(depth_peels, new_depth, location, normal, ob); - } - } - } - } - } - - return retval; -} - -int peelObjects(ListBase *depth_peels, short mval[2]) -{ - Base *base; - int retval = 0; - float ray_start[3], ray_normal[3]; - - viewray(mval, ray_start, ray_normal); - - base= FIRSTBASE; - for ( base = FIRSTBASE; base != NULL; base = base->next ) { - if ( BASE_SELECTABLE(base) ) { - Object *ob = base->object; - - if (ob->transflag & OB_DUPLI) - { - DupliObject *dupli_ob; - ListBase *lb = object_duplilist(G.scene, ob); - - for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) - { - Object *ob = dupli_ob->ob; - - if (ob->type == OB_MESH) { - DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); - int val; - - val = peelDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, depth_peels); - - retval = retval || val; - - dm->release(dm); - } - } - - free_object_duplilist(lb); - } - - if (ob->type == OB_MESH) { - DerivedMesh *dm = NULL; - int val; - - if (ob != G.obedit) - { - dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); - - val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); - } - else - { - dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); - - val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); - } - - retval = retval || val; - - dm->release(dm); - } - } - } - - BLI_sortlist(depth_peels, cmpPeel); - - return retval; -} /*********************** CONVERSION ***************************/ void sk_autoname(ReebArc *arc) @@ -1087,6 +871,8 @@ void sk_filterStroke(SK_Stroke *stk, int start, int end) int nb_points = stk->nb_points; int i, j; + return; + if (start == -1) { start = 0; @@ -1783,99 +1569,120 @@ int sk_addStrokeSnapPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { - ListBase depth_peels; - SK_DepthPeel *p1, *p2; - float *last_p = NULL; - float dist = FLT_MAX; - float p[3]; int point_added = 0; - - depth_peels.first = depth_peels.last = NULL; - - peelObjects(&depth_peels, dd->mval); - - if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) - { - last_p = stk->points[stk->nb_points - 1].p; - } - else if (LAST_SNAP_POINT_VALID) - { - last_p = LAST_SNAP_POINT; - } - - - for (p1 = depth_peels.first; p1; p1 = p1->next) - { - if (p1->flag == 0) - { - float vec[3]; - float new_dist; - - p2 = NULL; - p1->flag = 1; - /* if peeling objects, take the first and last from each object */ - if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT) + if (G.scene->snap_mode == SCE_SNAP_MODE_VOLUME) + { + ListBase depth_peels; + DepthPeel *p1, *p2; + float *last_p = NULL; + float dist = FLT_MAX; + float p[3]; + + depth_peels.first = depth_peels.last = NULL; + + peelObjects(&depth_peels, dd->mval); + + if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) + { + last_p = stk->points[stk->nb_points - 1].p; + } + else if (LAST_SNAP_POINT_VALID) + { + last_p = LAST_SNAP_POINT; + } + + + for (p1 = depth_peels.first; p1; p1 = p1->next) + { + if (p1->flag == 0) { - SK_DepthPeel *peel; - for (peel = p1->next; peel; peel = peel->next) + float vec[3]; + float new_dist; + + p2 = NULL; + p1->flag = 1; + + /* if peeling objects, take the first and last from each object */ + if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT) { - if (peel->ob == p1->ob) + DepthPeel *peel; + for (peel = p1->next; peel; peel = peel->next) { - peel->flag = 1; - p2 = peel; + if (peel->ob == p1->ob) + { + peel->flag = 1; + p2 = peel; + } } } - } - /* otherwise, pair first with second and so on */ - else - { - for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + /* otherwise, pair first with second and so on */ + else { - /* nothing to do here */ + for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + { + /* nothing to do here */ + } + } + + if (p2) + { + p2->flag = 1; + + VecAddf(vec, p1->p, p2->p); + VecMulf(vec, 0.5f); + } + else + { + VECCOPY(vec, p1->p); + } + + if (last_p == NULL) + { + VECCOPY(p, vec); + dist = 0; + break; + } + + new_dist = VecLenf(last_p, vec); + + if (new_dist < dist) + { + VECCOPY(p, vec); + dist = new_dist; } } + } + + if (dist != FLT_MAX) + { + pt->type = dd->type; + pt->mode = PT_EMBED; + VECCOPY(pt->p, p); - if (p2) - { - p2->flag = 1; - - VecAddf(vec, p1->p, p2->p); - VecMulf(vec, 0.5f); - } - else - { - VECCOPY(vec, p1->p); - } + point_added = 1; + } + + BLI_freelistN(&depth_peels); + } + else + { + float vec[3]; + float no[3]; + int found = 0; + int dist = 40; // Use a user defined value here + + found = snapObjects(&dist, vec, no, NOT_SELECTED); + if (found == 1) + { + pt->type = dd->type; + pt->mode = PT_EMBED; + VECCOPY(pt->p, vec); - if (last_p == NULL) - { - VECCOPY(p, vec); - dist = 0; - break; - } - - new_dist = VecLenf(last_p, vec); - - if (new_dist < dist) - { - VECCOPY(p, vec); - dist = new_dist; - } + point_added = 1; } } - if (dist != FLT_MAX) - { - pt->type = dd->type; - pt->mode = PT_EMBED; - VECCOPY(pt->p, p); - - point_added = 1; - } - - BLI_freelistN(&depth_peels); - return point_added; } diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 878213e80a3..53be105f7a8 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -5218,6 +5218,7 @@ static char *snapmode_pup(void) str += sprintf(str, "%s", "|Vertex%x0"); str += sprintf(str, "%s", "|Edge%x1"); str += sprintf(str, "%s", "|Face%x2"); + str += sprintf(str, "%s", "|Volume%x3"); return string; } diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index eeb5eaeec10..1f21bda3b59 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -43,6 +43,7 @@ #include "BLI_arithb.h" #include "BLI_editVert.h" +#include "BLI_blenlib.h" #include "BDR_drawobject.h" @@ -57,6 +58,8 @@ #include "BIF_drawimage.h" #include "BIF_editmesh.h" +#include "BIF_transform.h" + #include "BKE_global.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -91,11 +94,6 @@ float RotationBetween(TransInfo *t, float p1[3], float p2[3]); float TranslationBetween(TransInfo *t, float p1[3], float p2[3]); float ResizeBetween(TransInfo *t, float p1[3], float p2[3]); -/* Modes */ -#define NOT_SELECTED 0 -#define NOT_ACTIVE 1 -int snapObjects(int *dist, float *loc, float *no, int mode); - /****************** IMPLEMENTATIONS *********************/ @@ -103,7 +101,7 @@ int BIF_snappingSupported(void) { int status = 0; - if (G.obedit == NULL || G.obedit->type==OB_MESH) /* only support object or mesh */ + if (G.obedit == NULL || ELEM(G.obedit->type, OB_MESH, OB_ARMATURE)) /* only support object, mesh, armature */ { status = 1; } @@ -277,7 +275,7 @@ void initSnapping(TransInfo *t) /* Edit mode */ if (t->tsnap.applySnap != NULL && // A snapping function actually exist (G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on - (G.obedit != NULL && G.obedit->type==OB_MESH) && // Temporary limited to edit mode meshes + (G.obedit != NULL && ELEM(G.obedit->type, OB_MESH, OB_ARMATURE)) && // Temporary limited to edit mode meshes and armatures ((t->flag & T_PROP_EDIT) == 0) ) // No PET, obviously { t->tsnap.status |= SNAP_ON; @@ -481,87 +479,167 @@ void CalcSnapGrid(TransInfo *t, float *vec) void CalcSnapGeometry(TransInfo *t, float *vec) { - /* Object mode */ - if (G.obedit == NULL) + if (t->spacetype == SPACE_VIEW3D) { - if (t->spacetype == SPACE_VIEW3D) + float loc[3]; + float no[3]; + int found = 0; + int dist = 40; // Use a user defined value here + SnapMode mode; + + if (G.scene->snap_mode == SCE_SNAP_MODE_VOLUME) { - float vec[3]; - float no[3]; - int found = 0; - int dist = 40; // Use a user defined value here + ListBase depth_peels; + DepthPeel *p1, *p2; + float *last_p = NULL; + float dist = FLT_MAX; + float p[3]; + short mval[2]; + + getmouseco_areawin(mval); - found = snapObjects(&dist, vec, no, NOT_SELECTED); - if (found == 1) + depth_peels.first = depth_peels.last = NULL; + + peelObjects(&depth_peels, mval); + +// if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) +// { +// last_p = stk->points[stk->nb_points - 1].p; +// } +// else if (LAST_SNAP_POINT_VALID) +// { +// last_p = LAST_SNAP_POINT; +// } + + + for (p1 = depth_peels.first; p1; p1 = p1->next) { - float tangent[3]; - - VecSubf(tangent, vec, t->tsnap.snapPoint); - tangent[2] = 0; - - if (Inpf(tangent, tangent) > 0) + if (p1->flag == 0) { - VECCOPY(t->tsnap.snapTangent, tangent); + float vec[3]; + float new_dist; + + p2 = NULL; + p1->flag = 1; + + /* if peeling objects, take the first and last from each object */ + if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT) + { + DepthPeel *peel; + for (peel = p1->next; peel; peel = peel->next) + { + if (peel->ob == p1->ob) + { + peel->flag = 1; + p2 = peel; + } + } + } + /* otherwise, pair first with second and so on */ + else + { + for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) + { + /* nothing to do here */ + } + } + + if (p2) + { + p2->flag = 1; + + VecAddf(vec, p1->p, p2->p); + VecMulf(vec, 0.5f); + } + else + { + VECCOPY(vec, p1->p); + } + + if (last_p == NULL) + { + VECCOPY(p, vec); + dist = 0; + break; + } + + new_dist = VecLenf(last_p, vec); + + if (new_dist < dist) + { + VECCOPY(p, vec); + dist = new_dist; + } } - - VECCOPY(t->tsnap.snapPoint, vec); - VECCOPY(t->tsnap.snapNormal, no); - - t->tsnap.status |= POINT_INIT; + } + + if (dist != FLT_MAX) + { + VECCOPY(loc, p); + found = 1; + } + + BLI_freelistN(&depth_peels); + } + else + { + if (G.obedit == NULL) + { + mode = NOT_SELECTED; } else { - t->tsnap.status &= ~POINT_INIT; + mode = NOT_ACTIVE; } + + found = snapObjects(&dist, loc, no, NOT_SELECTED); + } + + if (found == 1) + { + float tangent[3]; + + VecSubf(tangent, loc, t->tsnap.snapPoint); + tangent[2] = 0; + + if (Inpf(tangent, tangent) > 0) + { + VECCOPY(t->tsnap.snapTangent, tangent); + } + + VECCOPY(t->tsnap.snapPoint, loc); + VECCOPY(t->tsnap.snapNormal, no); + + t->tsnap.status |= POINT_INIT; + } + else + { + t->tsnap.status &= ~POINT_INIT; } } - /* Mesh edit mode */ - else if (G.obedit != NULL && G.obedit->type==OB_MESH) - { - if (t->spacetype == SPACE_VIEW3D) + else if (t->spacetype == SPACE_IMAGE && G.obedit != NULL && G.obedit->type==OB_MESH) + { /* same as above but for UV's */ + MTFace *nearesttf=NULL; + float aspx, aspy; + int face_corner; + + find_nearest_uv(&nearesttf, NULL, NULL, &face_corner); + + if (nearesttf != NULL) { - float vec[3]; - float no[3]; - int found = 0; - int dist = 40; // Use a user defined value here + VECCOPY2D(t->tsnap.snapPoint, nearesttf->uv[face_corner]); - found = snapObjects(&dist, vec, no, NOT_ACTIVE); - if (found == 1) - { - VECCOPY(t->tsnap.snapPoint, vec); - VECCOPY(t->tsnap.snapNormal, no); - - t->tsnap.status |= POINT_INIT; - } - else - { - t->tsnap.status &= ~POINT_INIT; - } - } - else if (t->spacetype == SPACE_IMAGE) - { /* same as above but for UV's */ - MTFace *nearesttf=NULL; - float aspx, aspy; - int face_corner; + transform_aspect_ratio_tface_uv(&aspx, &aspy); + t->tsnap.snapPoint[0] *= aspx; + t->tsnap.snapPoint[1] *= aspy; + + //Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint); - find_nearest_uv(&nearesttf, NULL, NULL, &face_corner); - - if (nearesttf != NULL) - { - VECCOPY2D(t->tsnap.snapPoint, nearesttf->uv[face_corner]); - - transform_aspect_ratio_tface_uv(&aspx, &aspy); - t->tsnap.snapPoint[0] *= aspx; - t->tsnap.snapPoint[1] *= aspy; - - //Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint); - - t->tsnap.status |= POINT_INIT; - } - else - { - t->tsnap.status &= ~POINT_INIT; - } + t->tsnap.status |= POINT_INIT; + } + else + { + t->tsnap.status &= ~POINT_INIT; } } } @@ -824,7 +902,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta if (test) { - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL); + result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001); if (result) { float location[3], normal[3]; @@ -868,7 +946,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta if (f->v4 && result == 0) { - result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL); + result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001); if (result) { float location[3], normal[3]; @@ -1149,7 +1227,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta return retval; } -int snapObjects(int *dist, float *loc, float *no, int mode) { +int snapObjects(int *dist, float *loc, float *no, SnapMode mode) { Base *base; float depth = FLT_MAX; int retval = 0; @@ -1164,11 +1242,14 @@ int snapObjects(int *dist, float *loc, float *no, int mode) { DerivedMesh *dm; Object *ob = G.obedit; - dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); - - retval = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 1); - - dm->release(dm); + if (ob->type == OB_MESH) + { + dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); + + retval = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 1); + + dm->release(dm); + } } base= FIRSTBASE; @@ -1227,6 +1308,238 @@ int snapObjects(int *dist, float *loc, float *no, int mode) { return retval; } +/******************** PEELING *********************************/ + + +int cmpPeel(void *arg1, void *arg2) +{ + DepthPeel *p1 = arg1; + DepthPeel *p2 = arg2; + int val = 0; + + if (p1->depth < p2->depth) + { + val = -1; + } + else if (p1->depth > p2->depth) + { + val = 1; + } + + return val; +} + +void removeDoublesPeel(ListBase *depth_peels) +{ + DepthPeel *peel; + + for (peel = depth_peels->first; peel; peel = peel->next) + { + DepthPeel *next_peel = peel->next; + + if (peel && next_peel && ABS(peel->depth - next_peel->depth) < 0.0015) + { + peel->next = next_peel->next; + + if (next_peel->next) + { + next_peel->next->prev = peel; + } + + MEM_freeN(next_peel); + } + } +} + +void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob) +{ + DepthPeel *peel = MEM_callocN(sizeof(DepthPeel), "DepthPeel"); + + peel->depth = depth; + peel->ob = ob; + VECCOPY(peel->p, p); + VECCOPY(peel->no, no); + + BLI_addtail(depth_peels, peel); + + peel->flag = 0; +} + +int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels) +{ + int retval = 0; + int totvert = dm->getNumVerts(dm); + int totface = dm->getNumFaces(dm); + + if (totvert > 0) { + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_start_local[3], ray_normal_local[3]; + int test = 1; + + Mat4Invert(imat, obmat); + + Mat3CpyMat4(timat, imat); + Mat3Transp(timat); + + VECCOPY(ray_start_local, ray_start); + VECCOPY(ray_normal_local, ray_normal); + + Mat4MulVecfl(imat, ray_start_local); + Mat4Mul3Vecfl(imat, ray_normal_local); + + + /* If number of vert is more than an arbitrary limit, + * test against boundbox first + * */ + if (totface > 16) { + struct BoundBox *bb = object_get_boundbox(ob); + test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local); + } + + if (test == 1) { + MVert *verts = dm->getVertArray(dm); + MFace *faces = dm->getFaceArray(dm); + int i; + + for( i = 0; i < totface; i++) { + MFace *f = faces + i; + float lambda; + int result; + + + result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001); + + if (result) { + float location[3], normal[3]; + float intersect[3]; + float new_depth; + + VECCOPY(intersect, ray_normal_local); + VecMulf(intersect, lambda); + VecAddf(intersect, intersect, ray_start_local); + + VECCOPY(location, intersect); + + if (f->v4) + CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); + else + CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + Mat3MulVecfl(timat, normal); + Normalize(normal); + + addDepthPeel(depth_peels, new_depth, location, normal, ob); + } + + if (f->v4 && result == 0) + { + result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001); + + if (result) { + float location[3], normal[3]; + float intersect[3]; + float new_depth; + + VECCOPY(intersect, ray_normal_local); + VecMulf(intersect, lambda); + VecAddf(intersect, intersect, ray_start_local); + + VECCOPY(location, intersect); + + if (f->v4) + CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); + else + CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + Mat3MulVecfl(timat, normal); + Normalize(normal); + + addDepthPeel(depth_peels, new_depth, location, normal, ob); + } + } + } + } + } + + return retval; +} + +int peelObjects(ListBase *depth_peels, short mval[2]) +{ + Base *base; + int retval = 0; + float ray_start[3], ray_normal[3]; + + viewray(mval, ray_start, ray_normal); + + base= FIRSTBASE; + for ( base = FIRSTBASE; base != NULL; base = base->next ) { + if ( BASE_SELECTABLE(base) ) { + Object *ob = base->object; + + if (ob->transflag & OB_DUPLI) + { + DupliObject *dupli_ob; + ListBase *lb = object_duplilist(G.scene, ob); + + for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) + { + Object *ob = dupli_ob->ob; + + if (ob->type == OB_MESH) { + DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + int val; + + val = peelDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, depth_peels); + + retval = retval || val; + + dm->release(dm); + } + } + + free_object_duplilist(lb); + } + + if (ob->type == OB_MESH) { + DerivedMesh *dm = NULL; + int val; + + if (ob != G.obedit) + { + dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + + val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); + } + else + { + dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); + + val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); + } + + retval = retval || val; + + dm->release(dm); + } + } + } + + BLI_sortlist(depth_peels, cmpPeel); + removeDoublesPeel(depth_peels); + + return retval; +} + /*================================================================*/ static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action); From 394d893e13257cb0fc5bec815e2111c12d5ed4ec Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Feb 2009 03:29:31 +0000 Subject: [PATCH 205/252] compile scripts when converting controllers to give more predictable performance and print syntax errors early on rather then when the script is first executed. --- .../Converter/KX_ConvertControllers.cpp | 7 ++ .../GameLogic/SCA_PythonController.cpp | 69 ++++++++++++------- .../GameLogic/SCA_PythonController.h | 1 + 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp index da490b4ee85..fb100b0a68b 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.cpp +++ b/source/gameengine/Converter/KX_ConvertControllers.cpp @@ -200,6 +200,13 @@ void BL_ConvertControllers( gameobj->AddController(gamecontroller); converter->RegisterGameController(gamecontroller, bcontr); + + if (bcontr->type==CONT_PYTHON) { + /* not strictly needed but gives syntax errors early on and + * gives more pradictable performance for larger scripts */ + (static_cast(gamecontroller))->Compile(); + } + //done with gamecontroller gamecontroller->Release(); } diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 2fff21f22fb..5ab8db2986d 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -242,6 +242,43 @@ PyMethodDef SCA_PythonController::Methods[] = { }; +bool SCA_PythonController::Compile() +{ + //printf("py script modified '%s'\n", m_scriptName.Ptr()); + + // if a script already exists, decref it before replace the pointer to a new script + if (m_bytecode) + { + Py_DECREF(m_bytecode); + m_bytecode=NULL; + } + // recompile the scripttext into bytecode + m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input); + m_bModified=false; + + if (m_bytecode) + { + + return true; + } + else { + // didn't compile, so instead of compile, complain + // something is wrong, tell the user what went wrong + printf("Python compile error from controller \"%s\": \n", GetName().Ptr()); + //PyRun_SimpleString(m_scriptText.Ptr()); + PyErr_Print(); + + /* Added in 2.48a, the last_traceback can reference Objects for example, increasing + * their user count. Not to mention holding references to wrapped data. + * This is especially bad when the PyObject for the wrapped data is free'd, after blender + * has alredy dealocated the pointer */ + PySys_SetObject( (char *)"last_traceback", Py_None); + PyErr_Clear(); /* just to be sure */ + + return false; + } +} + void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) { m_sCurrentController = this; @@ -249,33 +286,13 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) if (m_bModified) { - // if a script already exists, decref it before replace the pointer to a new script - if (m_bytecode) - { - Py_DECREF(m_bytecode); - m_bytecode=NULL; - } - // recompile the scripttext into bytecode - m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input); - if (!m_bytecode) - { - // didn't compile, so instead of compile, complain - // something is wrong, tell the user what went wrong - printf("Python compile error from controller \"%s\": \n", GetName().Ptr()); - //PyRun_SimpleString(m_scriptText.Ptr()); - PyErr_Print(); - - /* Added in 2.48a, the last_traceback can reference Objects for example, increasing - * their user count. Not to mention holding references to wrapped data. - * This is especially bad when the PyObject for the wrapped data is free'd, after blender - * has alredy dealocated the pointer */ - PySys_SetObject( "last_traceback", Py_None); - PyErr_Clear(); /* just to be sure */ - + if (Compile()==false) // sets m_bModified to false return; - } - m_bModified=false; } + if (!m_bytecode) { + return; + } + /* * This part here with excdict is a temporary patch @@ -313,7 +330,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) * their user count. Not to mention holding references to wrapped data. * This is especially bad when the PyObject for the wrapped data is free'd, after blender * has alredy dealocated the pointer */ - PySys_SetObject( "last_traceback", Py_None); + PySys_SetObject( (char *)"last_traceback", Py_None); PyErr_Clear(); /* just to be sure */ //PyRun_SimpleString(m_scriptText.Ptr()); diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 00c30d7f3d5..046ef1f7aed 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -70,6 +70,7 @@ class SCA_PythonController : public SCA_IController void AddTriggeredSensor(class SCA_ISensor* sensor) { m_triggeredSensors.push_back(sensor); } int IsTriggered(class SCA_ISensor* sensor); + bool Compile(); static const char* sPyGetCurrentController__doc__; static PyObject* sPyGetCurrentController(PyObject* self); From 6c7c38a4e4892677f8e7db2b41115209901a2d35 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Feb 2009 05:50:45 +0000 Subject: [PATCH 206/252] BGE Py API * Made GameLogic.addActiveActuator(actu, bool) to raise an error if the actuator is not in the list. Before it would allow any value as the actuator and fail silently (makes debugging scripts more difficult). * Allow the actuator to be a string which is convenient if you dont want to change the settings of the actuator. * Added activate/deactivate functions to the controller, this is more logical since the GameLogic.addActiveActuator() function is running through the controller anyway. GameLogic.addActiveActuator(controller.getActuator("SomeAct"), True) ...can be replaced with... controller.activate("SomeAct") --- .../GameLogic/SCA_PythonController.cpp | 91 ++++++++++++++----- .../GameLogic/SCA_PythonController.h | 4 + source/gameengine/PyDoc/GameLogic.py | 2 +- source/gameengine/PyDoc/KX_Scene.py | 2 + .../gameengine/PyDoc/SCA_PythonController.py | 12 ++- 5 files changed, 86 insertions(+), 25 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 5ab8db2986d..92852ee03cb 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -157,8 +157,40 @@ static const char* sPyGetCurrentController__doc__; PyObject* SCA_PythonController::sPyGetCurrentController(PyObject* self) { - m_sCurrentController->AddRef(); - return m_sCurrentController; + return m_sCurrentController->AddRef(); +} + +SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) +{ + // for safety, todo: only allow for registered actuators (pointertable) + // we don't want to crash gameengine/blender by python scripts + std::vector lacts = m_sCurrentController->GetLinkedActuators(); + std::vector::iterator it; + + if (PyString_Check(value)) { + /* get the actuator from the name */ + char *name= PyString_AsString(value); + for(it = lacts.begin(); it!= lacts.end(); it++) { + if( name == (*it)->GetName() ) { + return *it; + } + } + } + else { + /* Expecting an actuator type */ + for(it = lacts.begin(); it!= lacts.end(); it++) { + if( static_cast(value) == (*it) ) { + return *it; + } + } + } + + /* set the exception */ + PyObject *value_str = PyObject_Repr(value); /* new ref */ + PyErr_Format(PyExc_ValueError, "'%s' not in this controllers actuator list", PyString_AsString(value_str)); + Py_DECREF(value_str); + + return false; } #if 0 @@ -175,26 +207,14 @@ PyObject* SCA_PythonController::sPyAddActiveActuator( int activate; if (!PyArg_ParseTuple(args, "Oi", &ob1,&activate)) return NULL; - - // for safety, todo: only allow for registered actuators (pointertable) - // we don't want to crash gameengine/blender by python scripts - std::vector lacts = m_sCurrentController->GetLinkedActuators(); - std::vector::iterator it; - bool found = false; - CValue* act = (CValue*)ob1; - - for(it = lacts.begin(); it!= lacts.end(); it++) { - if( static_cast(act) == (*it) ) { - found=true; - break; - } - } - if(found){ - CValue* boolval = new CBoolValue(activate!=0); - m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)act,boolval); - boolval->Release(); - } + SCA_IActuator* actu = LinkedActuatorFromPy(ob1); + if(actu==NULL) + return NULL; + + CValue* boolval = new CBoolValue(activate!=0); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu,boolval); + boolval->Release(); Py_RETURN_NONE; } @@ -229,6 +249,9 @@ PyParentObject SCA_PythonController::Parents[] = { NULL }; PyMethodDef SCA_PythonController::Methods[] = { + {"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O}, + {"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O}, + {"getActuators", (PyCFunction) SCA_PythonController::sPyGetActuators, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetActuators_doc}, {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc}, {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc}, @@ -380,6 +403,29 @@ int SCA_PythonController::_setattr(const char *attr, PyObject *value) return SCA_IController::_setattr(attr, value); } +PyObject* SCA_PythonController::PyActivate(PyObject* self, PyObject *value) +{ + SCA_IActuator* actu = LinkedActuatorFromPy(value); + if(actu==NULL) + return NULL; + + CValue* boolval = new CBoolValue(true); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval); + boolval->Release(); + Py_RETURN_NONE; +} + +PyObject* SCA_PythonController::PyDeActivate(PyObject* self, PyObject *value) +{ + SCA_IActuator* actu = LinkedActuatorFromPy(value); + if(actu==NULL) + return NULL; + + CValue* boolval = new CBoolValue(false); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval); + boolval->Release(); + Py_RETURN_NONE; +} PyObject* SCA_PythonController::PyGetActuators(PyObject* self) { @@ -437,8 +483,7 @@ SCA_PythonController::PyGetActuator(PyObject* self, PyObject* value) for (unsigned int index=0;indexGetName(); - if (realname == scriptArg) + if (actua->GetName() == scriptArg) { return actua->AddRef(); } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 046ef1f7aed..4ec18f32c23 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -77,9 +77,13 @@ class SCA_PythonController : public SCA_IController static const char* sPyAddActiveActuator__doc__; static PyObject* sPyAddActiveActuator(PyObject* self, PyObject* args); + static SCA_IActuator* LinkedActuatorFromPy(PyObject *value); virtual PyObject* _getattr(const char *attr); virtual int _setattr(const char *attr, PyObject *value); + + KX_PYMETHOD_O(SCA_PythonController,Activate); + KX_PYMETHOD_O(SCA_PythonController,DeActivate); KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetSensors); KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetActuators); KX_PYMETHOD_DOC_O(SCA_PythonController,GetSensor); diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index 9dab7db6081..f743acf06fe 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -159,7 +159,7 @@ def addActiveActuator(actuator, activate): """ Activates the given actuator. - @type actuator: L{SCA_IActuator} + @type actuator: L{SCA_IActuator} or the actuator name as a string. @type activate: boolean @param activate: whether to activate or deactivate the given actuator. """ diff --git a/source/gameengine/PyDoc/KX_Scene.py b/source/gameengine/PyDoc/KX_Scene.py index 4a0a7a9556d..24b81bbf55e 100644 --- a/source/gameengine/PyDoc/KX_Scene.py +++ b/source/gameengine/PyDoc/KX_Scene.py @@ -39,6 +39,8 @@ class KX_Scene: @ivar name: The scene's name @type name: string + @type objects: A list of objects in the scene. + @type objects: list [L{KX_GameObject}] @ivar active_camera: The current active camera @type active_camera: L{KX_Camera} @ivar suspended: True if the scene is suspended. diff --git a/source/gameengine/PyDoc/SCA_PythonController.py b/source/gameengine/PyDoc/SCA_PythonController.py index 06f2b7e9d1d..9684b41d481 100644 --- a/source/gameengine/PyDoc/SCA_PythonController.py +++ b/source/gameengine/PyDoc/SCA_PythonController.py @@ -15,7 +15,17 @@ class SCA_PythonController(SCA_IController): This can be used with the GameObject's state to test if the controller is active. @type state: integer """ - + def activate(actuator): + """ + Activates an actuator attached to this controller. + @type actuator: actuator or the actuator name as a string + """ + def deactivate(actuator): + """ + Deactivates an actuator attached to this controller. + @type actuator: actuator or the actuator name as a string + """ + def getSensors(): """ Gets a list of all sensors attached to this controller. From 33aee345ed5b1e77b07f693fbea525dec7f728e7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Feb 2009 09:49:28 +0000 Subject: [PATCH 207/252] fix for segfault when the replace mesh actuator references a mesh that has no object in the current scene. --- source/gameengine/Ketsji/KX_Scene.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 7fcbf5b54bb..5ae1abc6a89 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1014,6 +1014,12 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) blendmesh->dvert!=NULL; // mesh has vertex group bool releaseParent = true; + + if (oldblendobj==NULL) { + std::cout << "warning: ReplaceMesh() new mesh is not used in an object from the current scene, you will get incorrect behavior" << std::endl; + bHasShapeKey= bHasDvert= bHasArmature= false; + } + if (bHasShapeKey) { BL_ShapeDeformer* shapeDeformer; From adaa4b0fd0c7dde64b9610b68188052d4d8a628c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Feb 2009 12:38:56 +0000 Subject: [PATCH 208/252] Making KX_GameObject names read only. This was committed in revision 2832 but never accounted for existing object name hashes which existed since revision 2. Its possible to update the names elsewhere but unlikely anyone ever used this successfully so removing. --- source/gameengine/Ketsji/KX_GameObject.cpp | 6 ++++++ source/gameengine/PyDoc/KX_GameObject.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 82b5fff534c..37f16b92a26 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1279,8 +1279,14 @@ int KX_GameObject::_setattr(const char *attr, PyObject *value) // _setattr metho { if (!strcmp(attr, "name")) { +#if 0 // was added in revision 2832, but never took into account Object name mappings from revision 2 + // unlikely anyone ever used this successfully , removing. m_name = PyString_AsString(value); return 0; +#else + PyErr_SetString(PyExc_AttributeError, "object name readonly"); + return 1; +#endif } } diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index efeffab2eed..4f389a1ae4f 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -7,7 +7,7 @@ class KX_GameObject: Properties assigned to game objects are accessible as attributes of this class. - @ivar name: The object's name. + @ivar name: The object's name. (Read only) @type name: string. @ivar mass: The object's mass (provided the object has a physics controller). Read only. @type mass: float From 56e9c87309e155d6710067759c415279848b6bea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Feb 2009 17:34:41 +0000 Subject: [PATCH 209/252] building the game engine without SDL works again --- source/blender/blenkernel/SConscript | 2 ++ source/gameengine/Ketsji/SConscript | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index fb67c855b81..a7e4d8807b2 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -28,6 +28,8 @@ if env['WITH_BF_QUICKTIME']: if env['WITH_BF_SDL']: incs += ' ' + env['BF_SDL_INC'] +else: + defs += ' DISABLE_SDL' if env['WITH_BF_INTERNATIONAL']: defs += ' WITH_FREETYPE2' diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index e9e68f14df8..40cbc35e7f3 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -4,6 +4,7 @@ import sys Import ('env') sources = env.Glob('*.cpp') +defs = '' # Mathutils C files. sources.extend([\ @@ -41,10 +42,12 @@ incs += ' ' + env['BF_OPENGL_INC'] if env['WITH_BF_SDL']: incs += ' ' + env['BF_SDL_INC'] - +else: + defs += ' DISABLE_SDL' + cxxflags = [] if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/GR') cxxflags.append ('/O2') -env.BlenderLib ( 'bf_ketsji', sources, Split(incs), [], libtype=['game','player'], priority=[25, 72], cxx_compileflags = cxxflags ) +env.BlenderLib ( 'bf_ketsji', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], cxx_compileflags = cxxflags ) From aa7c45c190db386e05f9ebee00275bc5e35db99a Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 24 Feb 2009 21:25:36 +0000 Subject: [PATCH 210/252] Snaping cleanup, removing a lot of duplicate code. Snapping to armatures: non-editmode armatures only, rest pose only, ... (this is mostly work in progress code). --- source/blender/src/transform_snap.c | 449 ++++++++++++++++------------ 1 file changed, 259 insertions(+), 190 deletions(-) diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 1f21bda3b59..3353c209d67 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -33,6 +33,7 @@ #include "PIL_time.h" +#include "DNA_armature_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_meshdata_types.h" // Temporary, for snapping to other unselected meshes @@ -815,6 +816,244 @@ void TargetSnapClosest(TransInfo *t) } /*================================================================*/ +int snapFace(float v1co[3], float v2co[3], float v3co[3], float *v4co, short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth) +{ + float lambda; + int result; + int retval = 0; + + result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, v1co, v2co, v3co, &lambda, NULL, 0.001); + + if (result) { + float location[3], normal[3]; + float intersect[3]; + float new_depth; + int screen_loc[2]; + int new_dist; + + VECCOPY(intersect, ray_normal_local); + VecMulf(intersect, lambda); + VecAddf(intersect, intersect, ray_start_local); + + VECCOPY(location, intersect); + + if (v4co) + CalcNormFloat4(v1co, v2co, v3co, v4co, normal); + else + CalcNormFloat(v1co, v2co, v3co, normal); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + project_int(location, screen_loc); + new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); + + if (new_dist <= *dist && new_depth < *depth) + { + *depth = new_depth; + retval = 1; + + VECCOPY(loc, location); + VECCOPY(no, normal); + + Mat3MulVecfl(timat, no); + Normalize(no); + + *dist = new_dist; + } + } + + return retval; +} + +int snapEdge(float v1co[3], short v1no[3], float v2co[3], short v2no[3], short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth) +{ + float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; + int result; + int retval = 0; + + VECCOPY(ray_end, ray_normal_local); + VecMulf(ray_end, 2000); + VecAddf(ray_end, ray_start_local, ray_end); + + result = LineIntersectLine(v1co, v2co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */ + + if (result) + { + float edge_loc[3], vec[3]; + float mul; + + /* check for behind ray_start */ + VecSubf(dvec, intersect, ray_start_local); + + VecSubf(edge_loc, v1co, v2co); + VecSubf(vec, intersect, v2co); + + mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); + + if (mul > 1) { + mul = 1; + VECCOPY(intersect, v1co); + } + else if (mul < 0) { + mul = 0; + VECCOPY(intersect, v2co); + } + + if (Inpf(ray_normal_local, dvec) > 0) + { + float location[3]; + float new_depth; + int screen_loc[2]; + int new_dist; + + VECCOPY(location, intersect); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + project_int(location, screen_loc); + new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); + + /* 10% threshold if edge is closer but a bit further + * this takes care of series of connected edges a bit slanted w.r.t the viewport + * otherwise, it would stick to the verts of the closest edge and not slide along merrily + * */ + if (new_dist <= *dist && new_depth < *depth * 1.01) + { + float n1[3], n2[3]; + + *depth = new_depth; + retval = 1; + + VecSubf(edge_loc, v1co, v2co); + VecSubf(vec, intersect, v2co); + + mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); + + if (no) + { + NormalShortToFloat(n1, v1no); + NormalShortToFloat(n2, v2no); + VecLerpf(no, n2, n1, mul); + Mat3MulVecfl(timat, no); + Normalize(no); + } + + VECCOPY(loc, location); + + *dist = new_dist; + } + } + } + + return retval; +} + +int snapVertex(float vco[3], short vno[3], short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth) +{ + int retval = 0; + float dvec[3]; + + VecSubf(dvec, vco, ray_start_local); + + if (Inpf(ray_normal_local, dvec) > 0) + { + float location[3]; + float new_depth; + int screen_loc[2]; + int new_dist; + + VECCOPY(location, vco); + + Mat4MulVecfl(obmat, location); + + new_depth = VecLenf(location, ray_start); + + project_int(location, screen_loc); + new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); + + if (new_dist <= *dist && new_depth < *depth) + { + *depth = new_depth; + retval = 1; + + VECCOPY(loc, location); + + if (no) + { + NormalShortToFloat(no, vno); + Mat3MulVecfl(timat, no); + Normalize(no); + } + + *dist = new_dist; + } + } + + return retval; +} + +int snapArmature(Object *ob, bArmature *ar, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth) +{ + Bone *b = ar->bonebase.first; + float imat[4][4]; + float ray_start_local[3], ray_normal_local[3]; + int retval = 0; + + Mat4Invert(imat, obmat); + + VECCOPY(ray_start_local, ray_start); + VECCOPY(ray_normal_local, ray_normal); + + Mat4MulVecfl(imat, ray_start_local); + Mat4Mul3Vecfl(imat, ray_normal_local); + + while(b) + { + switch (G.scene->snap_mode) + { + case SCE_SNAP_MODE_VERTEX: + retval |= snapVertex(b->arm_head, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + retval |= snapVertex(b->arm_tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + break; + case SCE_SNAP_MODE_EDGE: + retval |= snapEdge(b->arm_head, NULL, b->arm_tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + break; + } + + + if (b->childbase.first != NULL) + { + b = b->childbase.first; + } + else + { + while(1) + { + if (b->next != NULL) + { + b = b->next; + break; + } + else if (b->parent != NULL) + { + b = b->parent; + } + else /* nothing to go to */ + { + b = NULL; + break; + } + } + } + } + + return retval; +} + int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth, short EditMesh) { int retval = 0; @@ -868,8 +1107,6 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta for( i = 0; i < totface; i++) { EditFace *efa = NULL; MFace *f = faces + i; - float lambda; - int result; test = 1; /* reset for every face */ @@ -902,91 +1139,20 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta if (test) { - result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL, 0.001); + int result; + float *v4co = NULL; - if (result) { - float location[3], normal[3]; - float intersect[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - VECCOPY(location, intersect); - - if (f->v4) - CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); - else - CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) - { - *depth = new_depth; - retval = 1; - - VECCOPY(loc, location); - VECCOPY(no, normal); - - Mat3MulVecfl(timat, no); - Normalize(no); - - *dist = new_dist; - } + if (f->v4) + { + v4co = verts[f->v4].co; } - + + result = snapFace(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, v4co, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); + retval |= result; + if (f->v4 && result == 0) { - result = RayIntersectsTriangleThreshold(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL, 0.001); - - if (result) { - float location[3], normal[3]; - float intersect[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - VECCOPY(intersect, ray_normal_local); - VecMulf(intersect, lambda); - VecAddf(intersect, intersect, ray_start_local); - - VECCOPY(location, intersect); - - if (f->v4) - CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal); - else - CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) - { - *depth = new_depth; - retval = 1; - - VECCOPY(loc, location); - VECCOPY(no, normal); - - Mat3MulVecfl(timat, no); - Normalize(no); - - *dist = new_dist; - } - } + retval |= snapFace(verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, verts[f->v2].co, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); } } } @@ -1045,40 +1211,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta if (test) { - float dvec[3]; - - VecSubf(dvec, v->co, ray_start_local); - - if (Inpf(ray_normal_local, dvec) > 0) - { - float location[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - VECCOPY(location, v->co); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) - { - *depth = new_depth; - retval = 1; - - VECCOPY(loc, location); - - NormalShortToFloat(no, v->no); - Mat3MulVecfl(timat, no); - Normalize(no); - - *dist = new_dist; - } - } + retval |= snapVertex(v->co, v->no, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); } } @@ -1138,79 +1271,7 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta if (test) { - float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; - int result; - - VECCOPY(ray_end, ray_normal_local); - VecMulf(ray_end, 2000); - VecAddf(ray_end, ray_start_local, ray_end); - - result = LineIntersectLine(verts[e->v1].co, verts[e->v2].co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */ - - if (result) - { - float edge_loc[3], vec[3]; - float mul; - - /* check for behind ray_start */ - VecSubf(dvec, intersect, ray_start_local); - - VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co); - VecSubf(vec, intersect, verts[e->v2].co); - - mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); - - if (mul > 1) { - mul = 1; - VECCOPY(intersect, verts[e->v1].co); - } - else if (mul < 0) { - mul = 0; - VECCOPY(intersect, verts[e->v2].co); - } - - if (Inpf(ray_normal_local, dvec) > 0) - { - float location[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - VECCOPY(location, intersect); - - Mat4MulVecfl(obmat, location); - - new_depth = VecLenf(location, ray_start); - - project_int(location, screen_loc); - new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]); - - if (new_dist <= *dist && new_depth < *depth) - { - float n1[3], n2[3]; - - *depth = new_depth; - retval = 1; - - VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co); - VecSubf(vec, intersect, verts[e->v2].co); - - mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc); - - NormalShortToFloat(n1, verts[e->v1].no); - NormalShortToFloat(n2, verts[e->v2].no); - VecLerpf(no, n2, n1, mul); - Normalize(no); - - VECCOPY(loc, location); - - Mat3MulVecfl(timat, no); - Normalize(no); - - *dist = new_dist; - } - } - } + retval |= snapEdge(verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); } } @@ -1302,6 +1363,14 @@ int snapObjects(int *dist, float *loc, float *no, SnapMode mode) { dm->release(dm); } + else if (ob->type == OB_ARMATURE) + { + int val; + + val = snapArmature(ob, ob->data, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth); + + retval = retval || val; + } } } From 2eb85c01f3e0ea2ba9dd129ae70e8b370953d7b5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Feb 2009 03:26:02 +0000 Subject: [PATCH 211/252] remove warnings for the BGE - variables that shadow vers declared earlier - Py_Fatal print an error to the stderr - gcc was complaining about the order of initialized vars (for classes) - const return values for ints and bools didnt do anything. - braces for ambiguous if statements --- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 2 + .../Converter/BL_BlenderDataConversion.cpp | 32 ++++++------ source/gameengine/Converter/KX_IpoConvert.cpp | 50 +++++++++---------- source/gameengine/Expressions/InputParser.cpp | 2 +- .../gameengine/Expressions/PyObjectPlus.cpp | 2 +- source/gameengine/Expressions/PyObjectPlus.h | 2 +- .../GameLogic/Joystick/SCA_Joystick.cpp | 8 +-- .../gameengine/GameLogic/SCA_DelaySensor.cpp | 6 +-- source/gameengine/GameLogic/SCA_IActuator.cpp | 4 +- source/gameengine/GameLogic/SCA_IActuator.h | 2 +- .../gameengine/GameLogic/SCA_IController.cpp | 4 +- source/gameengine/GameLogic/SCA_IObject.cpp | 2 +- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 4 +- source/gameengine/Ketsji/BL_Shader.cpp | 4 +- source/gameengine/Ketsji/BL_Shader.h | 2 +- .../Ketsji/KX_BulletPhysicsController.cpp | 6 +-- .../Ketsji/KX_ConstraintActuator.cpp | 4 +- source/gameengine/Ketsji/KX_GameActuator.cpp | 2 +- source/gameengine/Ketsji/KX_GameObject.cpp | 15 +++--- .../gameengine/Ketsji/KX_IPO_SGController.cpp | 2 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 2 +- source/gameengine/Ketsji/KX_NearSensor.cpp | 2 +- .../gameengine/Ketsji/KX_ObjectActuator.cpp | 6 +-- source/gameengine/Ketsji/KX_PolyProxy.cpp | 4 +- source/gameengine/Ketsji/KX_PythonInit.cpp | 8 +-- source/gameengine/Ketsji/KX_SoundActuator.cpp | 2 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 8 +-- .../Rasterizer/RAS_IPolygonMaterial.cpp | 2 +- .../Rasterizer/RAS_IPolygonMaterial.h | 2 +- source/gameengine/Rasterizer/RAS_TexVert.h | 2 +- source/gameengine/VideoTexture/FilterBase.cpp | 2 +- source/gameengine/VideoTexture/FilterSource.h | 8 ++- 32 files changed, 104 insertions(+), 99 deletions(-) diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 67bec97ea32..d89d2d80ab4 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -563,10 +563,12 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, // get some preferences SYS_SystemHandle syshandle = SYS_GetSystem(); + /* bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0); bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0); bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); + */ bool game2ipo = true;//(SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0); bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0); bool usemat = false; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 2fa3e192179..3293d37af3a 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1997,18 +1997,18 @@ void BL_ConvertBlenderObjects(struct Main* maggie, MT_Vector3 x(ori.getColumn(0)); MT_Vector3 y(ori.getColumn(1)); MT_Vector3 z(ori.getColumn(2)); - MT_Vector3 scale(x.length(), y.length(), z.length()); - if (!MT_fuzzyZero(scale[0])) - x /= scale[0]; - if (!MT_fuzzyZero(scale[1])) - y /= scale[1]; - if (!MT_fuzzyZero(scale[2])) - z /= scale[2]; + MT_Vector3 parscale(x.length(), y.length(), z.length()); + if (!MT_fuzzyZero(parscale[0])) + x /= parscale[0]; + if (!MT_fuzzyZero(parscale[1])) + y /= parscale[1]; + if (!MT_fuzzyZero(parscale[2])) + z /= parscale[2]; ori.setColumn(0, x); ori.setColumn(1, y); ori.setColumn(2, z); parentinversenode->SetLocalOrientation(ori); - parentinversenode->SetLocalScale(scale); + parentinversenode->SetLocalScale(parscale); parentinversenode->AddChild(gameobj->GetSGNode()); } @@ -2194,18 +2194,18 @@ void BL_ConvertBlenderObjects(struct Main* maggie, MT_Vector3 x(ori.getColumn(0)); MT_Vector3 y(ori.getColumn(1)); MT_Vector3 z(ori.getColumn(2)); - MT_Vector3 scale(x.length(), y.length(), z.length()); - if (!MT_fuzzyZero(scale[0])) - x /= scale[0]; - if (!MT_fuzzyZero(scale[1])) - y /= scale[1]; - if (!MT_fuzzyZero(scale[2])) - z /= scale[2]; + MT_Vector3 localscale(x.length(), y.length(), z.length()); + if (!MT_fuzzyZero(localscale[0])) + x /= localscale[0]; + if (!MT_fuzzyZero(localscale[1])) + y /= localscale[1]; + if (!MT_fuzzyZero(localscale[2])) + z /= localscale[2]; ori.setColumn(0, x); ori.setColumn(1, y); ori.setColumn(2, z); parentinversenode->SetLocalOrientation(ori); - parentinversenode->SetLocalScale(scale); + parentinversenode->SetLocalScale(localscale); parentinversenode->AddChild(gameobj->GetSGNode()); } diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index ce004fa0504..f19390db8a9 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -311,67 +311,67 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend } { - KX_ObColorIpoSGController* ipocontr=NULL; + KX_ObColorIpoSGController* ipocontr_obcol=NULL; ipo = ipoList->GetScalarInterpolator(OB_COL_R); if (ipo) { - if (!ipocontr) + if (!ipocontr_obcol) { - ipocontr = new KX_ObColorIpoSGController(); - gameobj->GetSGNode()->AddSGController(ipocontr); - ipocontr->SetObject(gameobj->GetSGNode()); + ipocontr_obcol = new KX_ObColorIpoSGController(); + gameobj->GetSGNode()->AddSGController(ipocontr_obcol); + ipocontr_obcol->SetObject(gameobj->GetSGNode()); } KX_IInterpolator *interpolator = new KX_ScalarInterpolator( - &ipocontr->m_rgba[0], + &ipocontr_obcol->m_rgba[0], ipo); - ipocontr->AddInterpolator(interpolator); + ipocontr_obcol->AddInterpolator(interpolator); } ipo = ipoList->GetScalarInterpolator(OB_COL_G); if (ipo) { - if (!ipocontr) + if (!ipocontr_obcol) { - ipocontr = new KX_ObColorIpoSGController(); - gameobj->GetSGNode()->AddSGController(ipocontr); - ipocontr->SetObject(gameobj->GetSGNode()); + ipocontr_obcol = new KX_ObColorIpoSGController(); + gameobj->GetSGNode()->AddSGController(ipocontr_obcol); + ipocontr_obcol->SetObject(gameobj->GetSGNode()); } KX_IInterpolator *interpolator = new KX_ScalarInterpolator( - &ipocontr->m_rgba[1], + &ipocontr_obcol->m_rgba[1], ipo); - ipocontr->AddInterpolator(interpolator); + ipocontr_obcol->AddInterpolator(interpolator); } ipo = ipoList->GetScalarInterpolator(OB_COL_B); if (ipo) { - if (!ipocontr) + if (!ipocontr_obcol) { - ipocontr = new KX_ObColorIpoSGController(); - gameobj->GetSGNode()->AddSGController(ipocontr); - ipocontr->SetObject(gameobj->GetSGNode()); + ipocontr_obcol = new KX_ObColorIpoSGController(); + gameobj->GetSGNode()->AddSGController(ipocontr_obcol); + ipocontr_obcol->SetObject(gameobj->GetSGNode()); } KX_IInterpolator *interpolator = new KX_ScalarInterpolator( - &ipocontr->m_rgba[2], + &ipocontr_obcol->m_rgba[2], ipo); - ipocontr->AddInterpolator(interpolator); + ipocontr_obcol->AddInterpolator(interpolator); } ipo = ipoList->GetScalarInterpolator(OB_COL_A); if (ipo) { - if (!ipocontr) + if (!ipocontr_obcol) { - ipocontr = new KX_ObColorIpoSGController(); - gameobj->GetSGNode()->AddSGController(ipocontr); - ipocontr->SetObject(gameobj->GetSGNode()); + ipocontr_obcol = new KX_ObColorIpoSGController(); + gameobj->GetSGNode()->AddSGController(ipocontr_obcol); + ipocontr_obcol->SetObject(gameobj->GetSGNode()); } KX_IInterpolator *interpolator = new KX_ScalarInterpolator( - &ipocontr->m_rgba[3], + &ipocontr_obcol->m_rgba[3], ipo); - ipocontr->AddInterpolator(interpolator); + ipocontr_obcol->AddInterpolator(interpolator); } } diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index a60e1ee59dc..e016fb8d007 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -274,7 +274,7 @@ void CParser::NextSym() } else if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) { // reserved word? - int start; + start = chcount; CharRep(); GrabString(start); diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 2c4fbd5a867..e04b42ee9cc 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -147,7 +147,7 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel if (attrdef->m_length > 1) { PyObject* resultlist = PyList_New(attrdef->m_length); - for (int i=0; im_length; i++) + for (unsigned int i=0; im_length; i++) { switch (attrdef->m_type) { case KX_PYATTRIBUTE_TYPE_BOOL: diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 0fae175e3cf..37eae3a8c61 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -73,7 +73,7 @@ typedef int Py_ssize_t; #endif static inline void Py_Fatal(const char *M) { - //cout << M << endl; + fprintf(stderr, "%s\n", M); exit(-1); }; diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index e8e29fb2769..c21e5db1410 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -42,14 +42,14 @@ SCA_Joystick::SCA_Joystick(short int index) m_axis21(0), m_prec(3200), m_buttonnum(-2), + m_axismax(-1), m_hatdir(-2), + m_buttonmax(-1), + m_hatmax(-1), m_isinit(0), m_istrig_axis(0), m_istrig_button(0), - m_istrig_hat(0), - m_axismax(-1), - m_buttonmax(-1), - m_hatmax(-1) + m_istrig_hat(0) { #ifndef DISABLE_SDL m_private = new PrivateData(); diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index 25c9888cadd..31a620b939d 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -53,10 +53,10 @@ SCA_DelaySensor::SCA_DelaySensor(class SCA_EventManager* eventmgr, int duration, bool repeat, PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T), + : SCA_ISensor(gameobj,eventmgr, T), + m_repeat(repeat), m_delay(delay), - m_duration(duration), - m_repeat(repeat) + m_duration(duration) { Init(); } diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp index eeca2d7b44c..309f3108418 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.cpp +++ b/source/gameengine/GameLogic/SCA_IActuator.cpp @@ -36,8 +36,8 @@ using namespace std; SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj, PyTypeObject* T) : - m_links(0), - SCA_ILogicBrick(gameobj,T) + SCA_ILogicBrick(gameobj,T), + m_links(0) { // nothing to do } diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 7ffb21b5490..51bd6454d92 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -36,9 +36,9 @@ class SCA_IActuator : public SCA_ILogicBrick { friend class SCA_LogicManager; protected: - std::vector m_events; int m_links; // number of active links to controllers // when 0, the actuator is automatically stopped + std::vector m_events; void RemoveAllEvents(); public: diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index 0bd20117f31..f9c192cae5c 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -38,8 +38,8 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj, PyTypeObject* T) : - m_statemask(0), - SCA_ILogicBrick(gameobj,T) + SCA_ILogicBrick(gameobj,T), + m_statemask(0) { } diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 3afc48b719c..e5ca26eac85 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -40,7 +40,7 @@ MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); -SCA_IObject::SCA_IObject(PyTypeObject* T): m_initState(0), m_state(0), CValue(T) +SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0) { m_suspended = false; } diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 4f4d62f13b9..36e4a5f2c30 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -158,8 +158,8 @@ bool SCA_MouseSensor::Evaluate(CValue* event) case KX_MOUSESENSORMODE_WHEELUP: case KX_MOUSESENSORMODE_WHEELDOWN: { - const SCA_InputEvent& event = mousedev->GetEventValue(m_hotkey); - switch (event.m_status){ + const SCA_InputEvent& mevent = mousedev->GetEventValue(m_hotkey); + switch (mevent.m_status){ case SCA_InputEvent::KX_JUSTACTIVATED: m_val = 1; result = true; diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 2a4a74d5b90..e8281201d24 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -18,7 +18,7 @@ #define spit(x) std::cout << x << std::endl; #define SORT_UNIFORMS 1 -#define UNIFORM_MAX_LEN sizeof(float)*16 +#define UNIFORM_MAX_LEN (int)sizeof(float)*16 #define MAX_LOG_LEN 262144 // bounds BL_Uniform::BL_Uniform(int data_size) @@ -108,7 +108,7 @@ void BL_Uniform::SetData(int location, int type,bool transpose) #endif } -const bool BL_Shader::Ok()const +bool BL_Shader::Ok()const { return (mShader !=0 && mOk && mUse); } diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 52cbd0cda51..76acd5513ef 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -166,7 +166,7 @@ public: //const BL_Sampler* GetSampler(int i); void SetSampler(int loc, int unit); - const bool Ok()const; + bool Ok()const; unsigned int GetProg(); void SetProg(bool enable); int GetAttribute(){return mAttr;}; diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 534c48661b7..062e9f7df50 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -384,10 +384,10 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode) childit!= destnode->GetSGChildren().end(); ++childit ) { - KX_GameObject *clientgameobj = static_cast( (*childit)->GetSGClientObject()); - if (clientgameobj) + KX_GameObject *clientgameobj_child = static_cast( (*childit)->GetSGClientObject()); + if (clientgameobj_child) { - parentKxCtrl = (KX_BulletPhysicsController*)clientgameobj->GetPhysicsController(); + parentKxCtrl = (KX_BulletPhysicsController*)clientgameobj_child->GetPhysicsController(); parentctrl = parentKxCtrl; ccdParent = parentKxCtrl; } diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index c0d802a9cf9..8a7ff41dfa6 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -56,9 +56,9 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj, int option, char *property, PyTypeObject* T) : + SCA_IActuator(gameobj, T), m_refDirection(refDir), - m_currentTime(0), - SCA_IActuator(gameobj, T) + m_currentTime(0) { m_posDampTime = posDampTime; m_rotDampTime = rotDampTime; diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 2387dcdef3a..3090c668f03 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -132,7 +132,7 @@ bool KX_GameActuator::Update() { char mashal_path[512]; char *marshal_buffer = NULL; - int marshal_length; + unsigned int marshal_length; FILE *fp = NULL; pathGamePythonConfig(mashal_path); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 37f16b92a26..60512991cf4 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1462,11 +1462,9 @@ PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value) 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); MT_Point3 point(0.0,0.0,0.0); - - PyObject* pypos = NULL; + if (PyArg_ParseTuple(args, "|O:getVelocity", &pypos)) { if (pypos) @@ -1478,10 +1476,11 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) if (m_pPhysicsController1) { - velocity = m_pPhysicsController1->GetVelocity(point); + return PyObjectFrom(m_pPhysicsController1->GetVelocity(point)); + } + else { + return PyObjectFrom(MT_Vector3(0.0,0.0,0.0)); } - - return PyObjectFrom(velocity); } @@ -2045,8 +2044,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, 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); + RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); + KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon); PyTuple_SET_ITEM(returnValue, 3, polyproxy); } else diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index 67d54cf0b0b..55a7e2ade60 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -58,8 +58,8 @@ KX_IpoSGController::KX_IpoSGController() m_ipo_add(false), m_ipo_local(false), m_modified(true), - m_ipo_start_initialized(false), m_ipotime(1.0), + m_ipo_start_initialized(false), m_ipo_start_euler(0.0,0.0,0.0), m_ipo_euler_initialized(false) { diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 1271474802c..074b3195121 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -713,7 +713,7 @@ void KX_KetsjiEngine::Render() if (!BeginFrame()) return; - KX_SceneList::iterator sceneit; + for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) // for each scene, call the proceed functions { diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 7ef544618f8..fb38f16c169 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -240,7 +240,7 @@ bool KX_NearSensor::BroadPhaseFilterCollision(void*obj1,void*obj2) bool KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData * coll_data) { // KX_TouchEventManager* toucheventmgr = static_cast(m_eventmgr); - KX_GameObject* parent = static_cast(GetParent()); +// KX_GameObject* parent = static_cast(GetParent()); // need the mapping from PHY_IPhysicsController to gameobjects now diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 9a620998538..b647c72fc10 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -65,12 +65,12 @@ KX_ObjectActuator( m_current_linear_factor(0.0), m_current_angular_factor(0.0), m_damping(damping), + m_previous_error(0.0,0.0,0.0), + m_error_accumulator(0.0,0.0,0.0), m_bitLocalFlag (flag), m_active_combined_velocity (false), m_linear_damping_active(false), - m_angular_damping_active(false), - m_error_accumulator(0.0,0.0,0.0), - m_previous_error(0.0,0.0,0.0) + m_angular_damping_active(false) { if (m_bitLocalFlag.ServoControl) { diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index 1c9e2a49c11..ff962d57c9d 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -146,8 +146,8 @@ PyObject* KX_PolyProxy::_getattr(const char *attr) } KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon) -: m_mesh((RAS_MeshObject*)mesh), - m_polygon(polygon) +: m_polygon(polygon), + m_mesh((RAS_MeshObject*)mesh) { } diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index c3ae3d0ec52..b3e8d15189f 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -196,7 +196,7 @@ static PyObject* gPyGetSpectrum(PyObject*) } - +#if 0 // unused static PyObject* gPyStartDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); @@ -213,7 +213,7 @@ static PyObject* gPyStartDSP(PyObject*, PyObject* args) Py_RETURN_NONE; } - +#endif static PyObject* gPyStopDSP(PyObject*, PyObject* args) @@ -257,7 +257,7 @@ static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate); Py_RETURN_NONE; } - +#if 0 // unused static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) { int debugMode; @@ -267,7 +267,7 @@ static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) PHY_GetActiveEnvironment()->setDebugMode(debugMode); Py_RETURN_NONE; } - +#endif static PyObject* gPyGetPhysicsTicRate(PyObject*) diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 37604518486..562c096d440 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -444,7 +444,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) ? m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF; PyObject* result = PyInt_FromLong(looping); return result; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index d2274c1e8d6..eb01385bc01 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -317,8 +317,8 @@ static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVec CcdPhysicsEnvironment::CcdPhysicsEnvironment(btDispatcher* dispatcher,btOverlappingPairCache* pairCache) -:m_scalingPropagated(false), -m_numIterations(10), +:m_numIterations(10), +m_scalingPropagated(false), m_numTimeSubSteps(1), m_ccdMode(0), m_solverType(-1), @@ -326,8 +326,8 @@ m_profileTimings(0), m_enableSatCollisionDetection(false), m_solver(NULL), m_ownPairCache(NULL), -m_ownDispatcher(NULL), -m_filterCallback(NULL) +m_filterCallback(NULL), +m_ownDispatcher(NULL) { for (int i=0;im_previous != NULL; frst = frst->m_previous->m_filter); + for (frst = this; frst->m_previous != NULL; frst = frst->m_previous->m_filter) {}; // set first filter return frst; } diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h index 7e90747d252..6385ed5108f 100644 --- a/source/gameengine/VideoTexture/FilterSource.h +++ b/source/gameengine/VideoTexture/FilterSource.h @@ -189,9 +189,10 @@ protected: int d = m_buffU[offset] - 128; int e = m_buffV[offset] - 128; // if horizontal interpolation is needed - if ((x & 1) == 1) + if ((x & 1) == 1) { // if vertical interpolation is needed too if ((y & 1) == 1) + { // if this pixel is on the edge if (isEdge(x, y, size)) { @@ -206,7 +207,8 @@ protected: e = interpolVH(m_buffV + offset) - 128; } // otherwise use horizontal interpolation only - else + } + else { // if this pixel is on the edge if (isEdge(x, y, size)) { @@ -221,6 +223,8 @@ protected: e = interpolH(m_buffV + offset) - 128; } // otherwise if only vertical interpolation is needed + } + } else if ((y & 1) == 1) // if this pixel is on the edge if (isEdge(x, y, size)) From c77af311665d230ed933138cd20962d021ad5c2b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Feb 2009 06:43:03 +0000 Subject: [PATCH 212/252] Minor speedups for the BGE * Where possible use vec.setValue(x,y,z) to assign values to a vector instead of vec= MT_Vector3(x,y,z), for MT_Point and MT_Matrix types too. * Comparing TexVerts was creating 10 MT_Vector types - instead compare as floats. * Added SG_Spatial::SetWorldFromLocalTransform() since the local transform is use for world transform in some cases. * removed some unneeded vars from UpdateChildCoordinates functions * Py API - Mouse, Ray, Radar sensors - use PyObjectFrom(vec) rather then filling the lists in each function. Use METH_NOARGS for get*() functions. --- source/blender/python/api2_2x/Mathutils.c | 10 +-- .../Converter/BL_BlenderDataConversion.cpp | 69 ++++++-------- .../gameengine/Converter/BL_MeshDeformer.cpp | 4 +- source/gameengine/Ketsji/KX_GameObject.cpp | 28 +++--- .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 89 ++++--------------- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 12 +-- source/gameengine/Ketsji/KX_RadarSensor.cpp | 35 ++------ source/gameengine/Ketsji/KX_RadarSensor.h | 6 +- source/gameengine/Ketsji/KX_RaySensor.cpp | 64 +++---------- source/gameengine/Ketsji/KX_RaySensor.h | 8 +- .../KX_SG_BoneParentNodeRelationship.cpp | 19 ++-- .../Ketsji/KX_SG_NodeRelationships.cpp | 80 ++++------------- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 6 +- source/gameengine/Rasterizer/RAS_TexVert.cpp | 26 +++--- source/gameengine/Rasterizer/RAS_TexVert.h | 1 + source/gameengine/SceneGraph/SG_BBox.cpp | 4 +- source/gameengine/SceneGraph/SG_Spatial.cpp | 19 ++-- source/gameengine/SceneGraph/SG_Spatial.h | 2 + 18 files changed, 164 insertions(+), 318 deletions(-) diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c index f0b51285376..b370aa0e1e8 100644 --- a/source/blender/python/api2_2x/Mathutils.c +++ b/source/blender/python/api2_2x/Mathutils.c @@ -350,7 +350,7 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2) PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args) { float high, low, range; - double rand; + double drand; //initializers high = 1.0; low = 0.0; @@ -364,14 +364,14 @@ PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args) "Mathutils.Rand(): high value should be larger than low value\n")); //get the random number 0 - 1 - rand = BLI_drand(); + drand = BLI_drand(); //set it to range range = high - low; - rand = rand * range; - rand = rand + low; + drand = drand * range; + drand = drand + low; - return PyFloat_FromDouble(rand); + return PyFloat_FromDouble(drand); } //----------------------------------VECTOR FUNCTIONS--------------------- //----------------------------------Mathutils.Vector() ------------------ diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 3293d37af3a..3a0302562e6 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -593,7 +593,7 @@ BL_Material* ConvertMaterial( MT_Point2 uv2[4]; const char *uvName = "", *uv2Name = ""; - uv[0]= uv[1]= uv[2]= uv[3]= MT_Point2(0.0f, 0.0f); + uv2[0]= uv2[1]= uv2[2]= uv2[3]= MT_Point2(0.0f, 0.0f); if( validface ) { @@ -607,12 +607,12 @@ BL_Material* ConvertMaterial( material->tile = tface->tile; material->mode = tface->mode; - uv[0] = MT_Point2(tface->uv[0]); - uv[1] = MT_Point2(tface->uv[1]); - uv[2] = MT_Point2(tface->uv[2]); + uv[0].setValue(tface->uv[0]); + uv[1].setValue(tface->uv[1]); + uv[2].setValue(tface->uv[2]); if (mface->v4) - uv[3] = MT_Point2(tface->uv[3]); + uv[3].setValue(tface->uv[3]); uvName = tfaceName; } @@ -622,6 +622,8 @@ BL_Material* ConvertMaterial( material->mode = default_face_mode; material->transp = TF_SOLID; material->tile = 0; + + uv[0]= uv[1]= uv[2]= uv[3]= MT_Point2(0.0f, 0.0f); } // with ztransp enabled, enforce alpha blending mode @@ -665,14 +667,14 @@ BL_Material* ConvertMaterial( { MT_Point2 uvSet[4]; - uvSet[0] = MT_Point2(layer.face->uv[0]); - uvSet[1] = MT_Point2(layer.face->uv[1]); - uvSet[2] = MT_Point2(layer.face->uv[2]); + uvSet[0].setValue(layer.face->uv[0]); + uvSet[1].setValue(layer.face->uv[1]); + uvSet[2].setValue(layer.face->uv[2]); if (mface->v4) - uvSet[3] = MT_Point2(layer.face->uv[3]); + uvSet[3].setValue(layer.face->uv[3]); else - uvSet[3] = MT_Point2(0.0f, 0.0f); + uvSet[3].setValue(0.0f, 0.0f); if (isFirstSet) { @@ -790,10 +792,10 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* MT_Vector4 tan0(0,0,0,0), tan1(0,0,0,0), tan2(0,0,0,0), tan3(0,0,0,0); /* get coordinates, normals and tangents */ - pt0 = MT_Point3(mvert[mface->v1].co); - pt1 = MT_Point3(mvert[mface->v2].co); - pt2 = MT_Point3(mvert[mface->v3].co); - pt3 = (mface->v4)? MT_Point3(mvert[mface->v4].co): MT_Point3(0.0, 0.0, 0.0); + pt0.setValue(mvert[mface->v1].co); + pt1.setValue(mvert[mface->v2].co); + pt2.setValue(mvert[mface->v3].co); + if (mface->v4) pt3.setValue(mvert[mface->v4].co); if(mface->flag & ME_SMOOTH) { float n0[3], n1[3], n2[3], n3[3]; @@ -894,12 +896,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* visible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); - uv0 = MT_Point2(tface->uv[0]); - uv1 = MT_Point2(tface->uv[1]); - uv2 = MT_Point2(tface->uv[2]); + uv0.setValue(tface->uv[0]); + uv1.setValue(tface->uv[1]); + uv2.setValue(tface->uv[2]); if (mface->v4) - uv3 = MT_Point2(tface->uv[3]); + uv3.setValue(tface->uv[3]); } else { /* no texfaces, set COLLSION true and everything else FALSE */ @@ -960,7 +962,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); } else { - polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); + polymat->m_specular.setValue(0.0f,0.0f,0.0f); polymat->m_shininess = 35.0; } } @@ -1911,21 +1913,14 @@ void BL_ConvertBlenderObjects(struct Main* maggie, MT_Matrix3x3 angor; if (converter->addInitFromFrame) blenderscene->r.cfra=blenderscene->r.sfra; - MT_Point3 pos = MT_Point3( + MT_Point3 pos; + pos.setValue( blenderobject->loc[0]+blenderobject->dloc[0], blenderobject->loc[1]+blenderobject->dloc[1], blenderobject->loc[2]+blenderobject->dloc[2] ); - MT_Vector3 eulxyz = MT_Vector3( - blenderobject->rot[0], - blenderobject->rot[1], - blenderobject->rot[2] - ); - MT_Vector3 scale = MT_Vector3( - blenderobject->size[0], - blenderobject->size[1], - blenderobject->size[2] - ); + MT_Vector3 eulxyz(blenderobject->rot); + MT_Vector3 scale(blenderobject->size); if (converter->addInitFromFrame){//rcruiz float eulxyzPrev[3]; blenderscene->r.cfra=blenderscene->r.sfra-1; @@ -2113,21 +2108,13 @@ void BL_ConvertBlenderObjects(struct Main* maggie, if (converter->addInitFromFrame) blenderscene->r.cfra=blenderscene->r.sfra; - MT_Point3 pos = MT_Point3( + MT_Point3 pos( blenderobject->loc[0]+blenderobject->dloc[0], blenderobject->loc[1]+blenderobject->dloc[1], blenderobject->loc[2]+blenderobject->dloc[2] ); - MT_Vector3 eulxyz = MT_Vector3( - blenderobject->rot[0], - blenderobject->rot[1], - blenderobject->rot[2] - ); - MT_Vector3 scale = MT_Vector3( - blenderobject->size[0], - blenderobject->size[1], - blenderobject->size[2] - ); + MT_Vector3 eulxyz(blenderobject->rot); + MT_Vector3 scale(blenderobject->size); if (converter->addInitFromFrame){//rcruiz float eulxyzPrev[3]; blenderscene->r.cfra=blenderscene->r.sfra-1; diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index fa3b8185fe2..80112346c72 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -51,7 +51,6 @@ bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) { size_t i; - float *co; // only apply once per frame if the mesh is actually modified if(m_pMeshObject->MeshModified() && @@ -70,8 +69,7 @@ bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) // For each vertex for(i=it.startvertex; imvert[v.getOrigIndex()].co; - v.SetXYZ(MT_Point3(co)); + v.SetXYZ(m_bmesh->mvert[v.getOrigIndex()].co); } } } diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 60512991cf4..5e013a1c647 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -690,9 +690,9 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac) switch (axis) { case 0: //x axis - ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis + ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot? - ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot! + ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot! if (fac == 1.0) { x = vect; } else { @@ -705,9 +705,9 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac) z = x.cross(y); break; case 1: //y axis - ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]); + ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]); if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) - ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]); + ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); if (fac == 1.0) { y = vect; } else { @@ -720,9 +720,9 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac) x = y.cross(z); break; case 2: //z axis - ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]); + ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) - ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]); + ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]); if (fac == 1.0) { z = vect; } else { @@ -741,9 +741,9 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac) x.normalize(); //normalize the vectors y.normalize(); z.normalize(); - orimat = MT_Matrix3x3( x[0],y[0],z[0], - x[1],y[1],z[1], - x[2],y[2],z[2]); + orimat.setValue( x[0],y[0],z[0], + x[1],y[1],z[1], + x[2],y[2],z[2]); if (GetSGNode()->GetSGParent() != NULL) { // the object is a child, adapt its local orientation so that @@ -945,13 +945,11 @@ const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const const MT_Point3& KX_GameObject::NodeGetWorldPosition() const { - static MT_Point3 defaultPosition = MT_Point3(0.0, 0.0, 0.0); - // check on valid node in case a python controller holds a reference to a deleted object - if (!GetSGNode()) - return defaultPosition; - - return GetSGNode()->GetWorldPosition(); + if (GetSGNode()) + return GetSGNode()->GetWorldPosition(); + else + return MT_Point3(0.0, 0.0, 0.0); } /* Suspend/ resume: for the dynamic behaviour, there is a simple diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index bd15d3cffbe..afe4cd1e2a4 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -42,6 +42,7 @@ #include "KX_Scene.h" #include "KX_Camera.h" #include "KX_MouseFocusSensor.h" +#include "KX_PyMath.h" #include "KX_RayCast.h" #include "KX_IPhysicsController.h" @@ -320,12 +321,12 @@ PyParentObject KX_MouseFocusSensor::Parents[] = { }; PyMethodDef KX_MouseFocusSensor::Methods[] = { - {"getRayTarget", (PyCFunction) KX_MouseFocusSensor::sPyGetRayTarget, METH_VARARGS, (PY_METHODCHAR)GetRayTarget_doc}, - {"getRaySource", (PyCFunction) KX_MouseFocusSensor::sPyGetRaySource, METH_VARARGS, (PY_METHODCHAR)GetRaySource_doc}, - {"getHitObject",(PyCFunction) KX_MouseFocusSensor::sPyGetHitObject,METH_VARARGS, (PY_METHODCHAR)GetHitObject_doc}, - {"getHitPosition",(PyCFunction) KX_MouseFocusSensor::sPyGetHitPosition,METH_VARARGS, (PY_METHODCHAR)GetHitPosition_doc}, - {"getHitNormal",(PyCFunction) KX_MouseFocusSensor::sPyGetHitNormal,METH_VARARGS, (PY_METHODCHAR)GetHitNormal_doc}, - {"getRayDirection",(PyCFunction) KX_MouseFocusSensor::sPyGetRayDirection,METH_VARARGS, (PY_METHODCHAR)GetRayDirection_doc}, + {"getRayTarget", (PyCFunction) KX_MouseFocusSensor::sPyGetRayTarget, METH_NOARGS, (PY_METHODCHAR)GetRayTarget_doc}, + {"getRaySource", (PyCFunction) KX_MouseFocusSensor::sPyGetRaySource, METH_NOARGS, (PY_METHODCHAR)GetRaySource_doc}, + {"getHitObject",(PyCFunction) KX_MouseFocusSensor::sPyGetHitObject,METH_NOARGS, (PY_METHODCHAR)GetHitObject_doc}, + {"getHitPosition",(PyCFunction) KX_MouseFocusSensor::sPyGetHitPosition,METH_NOARGS, (PY_METHODCHAR)GetHitPosition_doc}, + {"getHitNormal",(PyCFunction) KX_MouseFocusSensor::sPyGetHitNormal,METH_NOARGS, (PY_METHODCHAR)GetHitNormal_doc}, + {"getRayDirection",(PyCFunction) KX_MouseFocusSensor::sPyGetRayDirection,METH_NOARGS, (PY_METHODCHAR)GetRayDirection_doc}, {NULL,NULL} //Sentinel @@ -339,14 +340,11 @@ PyObject* KX_MouseFocusSensor::_getattr(const char *attr) { const char KX_MouseFocusSensor::GetHitObject_doc[] = "getHitObject()\n" "\tReturns the name of the object that was hit by this ray.\n"; -PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self) { if (m_hitObject) - { return m_hitObject->AddRef(); - } + Py_RETURN_NONE; } @@ -354,61 +352,28 @@ PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self, const char KX_MouseFocusSensor::GetHitPosition_doc[] = "getHitPosition()\n" "\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n"; -PyObject* KX_MouseFocusSensor::PyGetHitPosition(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MouseFocusSensor::PyGetHitPosition(PyObject* self) { - - MT_Point3 pos = m_hitPosition; - - PyObject* resultlist = PyList_New(3); - int index; - for (index=0;index<3;index++) - { - PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index])); - } - return resultlist; - + return PyObjectFrom(m_hitPosition); } const char KX_MouseFocusSensor::GetRayDirection_doc[] = "getRayDirection()\n" "\tReturns the direction from the ray (in worldcoordinates) .\n"; -PyObject* KX_MouseFocusSensor::PyGetRayDirection(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MouseFocusSensor::PyGetRayDirection(PyObject* self) { MT_Vector3 dir = m_prevTargetPoint - m_prevSourcePoint; dir.normalize(); - - PyObject* resultlist = PyList_New(3); - int index; - for (index=0;index<3;index++) - { - PyList_SetItem(resultlist,index,PyFloat_FromDouble(dir[index])); - } - return resultlist; - + return PyObjectFrom(dir); } const char KX_MouseFocusSensor::GetHitNormal_doc[] = "getHitNormal()\n" "\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n"; -PyObject* KX_MouseFocusSensor::PyGetHitNormal(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MouseFocusSensor::PyGetHitNormal(PyObject* self) { - MT_Vector3 pos = m_hitNormal; - - PyObject* resultlist = PyList_New(3); - int index; - for (index=0;index<3;index++) - { - PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index])); - } - return resultlist; - + return PyObjectFrom(m_hitNormal); } @@ -417,16 +382,8 @@ const char KX_MouseFocusSensor::GetRayTarget_doc[] = "getRayTarget()\n" "\tReturns the target of the ray that seeks the focus object,\n" "\tin worldcoordinates."; -PyObject* KX_MouseFocusSensor::PyGetRayTarget(PyObject* self, - PyObject* args, - PyObject* kwds) { - PyObject *retVal = PyList_New(3); - - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_prevTargetPoint[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_prevTargetPoint[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_prevTargetPoint[2])); - - return retVal; +PyObject* KX_MouseFocusSensor::PyGetRayTarget(PyObject* self) { + return PyObjectFrom(m_prevTargetPoint); } /* getRayTarget */ @@ -434,16 +391,8 @@ const char KX_MouseFocusSensor::GetRaySource_doc[] = "getRaySource()\n" "\tReturns the source of the ray that seeks the focus object,\n" "\tin worldcoordinates."; -PyObject* KX_MouseFocusSensor::PyGetRaySource(PyObject* self, - PyObject* args, - PyObject* kwds) { - PyObject *retVal = PyList_New(3); - - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_prevSourcePoint[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_prevSourcePoint[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_prevSourcePoint[2])); - - return retVal; +PyObject* KX_MouseFocusSensor::PyGetRaySource(PyObject* self) { + return PyObjectFrom(m_prevSourcePoint); } /* eof */ diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index 704198ce5a3..4979783032c 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -89,13 +89,13 @@ class KX_MouseFocusSensor : public SCA_MouseSensor /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const char *attr); - KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRayTarget); - KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRaySource); + KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayTarget); + KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRaySource); - KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetHitObject); - KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetHitPosition); - KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetHitNormal); - KX_PYMETHOD_DOC(KX_MouseFocusSensor,GetRayDirection); + KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetHitObject); + KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetHitPosition); + KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetHitNormal); + KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayDirection); /* --------------------------------------------------------------------- */ SCA_IObject* m_hitObject; diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 1321b862463..2ba1126a633 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -28,6 +28,7 @@ #include "KX_RadarSensor.h" #include "KX_GameObject.h" +#include "KX_PyMath.h" #include "PHY_IPhysicsController.h" #ifdef HAVE_CONFIG_H @@ -221,11 +222,11 @@ PyParentObject KX_RadarSensor::Parents[] = { PyMethodDef KX_RadarSensor::Methods[] = { {"getConeOrigin", (PyCFunction) KX_RadarSensor::sPyGetConeOrigin, - METH_VARARGS, (PY_METHODCHAR)GetConeOrigin_doc}, + METH_NOARGS, (PY_METHODCHAR)GetConeOrigin_doc}, {"getConeTarget", (PyCFunction) KX_RadarSensor::sPyGetConeTarget, - METH_VARARGS, (PY_METHODCHAR)GetConeTarget_doc}, + METH_NOARGS, (PY_METHODCHAR)GetConeTarget_doc}, {"getConeHeight", (PyCFunction) KX_RadarSensor::sPyGetConeHeight, - METH_VARARGS, (PY_METHODCHAR)GetConeHeight_doc}, + METH_NOARGS, (PY_METHODCHAR)GetConeHeight_doc}, {NULL,NULL,NULL,NULL} //Sentinel }; @@ -238,41 +239,23 @@ const char KX_RadarSensor::GetConeOrigin_doc[] = "getConeOrigin()\n" "\tReturns the origin of the cone with which to test. The origin\n" "\tis in the middle of the cone."; -PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self, - PyObject* args, - PyObject* kwds) { - PyObject *retVal = PyList_New(3); - - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_origin[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_origin[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_origin[2])); - - return retVal; +PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self) { + return PyObjectFrom(m_cone_origin); } /* getConeOrigin */ const char KX_RadarSensor::GetConeTarget_doc[] = "getConeTarget()\n" "\tReturns the center of the bottom face of the cone with which to test.\n"; -PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self, - PyObject* args, - PyObject* kwds) { - PyObject *retVal = PyList_New(3); - - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_target[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_target[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_target[2])); - - return retVal; +PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self) { + return PyObjectFrom(m_cone_target); } /* getConeOrigin */ const char KX_RadarSensor::GetConeHeight_doc[] = "getConeHeight()\n" "\tReturns the height of the cone with which to test.\n"; -PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self) { return PyFloat_FromDouble(m_coneheight); } diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index f8f80725145..e4c6d73f22d 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -83,9 +83,9 @@ public: virtual PyObject* _getattr(const char *attr); - KX_PYMETHOD_DOC(KX_RadarSensor,GetConeOrigin); - KX_PYMETHOD_DOC(KX_RadarSensor,GetConeTarget); - KX_PYMETHOD_DOC(KX_RadarSensor,GetConeHeight); + KX_PYMETHOD_DOC_NOARGS(KX_RadarSensor,GetConeOrigin); + KX_PYMETHOD_DOC_NOARGS(KX_RadarSensor,GetConeTarget); + KX_PYMETHOD_DOC_NOARGS(KX_RadarSensor,GetConeHeight); }; diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index b8ebce28814..c7cb53f64ed 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -38,6 +38,7 @@ #include "KX_GameObject.h" #include "KX_Scene.h" #include "KX_RayCast.h" +#include "KX_PyMath.h" #include "PHY_IPhysicsEnvironment.h" #include "KX_IPhysicsController.h" #include "PHY_IPhysicsController.h" @@ -179,8 +180,8 @@ bool KX_RaySensor::Evaluate(CValue* event) bool reset = m_reset && m_level; m_rayHit = false; m_hitObject = NULL; - m_hitPosition = MT_Vector3(0,0,0); - m_hitNormal = MT_Vector3(1,0,0); + m_hitPosition.setValue(0,0,0); + m_hitNormal.setValue(1,0,0); KX_GameObject* obj = (KX_GameObject*)GetParent(); MT_Point3 frompoint = obj->NodeGetWorldPosition(); @@ -335,19 +336,17 @@ PyParentObject KX_RaySensor::Parents[] = { }; PyMethodDef KX_RaySensor::Methods[] = { - {"getHitObject",(PyCFunction) KX_RaySensor::sPyGetHitObject,METH_VARARGS, (PY_METHODCHAR)GetHitObject_doc}, - {"getHitPosition",(PyCFunction) KX_RaySensor::sPyGetHitPosition,METH_VARARGS, (PY_METHODCHAR)GetHitPosition_doc}, - {"getHitNormal",(PyCFunction) KX_RaySensor::sPyGetHitNormal,METH_VARARGS, (PY_METHODCHAR)GetHitNormal_doc}, - {"getRayDirection",(PyCFunction) KX_RaySensor::sPyGetRayDirection,METH_VARARGS, (PY_METHODCHAR)GetRayDirection_doc}, + {"getHitObject",(PyCFunction) KX_RaySensor::sPyGetHitObject,METH_NOARGS, (PY_METHODCHAR)GetHitObject_doc}, + {"getHitPosition",(PyCFunction) KX_RaySensor::sPyGetHitPosition,METH_NOARGS, (PY_METHODCHAR)GetHitPosition_doc}, + {"getHitNormal",(PyCFunction) KX_RaySensor::sPyGetHitNormal,METH_NOARGS, (PY_METHODCHAR)GetHitNormal_doc}, + {"getRayDirection",(PyCFunction) KX_RaySensor::sPyGetRayDirection,METH_NOARGS, (PY_METHODCHAR)GetRayDirection_doc}, {NULL,NULL} //Sentinel }; const char KX_RaySensor::GetHitObject_doc[] = "getHitObject()\n" "\tReturns the name of the object that was hit by this ray.\n"; -PyObject* KX_RaySensor::PyGetHitObject(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_RaySensor::PyGetHitObject(PyObject* self) { if (m_hitObject) { @@ -360,60 +359,25 @@ PyObject* KX_RaySensor::PyGetHitObject(PyObject* self, const char KX_RaySensor::GetHitPosition_doc[] = "getHitPosition()\n" "\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n"; -PyObject* KX_RaySensor::PyGetHitPosition(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_RaySensor::PyGetHitPosition(PyObject* self) { - - MT_Point3 pos = m_hitPosition; - - PyObject* resultlist = PyList_New(3); - int index; - for (index=0;index<3;index++) - { - PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index])); - } - return resultlist; - + return PyObjectFrom(m_hitPosition); } const char KX_RaySensor::GetRayDirection_doc[] = "getRayDirection()\n" "\tReturns the direction from the ray (in worldcoordinates) .\n"; -PyObject* KX_RaySensor::PyGetRayDirection(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_RaySensor::PyGetRayDirection(PyObject* self) { - - MT_Vector3 dir = m_rayDirection; - - PyObject* resultlist = PyList_New(3); - int index; - for (index=0;index<3;index++) - { - PyList_SetItem(resultlist,index,PyFloat_FromDouble(dir[index])); - } - return resultlist; - + return PyObjectFrom(m_rayDirection); } const char KX_RaySensor::GetHitNormal_doc[] = "getHitNormal()\n" "\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n"; -PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self) { - MT_Vector3 pos = m_hitNormal; - - PyObject* resultlist = PyList_New(3); - int index; - for (index=0;index<3;index++) - { - PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index])); - } - return resultlist; - + return PyObjectFrom(m_hitNormal); } diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index 2baec12f74e..09d8bc1369a 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -74,10 +74,10 @@ public: 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); - KX_PYMETHOD_DOC(KX_RaySensor,GetHitNormal); - KX_PYMETHOD_DOC(KX_RaySensor,GetRayDirection); + KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitObject); + KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitPosition); + KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitNormal); + KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetRayDirection); virtual PyObject* _getattr(const char *attr); diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp index d651373869a..151270cbd68 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp @@ -97,11 +97,11 @@ UpdateChildCoordinates( child_transform = parent_matrix * child_transform; // Recompute the child transform components from the transform. - child_w_scale = MT_Vector3( + child_w_scale.setValue( MT_Vector3(child_transform[0][0], child_transform[0][1], child_transform[0][2]).length(), MT_Vector3(child_transform[1][0], child_transform[1][1], child_transform[1][2]).length(), MT_Vector3(child_transform[2][0], child_transform[2][1], child_transform[2][2]).length()); - child_w_rotation = MT_Matrix3x3(child_transform[0][0], child_transform[0][1], child_transform[0][2], + child_w_rotation.setValue(child_transform[0][0], child_transform[0][1], child_transform[0][2], child_transform[1][0], child_transform[1][1], child_transform[1][2], child_transform[2][0], child_transform[2][1], child_transform[2][2]); child_w_rotation.scale(1.0/child_w_scale[0], 1.0/child_w_scale[1], 1.0/child_w_scale[2]); @@ -113,16 +113,15 @@ UpdateChildCoordinates( } } - if (!valid_parent_transform) + if (valid_parent_transform) { - child_w_scale = child_scale; - child_w_pos = child_pos; - child_w_rotation = child_rotation; + child->SetWorldScale(child_w_scale); + child->SetWorldPosition(child_w_pos); + child->SetWorldOrientation(child_w_rotation); + } + else { + child->SetWorldFromLocalTransform(); } - - child->SetWorldScale(child_w_scale); - child->SetWorldPosition(child_w_pos); - child->SetWorldOrientation(child_w_rotation); return valid_parent_transform; } diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp index 0c8e7e28771..0729ec8a902 100644 --- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp +++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp @@ -55,43 +55,21 @@ UpdateChildCoordinates( ){ MT_assert(child != NULL); - // This way of accessing child coordinates is a bit cumbersome - // be nice to have non constant reference access to these values. - - const MT_Vector3 & child_scale = child->GetLocalScale(); - const MT_Point3 & child_pos = child->GetLocalPosition(); - const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation(); - - // the childs world locations which we will update. - - MT_Vector3 child_w_scale; - MT_Point3 child_w_pos; - MT_Matrix3x3 child_w_rotation; - - if (parent) { - + if (parent==NULL) { /* Simple case */ + child->SetWorldFromLocalTransform(); + return false; + } + else { + // the childs world locations which we will update. const MT_Vector3 & p_world_scale = parent->GetWorldScaling(); const MT_Point3 & p_world_pos = parent->GetWorldPosition(); const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation(); - child_w_scale = p_world_scale * child_scale; - child_w_rotation = p_world_rotation * child_rotation; - - child_w_pos = p_world_pos + p_world_scale * - (p_world_rotation * child_pos); - - } else { - - child_w_scale = child_scale; - child_w_pos = child_pos; - child_w_rotation = child_rotation; + child->SetWorldScale(p_world_scale * child->GetLocalScale()); + child->SetWorldOrientation(p_world_rotation * child->GetLocalOrientation()); + child->SetWorldPosition(p_world_pos + p_world_scale * (p_world_rotation * child->GetLocalPosition())); + return true; } - - child->SetWorldScale(child_w_scale); - child->SetWorldPosition(child_w_pos); - child->SetWorldOrientation(child_w_rotation); - - return parent != NULL; } SG_ParentRelation * @@ -138,40 +116,14 @@ UpdateChildCoordinates( ){ MT_assert(child != NULL); - - const MT_Vector3 & child_scale = child->GetLocalScale(); - const MT_Point3 & child_pos = child->GetLocalPosition(); - const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation(); - - // the childs world locations which we will update. + child->SetWorldScale(child->GetLocalScale()); - MT_Vector3 child_w_scale; - MT_Point3 child_w_pos; - MT_Matrix3x3 child_w_rotation; - - if (parent) { - - // This is a vertex parent so we do not inherit orientation - // information. - - // const MT_Vector3 & p_world_scale = parent->GetWorldScaling(); /*unused*/ - const MT_Point3 & p_world_pos = parent->GetWorldPosition(); - // const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation(); /*unused*/ - - child_w_scale = child_scale; - child_w_rotation = child_rotation; - child_w_pos = p_world_pos + child_pos; - } else { - - child_w_scale = child_scale; - child_w_pos = child_pos; - child_w_rotation = child_rotation; - } - - child->SetWorldScale(child_w_scale); - child->SetWorldPosition(child_w_pos); - child->SetWorldOrientation(child_w_rotation); + if (parent) + child->SetWorldPosition(child->GetLocalPosition()+parent->GetWorldPosition()); + else + child->SetWorldPosition(child->GetLocalPosition()); + child->SetWorldOrientation(child->GetLocalOrientation()); return parent != NULL; } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 89dfc8e57ad..9d4fa14ad8e 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -258,18 +258,18 @@ bool KX_TrackToActuator::Update(double curtime, bool frame) { case 0: { - up = MT_Vector3(1.0,0,0); + up.setValue(1.0,0,0); break; } case 1: { - up = MT_Vector3(0,1.0,0); + up.setValue(0,1.0,0); break; } case 2: default: { - up = MT_Vector3(0,0,1.0); + up.setValue(0,0,1.0); } } #endif diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index b92965ed1cc..210addfb927 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -59,10 +59,10 @@ const MT_Point3& RAS_TexVert::xyz() void RAS_TexVert::SetRGBA(const MT_Vector4& rgba) { unsigned char *colp = (unsigned char*) &m_rgba; - colp[0] = (unsigned char) (rgba[0]*255.0); - colp[1] = (unsigned char) (rgba[1]*255.0); - colp[2] = (unsigned char) (rgba[2]*255.0); - colp[3] = (unsigned char) (rgba[3]*255.0); + colp[0] = (unsigned char) (rgba[0]*255.0f); + colp[1] = (unsigned char) (rgba[1]*255.0f); + colp[2] = (unsigned char) (rgba[2]*255.0f); + colp[3] = (unsigned char) (rgba[3]*255.0f); } @@ -71,7 +71,10 @@ void RAS_TexVert::SetXYZ(const MT_Point3& xyz) xyz.getValue(m_localxyz); } - +void RAS_TexVert::SetXYZ(const float *xyz) +{ + m_localxyz[0]= xyz[0]; m_localxyz[1]= xyz[1]; m_localxyz[2]= xyz[2]; +} void RAS_TexVert::SetUV(const MT_Point2& uv) { @@ -111,15 +114,18 @@ void RAS_TexVert::SetTangent(const MT_Vector3& tangent) } // compare two vertices, and return TRUE if both are almost identical (they can be shared) +#define _VEC_EQUAL3(_v1, _v2) (_v1[0]==_v2[0] && _v1[1]==_v2[1] && _v1[2]==_v2[2]) +#define _VEC_EQUAL2(_v1, _v2) (_v1[0]==_v2[0] && _v1[1]==_v2[1]) 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))) ; + _VEC_EQUAL3(m_normal, other->m_normal) && + _VEC_EQUAL3(m_tangent, other->m_tangent) && + _VEC_EQUAL2(m_uv1, other->m_uv1) && + _VEC_EQUAL2(m_uv2, other->m_uv2) // p -- + /* we know the verts must be shared so dont need to check this */ + /*&& FAST_MT_fuzzyEqual3(m_localxyz, other->m_localxyz)*/) ; } short RAS_TexVert::getFlag() const diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index 157a6ce3d51..811867f3579 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -115,6 +115,7 @@ public: } void SetXYZ(const MT_Point3& xyz); + void SetXYZ(const float *xyz); void SetUV(const MT_Point2& uv); void SetUV2(const MT_Point2& uv); diff --git a/source/gameengine/SceneGraph/SG_BBox.cpp b/source/gameengine/SceneGraph/SG_BBox.cpp index 4bd2805978e..a44262d04f7 100644 --- a/source/gameengine/SceneGraph/SG_BBox.cpp +++ b/source/gameengine/SceneGraph/SG_BBox.cpp @@ -34,8 +34,8 @@ #include "SG_Node.h" SG_BBox::SG_BBox() : - m_min(MT_Point3(0., 0., 0.)), - m_max(MT_Point3(0., 0., 0.)) + m_min(0., 0., 0.), + m_max(0., 0., 0.) { } diff --git a/source/gameengine/SceneGraph/SG_Spatial.cpp b/source/gameengine/SceneGraph/SG_Spatial.cpp index 5ba116e59db..99aeb3e72ee 100644 --- a/source/gameengine/SceneGraph/SG_Spatial.cpp +++ b/source/gameengine/SceneGraph/SG_Spatial.cpp @@ -44,13 +44,13 @@ SG_Spatial( ): SG_IObject(clientobj,clientinfo,callbacks), - m_localPosition(MT_Point3(0.0,0.0,0.0)), - m_localRotation(MT_Matrix3x3(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0)), - m_localScaling(MT_Vector3(1.f,1.f,1.f)), + m_localPosition(0.0,0.0,0.0), + m_localRotation(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0), + m_localScaling(1.f,1.f,1.f), - m_worldPosition(MT_Point3(0.0,0.0,0.0)), - m_worldRotation(MT_Matrix3x3(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0)), - m_worldScaling(MT_Vector3(1.f,1.f,1.f)), + m_worldPosition(0.0,0.0,0.0), + m_worldRotation(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0), + m_worldScaling(1.f,1.f,1.f), m_parent_relation (NULL), @@ -297,6 +297,13 @@ GetWorldScaling( return m_worldScaling; } +void SG_Spatial::SetWorldFromLocalTransform() +{ + m_worldPosition= m_localPosition; + m_worldScaling= m_localScaling; + m_worldRotation= m_localRotation; +} + SG_BBox& SG_Spatial::BBox() { return m_bbox; diff --git a/source/gameengine/SceneGraph/SG_Spatial.h b/source/gameengine/SceneGraph/SG_Spatial.h index 28848b0f933..6ccec2aa9c1 100644 --- a/source/gameengine/SceneGraph/SG_Spatial.h +++ b/source/gameengine/SceneGraph/SG_Spatial.h @@ -176,6 +176,8 @@ public: GetWorldScaling( ) const ; + void SetWorldFromLocalTransform(); + MT_Transform GetWorldTransform() const; bool ComputeWorldTransforms( const SG_Spatial *parent); From 7fffb0b6302618049a35e6bacf0aeed70a47d8aa Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Feb 2009 12:07:51 +0000 Subject: [PATCH 213/252] Building the game engine with Solid/Sumo is now optional for scons using WITH_BF_SOLID. Now Sumo is has been deprecated for a while we might want to remove it for 2.5. --- SConstruct | 1 + extern/SConscript | 4 ++-- source/blender/src/SConscript | 4 +++- source/gameengine/BlenderRoutines/SConscript | 13 +++++++++---- source/gameengine/Converter/SConscript | 13 +++++++++---- source/gameengine/GamePlayer/common/SConscript | 10 ++++++---- source/gameengine/GamePlayer/ghost/SConscript | 7 ++++--- source/gameengine/Ketsji/KX_ClientObjectInfo.h | 16 +++++++++++++--- .../gameengine/Ketsji/KX_ConvertPhysicsObject.h | 2 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 3 +++ source/gameengine/Ketsji/KX_NearSensor.cpp | 3 +-- source/gameengine/Ketsji/KX_TouchSensor.cpp | 6 ++++-- source/gameengine/Ketsji/SConscript | 10 +++++++--- source/gameengine/SConscript | 4 +++- tools/btools.py | 3 ++- 15 files changed, 68 insertions(+), 31 deletions(-) diff --git a/SConstruct b/SConstruct index 809166586e6..20d8f8fd2ec 100644 --- a/SConstruct +++ b/SConstruct @@ -280,6 +280,7 @@ if 'blenderlite' in B.targets: env['WITH_BF_PNG'] = False env['WITH_BF_ODE'] = False env['WITH_BF_BULLET'] = False + env['WITH_BF_SOLID'] = False env['WITH_BF_BINRELOC'] = False env['BF_BUILDINFO'] = False env['BF_NO_ELBEEM'] = True diff --git a/extern/SConscript b/extern/SConscript index 4c892e1956d..6bc067c0f03 100644 --- a/extern/SConscript +++ b/extern/SConscript @@ -5,8 +5,8 @@ Import('env') SConscript(['glew/SConscript']) if env['WITH_BF_GAMEENGINE']: - SConscript(['qhull/SConscript', - 'solid/SConscript']) + if env['WITH_BF_SOLID']: + SConscript(['qhull/SConscript', 'solid/SConscript']) if env['WITH_BF_BULLET']: SConscript(['bullet2/src/SConscript']) diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index 384ad1b1bf2..2e5dda6c772 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -70,7 +70,9 @@ if env['WITH_BF_ICONV']: if env['WITH_BF_GAMEENGINE']: defs.append('GAMEBLENDER=1') - + if env['WITH_BF_SOLID']: + defs.append('USE_SUMO_SOLID') + if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') incs += ' ' + env['BF_FFMPEG_INC'] diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index 7a1bf4d9ad6..f2d92384e3c 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -2,6 +2,7 @@ Import ('env') sources = env.Glob('*.cpp') +defs = [] incs = '. #source/kernel/gen_system #intern/string #intern/guardedalloc' incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #intern/bmfont' @@ -12,13 +13,17 @@ incs += ' #source/blender/blenkernel #source/blender #source/blender/include' incs += ' #source/blender/makesdna #source/gameengine/Rasterizer #source/gameengine/GameLogic' incs += ' #source/gameengine/Expressions #source/gameengine/Network' incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common' -incs += ' #source/gameengine/Physics/Bullet #source/gameengine/Physics/Sumo' -incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' +incs += ' #source/gameengine/Physics/Bullet' +incs += ' #source/gameengine/Network/LoopBackNetwork' incs += ' #intern/SoundSystem #source/blender/misc #source/blender/blenloader' incs += ' #extern/glew/include #source/blender/gpu' +if env['WITH_BF_SOLID']: + incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/Fuzzics/include' + incs += ' ' + env['BF_SOLID_INC'] + defs.append('USE_SUMO_SOLID') + incs += ' ' + env['BF_PYTHON_INC'] -incs += ' ' + env['BF_SOLID_INC'] incs += ' ' + env['BF_BULLET_INC'] incs += ' ' + env['BF_OPENGL_INC'] @@ -27,4 +32,4 @@ if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/GR') cxxflags.append ('/O2') -env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , cxx_compileflags=cxxflags) +env.BlenderLib ( 'bf_bloutines', sources, Split(incs), defs, libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , cxx_compileflags=cxxflags) diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index 3be352c568b..361dca58005 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -2,6 +2,7 @@ Import ('env') sources = env.Glob('*.cpp') +defs = [] incs = '. #source/kernel/gen_system #intern/string #intern/guardedalloc' incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #intern/bmfont' @@ -14,12 +15,16 @@ incs += ' #source/blender/include #source/blender/makesdna #source/gameengine/Ra incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #source/gameengine/GameLogic' incs += ' #source/gameengine/Expressions #source/gameengine/Network #source/gameengine/SceneGraph' 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/gameengine/Physics/Dummy' +incs += ' #source/gameengine/Network/LoopBackNetwork' incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu' +if env['WITH_BF_SOLID']: + incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/Fuzzics/include' + incs += ' ' + env['BF_SOLID_INC'] + defs.append('USE_SUMO_SOLID') + incs += ' ' + env['BF_PYTHON_INC'] -incs += ' ' + env['BF_SOLID_INC'] incs += ' ' + env['BF_BULLET_INC'] -env.BlenderLib ( 'bf_converter', sources, Split(incs), [], libtype=['game','player'], priority=[5,70] ) +env.BlenderLib ( 'bf_converter', sources, Split(incs), defs, libtype=['game','player'], priority=[5,70] ) diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index c9bda78d905..23ad413350b 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -39,15 +39,13 @@ incs = ['.', '#source/gameengine/Network', '#source/gameengine/SceneGraph', '#source/gameengine/Physics/common', - '#source/gameengine/Physics/Sumo', - '#source/gameengine/Physics/Sumo/Fuzzics/include', '#source/gameengine/Network/LoopBackNetwork', '#source/gameengine/GamePlayer/ghost', '#source/blender/misc', '#source/blender/blenloader', '#source/blender/gpu', '#extern/glew/include'] - + #This is all plugin stuff! #if sys.platform=='win32': # source_files += ['windows/GPW_Canvas.cpp', @@ -62,8 +60,12 @@ incs = ['.', # 'unix/GPU_System.cpp'] # gp_common_env.Append ( CPPPATH = ['unix']) +if env['WITH_BF_SOLID']: + incs.append('#source/gameengine/Physics/Sumo') + incs.append('#source/gameengine/Physics/Sumo/Fuzzics/include') + incs += Split(env['BF_SOLID_INC']) + incs += Split(env['BF_PYTHON_INC']) -incs += Split(env['BF_SOLID_INC']) incs += Split(env['BF_PNG_INC']) incs += Split(env['BF_ZLIB_INC']) diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 0785ce4bd0d..dd8761e0a45 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -34,8 +34,6 @@ incs = ['.', '#source/gameengine/Network', '#source/gameengine/SceneGraph', '#source/gameengine/Physics/common', - '#source/gameengine/Physics/Sumo', - '#source/gameengine/Physics/Sumo/Fuzzics/include', '#source/gameengine/Network/LoopBackNetwork', '#source/gameengine/GamePlayer/common', '#source/blender/misc', @@ -43,8 +41,11 @@ incs = ['.', '#source/blender/gpu', '#extern/glew/include'] +if env['WITH_BF_SOLID']: + incs.append(['#source/gameengine/Physics/Sumo', '#source/gameengine/Physics/Sumo/Fuzzics/include']) + incs += Split(env['BF_SOLID_INC']) + incs += Split(env['BF_PYTHON_INC']) -incs += Split(env['BF_SOLID_INC']) cxxflags = [] if env['OURPLATFORM']=='win32-vc': diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h index 5e8af0f040c..7345edb054b 100644 --- a/source/gameengine/Ketsji/KX_ClientObjectInfo.h +++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h @@ -29,7 +29,10 @@ #ifndef __KX_CLIENTOBJECT_INFO_H #define __KX_CLIENTOBJECT_INFO_H +/* Note, the way this works with/without sumo is a bit odd */ +#ifdef USE_SUMO_SOLID #include +#endif //USE_SUMO_SOLID #include @@ -38,7 +41,10 @@ class KX_GameObject; /** * Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks */ -struct KX_ClientObjectInfo : public SM_ClientObject +struct KX_ClientObjectInfo +#ifdef USE_SUMO_SOLID + : public SM_ClientObject +#endif { enum clienttype { STATIC, @@ -52,14 +58,18 @@ struct KX_ClientObjectInfo : public SM_ClientObject std::list m_sensors; public: KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC, void *auxilary_info = NULL) : +#ifdef USE_SUMO_SOLID SM_ClientObject(), +#endif m_type(type), m_gameobject(gameobject), m_auxilary_info(auxilary_info) {} - KX_ClientObjectInfo(const KX_ClientObjectInfo ©) - : SM_ClientObject(copy), + KX_ClientObjectInfo(const KX_ClientObjectInfo ©) : +#ifdef USE_SUMO_SOLID + SM_ClientObject(copy), +#endif m_type(copy.m_type), m_gameobject(copy.m_gameobject), m_auxilary_info(copy.m_auxilary_info) diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 53486cecf73..edacf38ab43 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -32,7 +32,7 @@ /* These are defined by the build system... */ //but the build system is broken, because it doesn't allow for 2 or more defines at once. //Please leave Sumo _AND_ Bullet enabled -#define USE_SUMO_SOLID +//#define USE_SUMO_SOLID // scons defines this #define USE_BULLET //#define USE_ODE diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 074b3195121..87f348799df 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -59,7 +59,10 @@ #include "KX_PythonInit.h" #include "KX_PyConstraintBinding.h" #include "PHY_IPhysicsEnvironment.h" + +#ifdef USE_SUMO_SOLID #include "SumoPhysicsEnvironment.h" +#endif #include "SND_Scene.h" #include "SND_IAudioDevice.h" diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index fb38f16c169..5b1df8b1fe1 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -37,7 +37,6 @@ #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" - #ifdef HAVE_CONFIG_H #include #endif @@ -272,7 +271,7 @@ bool KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData //} } - return DT_CONTINUE; + return false; // was DT_CONTINUE; but this was defined in Sumo as false } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 117adb44742..0b4d66dbb34 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -34,7 +34,9 @@ #include "SCA_LogicManager.h" #include "KX_GameObject.h" #include "KX_TouchEventManager.h" -#include "KX_SumoPhysicsController.h" + +#include "PHY_IPhysicsController.h" + #include #include "PHY_IPhysicsEnvironment.h" @@ -214,7 +216,7 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll } } - return DT_CONTINUE; + return false; // was DT_CONTINUE but this was defined in sumo as false. } diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 40cbc35e7f3..5989d9d8b52 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -31,11 +31,15 @@ incs += ' #source/blender/makesdna #source/blender/python #source/gameengine/Ras incs += ' #source/gameengine/GameLogic #source/gameengine/Expressions #source/gameengine/Network' incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common #source/gameengine/Physics/Bullet' incs += ' #source/gameengine/Physics/BlOde #source/gameengine/Physics/Dummy' -incs += ' #source/gameengine/Physics/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 += ' ' + env['BF_SOLID_INC'] +if env['WITH_BF_SOLID']: + incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/include' + incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' + incs += ' ' + env['BF_SOLID_INC'] + defs += ' USE_SUMO_SOLID' + + incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_BULLET_INC'] incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/gameengine/SConscript b/source/gameengine/SConscript index e841f206eee..51a05e70a07 100644 --- a/source/gameengine/SConscript +++ b/source/gameengine/SConscript @@ -15,10 +15,12 @@ SConscript(['BlenderRoutines/SConscript', 'Rasterizer/RAS_OpenGLRasterizer/SConscript', 'SceneGraph/SConscript', 'Physics/Bullet/SConscript', - 'Physics/Sumo/SConscript', 'VideoTexture/SConscript' ]) +if env['WITH_BF_SOLID']: + SConscript(['Physics/Sumo/SConscript']) + if env['WITH_BF_PLAYER']: SConscript(['GamePlayer/SConscript']) diff --git a/tools/btools.py b/tools/btools.py index 21ab547b11a..79f4717a262 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -44,7 +44,7 @@ def validate_arguments(args, bc): 'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'BF_GETTEXT_LIBPATH', 'WITH_BF_ICONV', 'BF_ICONV', 'BF_ICONV_INC', 'BF_ICONV_LIB', 'BF_ICONV_LIBPATH', 'WITH_BF_ODE', 'BF_ODE', 'BF_ODE_INC', 'BF_ODE_LIB', - 'WITH_BF_GAMEENGINE', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB', + 'WITH_BF_GAMEENGINE', 'WITH_BF_SOLID', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB', 'BF_SOLID', 'BF_SOLID_INC', 'BF_WINTAB', 'BF_WINTAB_INC', 'WITH_BF_YAFRAY', 'WITH_BF_FREETYPE', 'BF_FREETYPE', 'BF_FREETYPE_INC', 'BF_FREETYPE_LIB', 'BF_FREETYPE_LIBPATH', @@ -276,6 +276,7 @@ def read_opts(cfg, args): ('BF_BULLET_INC', 'Bullet include path', ''), ('BF_BULLET_LIB', 'Bullet library', ''), + (BoolVariable('WITH_BF_SOLID', 'Use Sumo/Solid deprecated physics system if true', True)), ('BF_SOLID', 'Solid base dir', '#/extern/solid'), ('BF_SOLID_INC', 'Solid include path', ''), ('BF_WINTAB', 'WinTab base dir', ''), From a4ad52f1aaa1c8ed0d2f1345cbff99769f353ae9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Feb 2009 17:19:30 +0000 Subject: [PATCH 214/252] New Pulse option for the collision sensor (off by default wont change existing logic) Previously only the first collision would trigger an event (no collisions a negative event ofcourse) With the Pulse option enabled, any change to the set of colliding objects will trigger an event. Added this because there was no way to count how many sheep were on a platform in YoFrankie without running a script periodically. Changes in collision are detected by comparing the number of objects colliding with the last event, as well as a hash made from the object pointers. Also changed the touch sensors internal list of colliding objects to only contain objects that match the property or material. - pulse isnt a great name, could change this. --- source/blender/makesdna/DNA_sensor_types.h | 1 + source/blender/src/buttons_logic.c | 14 ++-- .../Converter/KX_ConvertSensors.cpp | 8 ++- source/gameengine/Ketsji/KX_NearSensor.cpp | 1 + source/gameengine/Ketsji/KX_TouchSensor.cpp | 66 +++++++------------ source/gameengine/Ketsji/KX_TouchSensor.h | 16 ++++- 6 files changed, 53 insertions(+), 53 deletions(-) diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index d8a1ffc6c24..2cae2cc8ccb 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -238,6 +238,7 @@ typedef struct bJoystickSensor { * */ /* #define SENS_COLLISION_PROPERTY 0 */ #define SENS_COLLISION_MATERIAL 1 +#define SENS_COLLISION_PULSE 2 /* ray specific mode */ /* X-Ray means that the ray will traverse objects that don't have the property/material */ #define SENS_RAY_XRAY 2 diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 494dc05d8f9..775175ba332 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1131,17 +1131,21 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short /* The collision sensor will become a generic collision (i.e. it */ /* absorb the old touch sensor). */ - uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P",(short)(xco + 10),(short)(yco - 44), + uiDefButBitS(block, TOG, SENS_COLLISION_PULSE, B_REDR, "Pulse",(short)(xco + 10),(short)(yco - 44), + (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0, + "Changes to the set of colliding objects generate pulses"); + + uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P",(short)(xco + 10 + (0.20 * (width-20))),(short)(yco - 44), (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0, "Toggle collision on material or property."); if (cs->mode & SENS_COLLISION_MATERIAL) { - uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.20 * (width-20)), - (short)(yco-44), (short)(0.8*(width-20)), 19, &cs->materialName, 0, 31, 0, 0, + uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.40 * (width-20)), + (short)(yco-44), (short)(0.6*(width-20)), 19, &cs->materialName, 0, 31, 0, 0, "Only look for Objects with this material"); } else { - uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.20 * (width-20)), (short)(yco-44), - (short)(0.8*(width-20)), 19, &cs->name, 0, 31, 0, 0, + uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.40 * (width-20)), (short)(yco-44), + (short)(0.6*(width-20)), 19, &cs->name, 0, 31, 0, 0, "Only look for Objects with this property"); } diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 13b7f43195d..c9b51807767 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -306,12 +306,12 @@ void BL_ConvertSensors(struct Object* blenderobject, { // collision sensor can sense both materials and properties. - bool bFindMaterial = false; + bool bFindMaterial = false, bTouchPulse = false; bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data; - bFindMaterial = (blendertouchsensor->mode - & SENS_COLLISION_MATERIAL); + bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL); + bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE); STR_String touchPropOrMatName = ( bFindMaterial ? @@ -324,6 +324,7 @@ void BL_ConvertSensors(struct Object* blenderobject, gamesensor = new KX_TouchSensor(eventmgr, gameobj, bFindMaterial, + bTouchPulse, touchPropOrMatName); } @@ -349,6 +350,7 @@ void BL_ConvertSensors(struct Object* blenderobject, gamesensor = new KX_TouchSensor(eventmgr, gameobj, bFindMaterial, + false, touchpropertyname); } } diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 5b1df8b1fe1..a4aebdd8b6b 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -52,6 +52,7 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr, :KX_TouchSensor(eventmgr, gameobj, bFindMaterial, + false, touchedpropname, /* scene, */ T), diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 0b4d66dbb34..a30dc34e2fa 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -59,6 +59,7 @@ void KX_TouchSensor::EndFrame() { m_colliders->ReleaseAndRemoveAll(); m_hitObject = NULL; m_bTriggered = false; + m_bColliderHash = 0; } void KX_TouchSensor::UnregisterToManager() @@ -72,7 +73,6 @@ bool KX_TouchSensor::Evaluate(CValue* event) { bool result = false; bool reset = m_reset && m_level; - m_reset = false; if (m_bTriggered != m_bLastTriggered) { @@ -84,13 +84,24 @@ bool KX_TouchSensor::Evaluate(CValue* event) if (reset) // force an event result = true; + + if (m_bTouchPulse) { /* pulse on changes to the colliders */ + int count = m_colliders->GetCount(); + + if (m_bLastCount!=count || m_bColliderHash!=m_bLastColliderHash) { + m_bLastCount = count; + m_bLastColliderHash= m_bColliderHash; + result = true; + } + } return result; } -KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,const STR_String& touchedpropname,PyTypeObject* T) +KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,bool bTouchPulse,const STR_String& touchedpropname,PyTypeObject* T) :SCA_ISensor(gameobj,eventmgr,T), m_touchedpropname(touchedpropname), m_bFindMaterial(bFindMaterial), +m_bTouchPulse(bTouchPulse), m_eventmgr(eventmgr) /*m_sumoObj(sumoObj),*/ { @@ -116,6 +127,8 @@ void KX_TouchSensor::Init() m_bCollision = false; m_bTriggered = false; m_bLastTriggered = (m_invert)?true:false; + m_bLastCount = 0; + m_bColliderHash = m_bLastColliderHash = 0; m_hitObject = NULL; m_reset = true; } @@ -191,8 +204,6 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll if (m_links && !m_suspended && gameobj && (gameobj != parent) && client_info->isActor()) { - if (!m_colliders->SearchValue(gameobj)) - m_colliders->Add(gameobj->AddRef()); bool found = m_touchedpropname.IsEmpty(); if (!found) @@ -210,6 +221,12 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll } if (found) { + if (!m_colliders->SearchValue(gameobj)) { + m_colliders->Add(gameobj->AddRef()); + + if (m_bTouchPulse) + m_bColliderHash += (uint_ptr)(static_cast(&gameobj)); + } m_bTriggered = true; m_hitObject = gameobj; //printf("KX_TouchSensor::HandleCollision\n"); @@ -334,46 +351,7 @@ PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self, /* to do: do Py_IncRef if the object is already known in Python */ /* otherwise, this leaks memory */ - - if ( m_touchedpropname.IsEmpty() ) { - return m_colliders->AddRef(); - } else { - CListValue* newList = new CListValue(); - int i = 0; - while (i < m_colliders->GetCount()) { - if (m_bFindMaterial) { - /* need to associate the CValues from the list to material - * names. The collider list _should_ contains only - * KX_GameObjects. I am loathe to cast them, though... The - * material name must be retrieved from Sumo. To a Sumo - * object, a client-info block is attached. This block - * contains the material name. - * - this also doesn't work (obviously) for multi-materials... - */ - KX_GameObject* gameob = (KX_GameObject*) m_colliders->GetValue(i); - PHY_IPhysicsController* spc = dynamic_cast(gameob->GetPhysicsController()); - - if (spc) { - KX_ClientObjectInfo* cl_inf = static_cast(spc->getNewClientInfo()); - - if (NULL != cl_inf->m_auxilary_info && m_touchedpropname == ((char*)cl_inf->m_auxilary_info)) { - newList->Add(m_colliders->GetValue(i)->AddRef()); - } - } - - } else { - CValue* val = m_colliders->GetValue(i)->FindIdentifier(m_touchedpropname); - if (!val->IsError()) { - newList->Add(m_colliders->GetValue(i)->AddRef()); - } - val->Release(); - } - - i++; - } - return newList->AddRef(); - } - + return m_colliders->AddRef(); } /* 5. getTouchMaterial */ diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index e07f89f0a31..c463226a5be 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -39,6 +39,12 @@ struct PHY_CollData; #include "KX_ClientObjectInfo.h" +#if defined(_WIN64) +typedef unsigned __int64 uint_ptr; +#else +typedef unsigned long uint_ptr; +#endif + class KX_TouchEventManager; class KX_TouchSensor : public SCA_ISensor @@ -51,6 +57,7 @@ protected: */ STR_String m_touchedpropname; bool m_bFindMaterial; + bool m_bTouchPulse; /* changes in the colliding objects trigger pulses */ class SCA_EventManager* m_eventmgr; class PHY_IPhysicsController* m_physCtrl; @@ -58,13 +65,20 @@ protected: bool m_bCollision; bool m_bTriggered; bool m_bLastTriggered; + + // Use with m_bTouchPulse to detect changes + int m_bLastCount; /* size of m_colliders last tick */ + uint_ptr m_bColliderHash; /* hash collision objects pointers to trigger incase one object collides and another takes its place */ + uint_ptr m_bLastColliderHash; + SCA_IObject* m_hitObject; class CListValue* m_colliders; public: KX_TouchSensor(class SCA_EventManager* eventmgr, class KX_GameObject* gameobj, - bool fFindMaterial, + bool bFindMaterial, + bool bTouchPulse, const STR_String& touchedpropname, PyTypeObject* T=&Type) ; virtual ~KX_TouchSensor(); From 97e70ef3c41cc821da86bae0aa6b9830c52e784a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Feb 2009 17:20:41 +0000 Subject: [PATCH 215/252] forgot this file- remove Sumo from the menu if its disabled. --- source/blender/src/buttons_shading.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 98b78d54fff..fe4649f31f4 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2185,8 +2185,13 @@ static void world_panel_mistaph(World *wrld) #ifdef USE_ODE "Physics %t|None %x0|Sumo %x2|Ode %x4 |Bullet %x5", #else - //"Physics %t|None %x0|Sumo %x2|Bullet %x5", //disable Sumo, until too many people complain ;-) + +#ifdef USE_SUMO_SOLID "Physics %t|None %x0|Sumo (deprecated) %x2|Bullet %x5", +#else + "Physics %t|None %x0|Bullet %x5", //disable Sumo, until too many people complain ;-) +#endif + #endif 10,180,140,19, &wrld->physicsEngine, 0, 0, 0, 0, "Physics Engine"); From dff781c2a8c77f35fefe00b0a561235861d4d053 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 25 Feb 2009 20:07:45 +0000 Subject: [PATCH 216/252] Continue snapping cleaning job. Snap to armature correctly in edit mode and when posed. Merge snap and embed in skeleton sketching. Ctrl key does both, depends on the snap mode (volume or other). Snaps to other strokes in all snapping mode except Volume. --- source/blender/include/BIF_transform.h | 2 + source/blender/src/editarmature_sketch.c | 146 ++++--------------- source/blender/src/transform_snap.c | 170 +++++++++++------------ 3 files changed, 116 insertions(+), 202 deletions(-) diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index 8a8d7dc3b4a..096201f86d0 100644 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -148,6 +148,8 @@ typedef enum SnapMode NOT_ACTIVE = 1 } SnapMode; +#define SNAP_MIN_DISTANCE 30 + int snapObjects(int *dist, float *loc, float *no, SnapMode mode); int peelObjects(struct ListBase *depth_peels, short mval[2]); diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c index 7314add5e7b..1452a3d0441 100644 --- a/source/blender/src/editarmature_sketch.c +++ b/source/blender/src/editarmature_sketch.c @@ -71,7 +71,6 @@ typedef enum SK_PType typedef enum SK_PMode { - PT_EMBED, PT_SNAP, PT_PROJECT, } SK_PMode; @@ -178,8 +177,6 @@ SK_Point boneSnap; int LAST_SNAP_POINT_VALID = 0; float LAST_SNAP_POINT[3]; -#define SNAP_MIN_DISTANCE 12 - /******************** PROTOTYPES ******************************/ void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end); @@ -1474,100 +1471,7 @@ int sk_addStrokeDrawPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) return 1; } - -int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *source_stk, SK_DrawData *dd) -{ - SK_Stroke *stk; - int dist = SNAP_MIN_DISTANCE; - int point_added = 0; - - for (stk = sketch->strokes.first; stk; stk = stk->next) - { - SK_Point *spt = NULL; - if (stk == source_stk) - { - spt = sk_snapPointStroke(stk, dd->mval, &dist, NULL, 0); - } - else - { - spt = sk_snapPointStroke(stk, dd->mval, &dist, NULL, 1); - } - - if (spt != NULL) - { - VECCOPY(pt->p, spt->p); - point_added = 1; - } - } - - /* check on bones */ - { - SK_Point *spt = sk_snapPointArmature(G.obedit, &G.edbo, dd->mval, &dist); - - if (spt != NULL) - { - VECCOPY(pt->p, spt->p); - point_added = 1; - } - } - - if (point_added) - { - pt->type = PT_EXACT; - pt->mode = PT_SNAP; - } - - return point_added; -} - -int sk_addStrokeSnapPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - int point_added = 0; - SK_Point pt; - - sk_initPoint(&pt); - - point_added = sk_getStrokeSnapPoint(&pt, sketch, stk, dd); - - if (point_added) - { - float final_p[3]; - float distance; - float length; - int i, total; - - VECCOPY(final_p, pt.p); - - sk_projectDrawPoint(pt.p, stk, dd); - sk_appendStrokePoint(stk, &pt); - - /* update all previous point to give smooth Z progresion */ - total = 0; - length = 0; - for (i = stk->nb_points - 2; i > 0; i--) - { - length += VecLenf(stk->points[i].p, stk->points[i + 1].p); - total++; - if (stk->points[i].type == PT_EXACT) - { - break; - } - } - - if (total > 1) - { - distance = sk_distanceDepth(final_p, stk->points[i].p); - - sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance); - } - - VECCOPY(stk->points[stk->nb_points - 1].p, final_p); - } - - return point_added; -} - -int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) +int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { int point_added = 0; @@ -1657,7 +1561,7 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D if (dist != FLT_MAX) { pt->type = dd->type; - pt->mode = PT_EMBED; + pt->mode = PT_SNAP; VECCOPY(pt->p, p); point_added = 1; @@ -1667,16 +1571,39 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D } else { + SK_Stroke *snap_stk; float vec[3]; float no[3]; int found = 0; - int dist = 40; // Use a user defined value here + int dist = SNAP_MIN_DISTANCE; // Use a user defined value here + /* snap to strokes */ + // if (G.scene->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */ + for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next) + { + SK_Point *spt = NULL; + if (snap_stk == stk) + { + spt = sk_snapPointStroke(snap_stk, dd->mval, &dist, NULL, 0); + } + else + { + spt = sk_snapPointStroke(snap_stk, dd->mval, &dist, NULL, 1); + } + + if (spt != NULL) + { + VECCOPY(pt->p, spt->p); + point_added = 1; + } + } + + /* try to snap to closer object */ found = snapObjects(&dist, vec, no, NOT_SELECTED); if (found == 1) { pt->type = dd->type; - pt->mode = PT_EMBED; + pt->mode = PT_SNAP; VECCOPY(pt->p, vec); point_added = 1; @@ -1686,14 +1613,14 @@ int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_D return point_added; } -int sk_addStrokeEmbedPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) +int sk_addStrokeSnapPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { int point_added; SK_Point pt; sk_initPoint(&pt); - point_added = sk_getStrokeEmbedPoint(&pt, sketch, stk, dd); + point_added = sk_getStrokeSnapPoint(&pt, sketch, stk, dd); if (point_added) { @@ -1714,7 +1641,7 @@ int sk_addStrokeEmbedPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) { length += VecLenf(stk->points[i].p, stk->points[i + 1].p); total++; - if (stk->points[i].mode == PT_EMBED || stk->points[i].type == PT_EXACT) + if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT) { break; } @@ -1744,11 +1671,6 @@ void sk_addStrokePoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short point_added = sk_addStrokeSnapPoint(sketch, stk, dd); } - if (point_added == 0 && qual & LR_SHIFTKEY) - { - point_added = sk_addStrokeEmbedPoint(sketch, stk, dd); - } - if (point_added == 0) { point_added = sk_addStrokeDrawPoint(sketch, stk, dd); @@ -1767,11 +1689,6 @@ void sk_getStrokePoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawD if (qual & LR_CTRLKEY) { point_added = sk_getStrokeSnapPoint(pt, sketch, stk, dd); - } - - if (point_added == 0 && qual & LR_SHIFTKEY) - { - point_added = sk_getStrokeEmbedPoint(pt, sketch, stk, dd); LAST_SNAP_POINT_VALID = 1; VECCOPY(LAST_SNAP_POINT, pt->p); } @@ -2840,9 +2757,6 @@ void sk_drawSketch(SK_Sketch *sketch, int with_names) switch (sketch->next_point.mode) { case PT_SNAP: - glColor3f(0, 0.5, 1); - break; - case PT_EMBED: glColor3f(0, 1, 0); break; case PT_PROJECT: diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 3353c209d67..6be8b0e881a 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -33,6 +33,7 @@ #include "PIL_time.h" +#include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -50,6 +51,7 @@ #include "editmesh.h" #include "BIF_editsima.h" +#include "BIF_editarmature.h" #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_mywindow.h" @@ -485,7 +487,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) float loc[3]; float no[3]; int found = 0; - int dist = 40; // Use a user defined value here + int dist = SNAP_MIN_DISTANCE; // Use a user defined value here SnapMode mode; if (G.scene->snap_mode == SCE_SNAP_MODE_VOLUME) @@ -593,7 +595,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) mode = NOT_ACTIVE; } - found = snapObjects(&dist, loc, no, NOT_SELECTED); + found = snapObjects(&dist, loc, no, mode); } if (found == 1) @@ -921,7 +923,7 @@ int snapEdge(float v1co[3], short v1no[3], float v2co[3], short v2no[3], short m * this takes care of series of connected edges a bit slanted w.r.t the viewport * otherwise, it would stick to the verts of the closest edge and not slide along merrily * */ - if (new_dist <= *dist && new_depth < *depth * 1.01) + if (new_dist <= *dist && new_depth < *depth * 1.001) { float n1[3], n2[3]; @@ -996,9 +998,8 @@ int snapVertex(float vco[3], short vno[3], short mval[2], float ray_start[3], fl return retval; } -int snapArmature(Object *ob, bArmature *ar, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth) +int snapArmature(Object *ob, bArmature *arm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth, int editarmature) { - Bone *b = ar->bonebase.first; float imat[4][4]; float ray_start_local[3], ray_normal_local[3]; int retval = 0; @@ -1010,42 +1011,50 @@ int snapArmature(Object *ob, bArmature *ar, float obmat[][4], float ray_start[3] Mat4MulVecfl(imat, ray_start_local); Mat4Mul3Vecfl(imat, ray_normal_local); - - while(b) + + if(editarmature) { - switch (G.scene->snap_mode) - { - case SCE_SNAP_MODE_VERTEX: - retval |= snapVertex(b->arm_head, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); - retval |= snapVertex(b->arm_tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); - break; - case SCE_SNAP_MODE_EDGE: - retval |= snapEdge(b->arm_head, NULL, b->arm_tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); - break; - } - - - if (b->childbase.first != NULL) - { - b = b->childbase.first; - } - else - { - while(1) - { - if (b->next != NULL) - { - b = b->next; - break; + EditBone *eBone; + + for (eBone=G.edbo.first; eBone; eBone=eBone->next) { + if (eBone->layer & arm->layer) { + /* skip hidden or moving (selected) bones */ + if ((eBone->flag & (BONE_HIDDEN_A|BONE_ROOTSEL|BONE_TIPSEL))==0) { + switch (G.scene->snap_mode) + { + case SCE_SNAP_MODE_VERTEX: + retval |= snapVertex(eBone->head, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + retval |= snapVertex(eBone->tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + break; + case SCE_SNAP_MODE_EDGE: + retval |= snapEdge(eBone->head, NULL, eBone->tail, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + break; + } } - else if (b->parent != NULL) + } + } + } + else if (ob->pose && ob->pose->chanbase.first) + { + bPoseChannel *pchan; + Bone *bone; + + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + bone= pchan->bone; + /* skip hidden bones */ + if (bone && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) { + float *head_vec = pchan->pose_head; + float *tail_vec = pchan->pose_tail; + + switch (G.scene->snap_mode) { - b = b->parent; - } - else /* nothing to go to */ - { - b = NULL; - break; + case SCE_SNAP_MODE_VERTEX: + retval |= snapVertex(head_vec, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + retval |= snapVertex(tail_vec, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + break; + case SCE_SNAP_MODE_EDGE: + retval |= snapEdge(head_vec, NULL, tail_vec, NULL, mval, ray_start, ray_start_local, ray_normal_local, obmat, NULL, loc, NULL, dist, depth); + break; } } } @@ -1288,6 +1297,40 @@ int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta return retval; } +int snapObject(Object *ob, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth) +{ + int editobject = 0; + int retval = 0; + + if (ob == G.obedit) + { + editobject = 1; + } + + if (ob->type == OB_MESH) { + DerivedMesh *dm; + + if (editobject) + { + dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); + } + else + { + dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + } + + retval = snapDerivedMesh(ob, dm, obmat, ray_start, ray_normal, mval, loc, no, dist, depth, editobject); + + dm->release(dm); + } + else if (ob->type == OB_ARMATURE) + { + retval = snapArmature(ob, ob->data, obmat, ray_start, ray_normal, mval, loc, no, dist, depth, editobject); + } + + return retval; +} + int snapObjects(int *dist, float *loc, float *no, SnapMode mode) { Base *base; float depth = FLT_MAX; @@ -1300,17 +1343,9 @@ int snapObjects(int *dist, float *loc, float *no, SnapMode mode) { if (mode == NOT_ACTIVE) { - DerivedMesh *dm; Object *ob = G.obedit; - if (ob->type == OB_MESH) - { - dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); - - retval = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 1); - - dm->release(dm); - } + retval |= snapObject(ob, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth); } base= FIRSTBASE; @@ -1327,50 +1362,13 @@ int snapObjects(int *dist, float *loc, float *no, SnapMode mode) { { Object *ob = dupli_ob->ob; - if (ob->type == OB_MESH) { - DerivedMesh *dm; - int editmesh = 0; - int val; - - if (ob == G.obedit) - { - dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); - editmesh = 1; - } - else - { - dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); - } - - val = snapDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth, editmesh); - - retval = retval || val; - - dm->release(dm); - } + retval |= snapObject(ob, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth); } free_object_duplilist(lb); } - if (ob->type == OB_MESH) { - DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); - int val; - - val = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0); - - retval = retval || val; - - dm->release(dm); - } - else if (ob->type == OB_ARMATURE) - { - int val; - - val = snapArmature(ob, ob->data, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth); - - retval = retval || val; - } + retval |= snapObject(ob, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth); } } From 6bfb8ca6b09e983fe757c9590b462b113ad28b72 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Feb 2009 04:17:23 +0000 Subject: [PATCH 217/252] - Attributes for the collision sensor: propertyName, materialCheck, pulseCollisions, objectHit and objectHitList. Removed a check in Python API touch.setProperty() for the property name on the sensor owner before allowing the name to be set - it makes no sense and isnt checked when creating the sensor. - SCA_DelaySensor.py indent error making epydoc fail. --- source/gameengine/Ketsji/KX_NearSensor.cpp | 8 +- source/gameengine/Ketsji/KX_TouchSensor.cpp | 100 ++++++++++++-------- source/gameengine/Ketsji/KX_TouchSensor.h | 15 +-- source/gameengine/PyDoc/KX_TouchSensor.py | 32 ++++--- source/gameengine/PyDoc/SCA_DelaySensor.py | 7 +- 5 files changed, 100 insertions(+), 62 deletions(-) diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index a4aebdd8b6b..d859f670b07 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -311,10 +311,10 @@ PyParentObject KX_NearSensor::Parents[] = { PyMethodDef KX_NearSensor::Methods[] = { - {"setProperty", (PyCFunction) KX_NearSensor::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, - {"getProperty", (PyCFunction) KX_NearSensor::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, - {"getHitObject",(PyCFunction) KX_NearSensor::sPyGetHitObject, METH_VARARGS, (PY_METHODCHAR)GetHitObject_doc}, - {"getHitObjectList", (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_VARARGS, (PY_METHODCHAR)GetHitObjectList_doc}, + {"setProperty", (PyCFunction) KX_NearSensor::sPySetProperty, METH_O, (PY_METHODCHAR)SetProperty_doc}, + {"getProperty", (PyCFunction) KX_NearSensor::sPyGetProperty, METH_NOARGS, (PY_METHODCHAR)GetProperty_doc}, + {"getHitObject",(PyCFunction) KX_NearSensor::sPyGetHitObject, METH_NOARGS, (PY_METHODCHAR)GetHitObject_doc}, + {"getHitObjectList", (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_NOARGS, (PY_METHODCHAR)GetHitObjectList_doc}, {NULL,NULL} //Sentinel }; diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index a30dc34e2fa..de4b5c401fc 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -270,20 +270,57 @@ PyParentObject KX_TouchSensor::Parents[] = { PyMethodDef KX_TouchSensor::Methods[] = { {"setProperty", - (PyCFunction) KX_TouchSensor::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, + (PyCFunction) KX_TouchSensor::sPySetProperty, METH_O, (PY_METHODCHAR)SetProperty_doc}, {"getProperty", - (PyCFunction) KX_TouchSensor::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc}, + (PyCFunction) KX_TouchSensor::sPyGetProperty, METH_NOARGS, (PY_METHODCHAR)GetProperty_doc}, {"getHitObject", - (PyCFunction) KX_TouchSensor::sPyGetHitObject, METH_VARARGS, (PY_METHODCHAR)GetHitObject_doc}, + (PyCFunction) KX_TouchSensor::sPyGetHitObject, METH_NOARGS, (PY_METHODCHAR)GetHitObject_doc}, {"getHitObjectList", - (PyCFunction) KX_TouchSensor::sPyGetHitObjectList, METH_VARARGS, (PY_METHODCHAR)GetHitObjectList_doc}, + (PyCFunction) KX_TouchSensor::sPyGetHitObjectList, METH_NOARGS, (PY_METHODCHAR)GetHitObjectList_doc}, {NULL,NULL} //Sentinel }; -PyObject* KX_TouchSensor::_getattr(const char *attr) { +PyAttributeDef KX_TouchSensor::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW("propertyName",0,100,false,KX_TouchSensor,m_touchedpropname), + KX_PYATTRIBUTE_BOOL_RW("materialCheck",KX_TouchSensor,m_bFindMaterial), + KX_PYATTRIBUTE_BOOL_RW("pulseCollisions",KX_TouchSensor,m_bTouchPulse), + { NULL } //Sentinel +}; + +PyObject* KX_TouchSensor::_getattr(const char *attr) +{ + if (!strcmp(attr, "objectHit")) { + if (m_hitObject) return m_hitObject->AddRef(); + else Py_RETURN_NONE; + } + if (!strcmp(attr, "objectHitList")) { + return m_colliders->AddRef(); + } + + PyObject* object= _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; _getattr_up(SCA_ISensor); } +int KX_TouchSensor::_setattr(const char *attr, PyObject *value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + + if (!strcmp(attr, "objectHit")) { + PyErr_SetString(PyExc_AttributeError, "attribute \"objectHit\" is read only"); + return 1; + } + if (!strcmp(attr, "objectHitList")) { + PyErr_SetString(PyExc_AttributeError, "attribute \"objectHit\" is read only"); + return 1; + } + + return SCA_ISensor::_setattr(attr, value); +} + /* Python API */ /* 1. setProperty */ @@ -293,23 +330,16 @@ const char KX_TouchSensor::SetProperty_doc[] = "\tSet the property or material to collide with. Use\n" "\tsetTouchMaterial() to switch between properties and\n" "\tmaterials."; -PyObject* KX_TouchSensor::PySetProperty(PyObject* self, - PyObject* args, - PyObject* kwds) { - char *nameArg; - if (!PyArg_ParseTuple(args, "s", &nameArg)) { +PyObject* KX_TouchSensor::PySetProperty(PyObject* self, PyObject* value) +{ + ShowDeprecationWarning("setProperty()", "the propertyName property"); + char *nameArg= PyString_AsString(value); + if (nameArg==NULL) { + PyErr_SetString(PyExc_ValueError, "expected a "); return NULL; } - - CValue* prop = GetParent()->FindIdentifier(nameArg); - - if (!prop->IsError()) { - m_touchedpropname = nameArg; - } else { - ; /* not found ... */ - } - prop->Release(); + m_touchedpropname = nameArg; Py_RETURN_NONE; } /* 2. getProperty */ @@ -318,19 +348,16 @@ const char KX_TouchSensor::GetProperty_doc[] = "\tReturns the property or material to collide with. Use\n" "\tgetTouchMaterial() to find out whether this sensor\n" "\tlooks for properties or materials."; -PyObject* KX_TouchSensor::PyGetProperty(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_TouchSensor::PyGetProperty(PyObject* self) { return PyString_FromString(m_touchedpropname); } const char KX_TouchSensor::GetHitObject_doc[] = "getHitObject()\n" ; -PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self) { + ShowDeprecationWarning("getHitObject()", "the objectHit property"); /* to do: do Py_IncRef if the object is already known in Python */ /* otherwise, this leaks memory */ if (m_hitObject) @@ -344,13 +371,11 @@ const char KX_TouchSensor::GetHitObjectList_doc[] = "getHitObjectList()\n" "\tReturn a list of the objects this object collided with,\n" "\tbut only those matching the property/material condition.\n"; -PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self) { - + ShowDeprecationWarning("getHitObjectList()", "the objectHitList property"); /* to do: do Py_IncRef if the object is already known in Python */ - /* otherwise, this leaks memory */ + /* otherwise, this leaks memory */ /* Edit, this seems ok and not to leak memory - Campbell */ return m_colliders->AddRef(); } @@ -359,24 +384,25 @@ const char KX_TouchSensor::GetTouchMaterial_doc[] = "getTouchMaterial()\n" "\tReturns KX_TRUE if this sensor looks for a specific material,\n" "\tKX_FALSE if it looks for a specific property.\n" ; -PyObject* KX_TouchSensor::PyGetTouchMaterial(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_TouchSensor::PyGetTouchMaterial(PyObject* self) { + ShowDeprecationWarning("getTouchMaterial()", "the materialCheck property"); return PyInt_FromLong(m_bFindMaterial); } /* 6. setTouchMaterial */ +#if 0 const char KX_TouchSensor::SetTouchMaterial_doc[] = "setTouchMaterial(flag)\n" "\t- flag: KX_TRUE or KX_FALSE.\n" "\tSet flag to KX_TRUE to switch on positive pulse mode,\n" "\tKX_FALSE to switch off positive pulse mode.\n" ; -PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject *value) { - int pulseArg = 0; + int pulseArg = PyInt_AsLong(value); - if(!PyArg_ParseTuple(args, "i", &pulseArg)) { + if(pulseArg ==-1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_ValueError, "expected a bool"); return NULL; } @@ -384,6 +410,6 @@ PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject* args, PyO Py_RETURN_NONE; } - +#endif /* eof */ diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index c463226a5be..c523736967b 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -121,19 +121,22 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject *value); /* 1. setProperty */ - KX_PYMETHOD_DOC(KX_TouchSensor,SetProperty); + KX_PYMETHOD_DOC_O(KX_TouchSensor,SetProperty); /* 2. getProperty */ - KX_PYMETHOD_DOC(KX_TouchSensor,GetProperty); + KX_PYMETHOD_DOC_NOARGS(KX_TouchSensor,GetProperty); /* 3. getHitObject */ - KX_PYMETHOD_DOC(KX_TouchSensor,GetHitObject); + KX_PYMETHOD_DOC_NOARGS(KX_TouchSensor,GetHitObject); /* 4. getHitObject */ - KX_PYMETHOD_DOC(KX_TouchSensor,GetHitObjectList); + KX_PYMETHOD_DOC_NOARGS(KX_TouchSensor,GetHitObjectList); /* 5. getTouchMaterial */ - KX_PYMETHOD_DOC(KX_TouchSensor,GetTouchMaterial); + KX_PYMETHOD_DOC_NOARGS(KX_TouchSensor,GetTouchMaterial); +#if 0 /* 6. setTouchMaterial */ - KX_PYMETHOD_DOC(KX_TouchSensor,SetTouchMaterial); + KX_PYMETHOD_DOC_O(KX_TouchSensor,SetTouchMaterial); +#endif }; diff --git a/source/gameengine/PyDoc/KX_TouchSensor.py b/source/gameengine/PyDoc/KX_TouchSensor.py index f2cc101af10..4f020930c4c 100644 --- a/source/gameengine/PyDoc/KX_TouchSensor.py +++ b/source/gameengine/PyDoc/KX_TouchSensor.py @@ -1,13 +1,26 @@ # $Id$ # Documentation for KX_TouchSensor from SCA_ISensor import * +from KX_GameObject import * class KX_TouchSensor(SCA_ISensor): """ Touch sensor detects collisions between objects. + + @ivar propertyName: The name of the property or material this sensor detects (depending on the materialCheck property). + @type propertyName: string + @ivar materialCheck: when enabled this sensor checks for object materials rather then properties. + @type materialCheck: bool + @ivar pulseCollisions: The last collided object. + @type pulseCollisions: bool + @ivar objectHit: The last collided object. (Read Only) + @type objectHit: L{KX_GameObject} or None + @ivar objectHitList: A list of colliding objects. (Read Only) + @type objectHitList: list """ def setProperty(name): """ + DEPRECATED: use the propertyName property Set the property or material to collide with. Use setTouchMaterial() to switch between properties and materials. @@ -15,22 +28,25 @@ class KX_TouchSensor(SCA_ISensor): """ def getProperty(): """ + DEPRECATED: use the propertyName property Returns the property or material to collide with. Use getTouchMaterial() to find out whether this sensor - looks for properties or materials. + looks for properties or materials. (B{deprecated}) @rtype: string """ def getHitObject(): """ - Returns the last object hit by this touch sensor. + DEPRECATED: use the objectHit property + Returns the last object hit by this touch sensor. (B{deprecated}) @rtype: L{KX_GameObject} """ def getHitObjectList(): """ - Returns a list of all objects hit in the last frame. + DEPRECATED: use the objectHitList property + Returns a list of all objects hit in the last frame. (B{deprecated}) Only objects that have the requisite material/property are listed. @@ -38,13 +54,7 @@ class KX_TouchSensor(SCA_ISensor): """ def getTouchMaterial(): """ + DEPRECATED: use the materialCheck property Returns KX_TRUE if this sensor looks for a specific material, - KX_FALSE if it looks for a specific property. - """ - def setTouchMaterial(flag): - """ - Set flag to KX_TRUE to switch on positive pulse mode, - KX_FALSE to switch off positive pulse mode. - - @type flag: KX_TRUE or KX_FALSE. + KX_FALSE if it looks for a specific property. (B{deprecated}) """ diff --git a/source/gameengine/PyDoc/SCA_DelaySensor.py b/source/gameengine/PyDoc/SCA_DelaySensor.py index b99ed08bed5..6560df6573e 100644 --- a/source/gameengine/PyDoc/SCA_DelaySensor.py +++ b/source/gameengine/PyDoc/SCA_DelaySensor.py @@ -20,10 +20,9 @@ class SCA_DelaySensor(SCA_ISensor): @type delay: integer. @ivar duration: length of the ON period in number of frame after the initial OFF period. If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. - @type duration: integer - @ivar repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. - @type repeat: integer - + @type duration: integer + @ivar repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. + @type repeat: integer """ def setDelay(delay): """ From f87194820bdd20540203a7bb6b91e1932f9ebd16 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Feb 2009 04:40:00 +0000 Subject: [PATCH 218/252] openjpeg contained a C file with a main() function, user reported it was overriding blenderplayers. remove this file from building, other build systems should do this too. --- extern/libopenjpeg/SConscript | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extern/libopenjpeg/SConscript b/extern/libopenjpeg/SConscript index eb408c1e9c0..d14b8329580 100644 --- a/extern/libopenjpeg/SConscript +++ b/extern/libopenjpeg/SConscript @@ -5,6 +5,10 @@ import sys Import('env') sources = env.Glob('*.c') + +# This file contains a main() - can override blenders +sources.remove('t1_generate_luts.c') + incs = '.' flags = [] defs = [] From 936a6eeda87bfd36ada735e5edac06f161a5de25 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Feb 2009 05:17:54 +0000 Subject: [PATCH 219/252] small errors in touch sensor and gameObject --- source/gameengine/Ketsji/KX_GameObject.cpp | 2 +- source/gameengine/Ketsji/KX_TouchSensor.cpp | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 5e013a1c647..9c6bd2edf0e 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1170,7 +1170,7 @@ int KX_GameObject::_setattr(const char *attr, PyObject *value) // _setattr metho { if (!strcmp(attr, "parent")) { - PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()"); + PyErr_SetString(PyExc_AttributeError, "attribute \"parent\" is read only\nUse setParent()"); return 1; } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index de4b5c401fc..32fcc148395 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -284,6 +284,8 @@ PyAttributeDef KX_TouchSensor::Attributes[] = { KX_PYATTRIBUTE_STRING_RW("propertyName",0,100,false,KX_TouchSensor,m_touchedpropname), KX_PYATTRIBUTE_BOOL_RW("materialCheck",KX_TouchSensor,m_bFindMaterial), KX_PYATTRIBUTE_BOOL_RW("pulseCollisions",KX_TouchSensor,m_bTouchPulse), + KX_PYATTRIBUTE_DUMMY("objectHit"), + KX_PYATTRIBUTE_DUMMY("objectHitList"), { NULL } //Sentinel }; @@ -309,15 +311,6 @@ int KX_TouchSensor::_setattr(const char *attr, PyObject *value) if (ret >= 0) return ret; - if (!strcmp(attr, "objectHit")) { - PyErr_SetString(PyExc_AttributeError, "attribute \"objectHit\" is read only"); - return 1; - } - if (!strcmp(attr, "objectHitList")) { - PyErr_SetString(PyExc_AttributeError, "attribute \"objectHit\" is read only"); - return 1; - } - return SCA_ISensor::_setattr(attr, value); } From c785532becca59aa2d1b3ae67784b7ac2b733ec2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Feb 2009 09:04:06 +0000 Subject: [PATCH 220/252] Py BGE API Python dir(ob) for game types now includes attributes names, * Use "__dict__" rather then "__methods__" attribute to be Python 3.0 compatible * Added _getattr_dict() for getting the method and attribute names from a PyObject, rather then building it in the macro. * Added place holder *::Attribute array, needed for the _getattr_up macro. --- source/gameengine/Expressions/ListValue.cpp | 4 +- .../gameengine/Expressions/PyObjectPlus.cpp | 30 +++++++++++++++ source/gameengine/Expressions/PyObjectPlus.h | 37 +++++++------------ source/gameengine/Expressions/Value.cpp | 4 ++ .../GameLogic/SCA_2DFilterActuator.cpp | 3 ++ .../GameLogic/SCA_ANDController.cpp | 4 ++ .../gameengine/GameLogic/SCA_AlwaysSensor.cpp | 4 ++ source/gameengine/GameLogic/SCA_IObject.cpp | 3 ++ .../GameLogic/SCA_NANDController.cpp | 4 ++ .../GameLogic/SCA_NORController.cpp | 4 ++ .../gameengine/GameLogic/SCA_ORController.cpp | 5 +++ .../GameLogic/SCA_PythonController.cpp | 3 ++ .../GameLogic/SCA_XNORController.cpp | 4 ++ .../GameLogic/SCA_XORController.cpp | 4 ++ source/gameengine/Ketsji/BL_Shader.cpp | 3 ++ .../KXNetwork/KX_NetworkMessageActuator.cpp | 4 ++ .../KXNetwork/KX_NetworkMessageSensor.cpp | 4 ++ .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 3 ++ source/gameengine/Ketsji/KX_CDActuator.cpp | 4 +- source/gameengine/Ketsji/KX_Camera.cpp | 4 ++ .../Ketsji/KX_ConstraintActuator.cpp | 4 ++ .../Ketsji/KX_ConstraintWrapper.cpp | 4 ++ source/gameengine/Ketsji/KX_GameActuator.cpp | 4 ++ source/gameengine/Ketsji/KX_GameObject.cpp | 3 ++ source/gameengine/Ketsji/KX_IpoActuator.cpp | 4 ++ source/gameengine/Ketsji/KX_Light.cpp | 4 ++ source/gameengine/Ketsji/KX_MeshProxy.cpp | 4 ++ .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 4 ++ source/gameengine/Ketsji/KX_NearSensor.cpp | 3 ++ .../gameengine/Ketsji/KX_ObjectActuator.cpp | 4 ++ .../gameengine/Ketsji/KX_ParentActuator.cpp | 4 ++ source/gameengine/Ketsji/KX_PolyProxy.cpp | 4 ++ .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 3 ++ source/gameengine/Ketsji/KX_RadarSensor.cpp | 4 ++ source/gameengine/Ketsji/KX_RaySensor.cpp | 4 ++ .../Ketsji/KX_SCA_AddObjectActuator.cpp | 3 ++ .../Ketsji/KX_SCA_DynamicActuator.cpp | 3 ++ .../Ketsji/KX_SCA_EndObjectActuator.cpp | 3 ++ .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 4 +- source/gameengine/Ketsji/KX_Scene.cpp | 4 ++ source/gameengine/Ketsji/KX_SceneActuator.cpp | 4 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 4 +- source/gameengine/Ketsji/KX_StateActuator.cpp | 4 ++ .../gameengine/Ketsji/KX_TrackToActuator.cpp | 3 ++ .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 3 ++ source/gameengine/Ketsji/KX_VertexProxy.cpp | 4 ++ .../Ketsji/KX_VisibilityActuator.cpp | 4 ++ 47 files changed, 206 insertions(+), 29 deletions(-) diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 9acc6ad2cde..90a939af236 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -232,7 +232,9 @@ PyMethodDef CListValue::Methods[] = { {NULL,NULL} //Sentinel }; - +PyAttributeDef CListValue::Attributes[] = { + { NULL } //Sentinel +}; PyObject* CListValue::_getattr(const char *attr) { _getattr_up(CValue); diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index e04b42ee9cc..1bead0a7664 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -707,5 +707,35 @@ PyObject *PyObjectPlus::Py_isA(PyObject *value) // Python wrapper for isA Py_RETURN_FALSE; } +/* Utility function called by the macro _getattr_up() + * for getting ob.__dict__() values from our PyObject + * this is used by python for doing dir() on an object, so its good + * if we return a list of attributes and methods. + * + * Other then making dir() useful the value returned from __dict__() is not useful + * since every value is a Py_None + * */ +PyObject *_getattr_dict(PyObject *pydict, PyMethodDef *meth, PyAttributeDef *attrdef) +{ + if(pydict==NULL) { /* incase calling __dict__ on the parent of this object raised an error */ + PyErr_Clear(); + pydict = PyDict_New(); + } + + if(meth) { + for (; meth->ml_name != NULL; meth++) { + PyDict_SetItemString(pydict, meth->ml_name, Py_None); + } + } + + if(attrdef) { + for (; attrdef->m_name != NULL; attrdef++) { + PyDict_SetItemString(pydict, attrdef->m_name, Py_None); + } + } + + return pydict; +} + #endif //NO_EXP_PYTHON_EMBEDDING diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 37eae3a8c61..1a5f50a3d23 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -89,35 +89,22 @@ static inline void Py_Fatal(const char *M) { virtual PyParentObject *GetParents(void) {return Parents;} + // This defines the _getattr_up macro // which allows attribute and method calls // to be properly passed up the hierarchy. #define _getattr_up(Parent) \ - PyObject *rvalue = NULL; \ - if (!strcmp(attr, "__methods__")) { \ - PyObject *_attr_string = NULL; \ - PyMethodDef *meth = Methods; \ - rvalue = Parent::_getattr(attr); \ - if (rvalue==NULL) { \ - PyErr_Clear(); \ - rvalue = PyList_New(0); \ - } \ - if (meth) { \ - for (; meth->ml_name != NULL; meth++) { \ - _attr_string = PyString_FromString(meth->ml_name); \ - PyList_Append(rvalue, _attr_string); \ - Py_DECREF(_attr_string); \ - } \ + PyObject *rvalue = Py_FindMethod(Methods, this, attr); \ + \ + if (rvalue == NULL) { \ + PyErr_Clear(); \ + rvalue = Parent::_getattr(attr); \ } \ - } else { \ - rvalue = Py_FindMethod(Methods, this, attr); \ - if (rvalue == NULL) { \ - PyErr_Clear(); \ - rvalue = Parent::_getattr(attr); \ - } \ - } \ - return rvalue; \ - + if ((rvalue == NULL) && !strcmp(attr, "__dict__")) {\ + PyErr_Clear(); \ + rvalue = _getattr_dict(Parent::_getattr(attr), Methods, Attributes); \ + } \ + return rvalue; \ /** * These macros are helpfull when embedding Python routines. The second @@ -398,6 +385,8 @@ public: } }; +PyObject *_getattr_dict(PyObject *pydict, PyMethodDef *meth, PyAttributeDef *attrdef); + #endif // _adr_py_lib_h_ #endif //NO_EXP_PYTHON_EMBEDDING diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 9b26cda01b3..d29e3961c65 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -673,6 +673,10 @@ static PyMethodDef CValueMethods[] = { NULL,NULL} // Sentinel }; +PyAttributeDef CValue::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* CValue::_getattr(const char *attr) { diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 6fcb1be654c..7bf051f2b5c 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -113,6 +113,9 @@ PyMethodDef SCA_2DFilterActuator::Methods[] = { {NULL,NULL} }; +PyAttributeDef SCA_2DFilterActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* SCA_2DFilterActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index 98a3c2e96cd..b67ef7dabaf 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -137,6 +137,10 @@ PyMethodDef SCA_ANDController::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_ANDController::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* SCA_ANDController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index 76aa328aa48..154f0ad8cef 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -135,6 +135,10 @@ PyMethodDef SCA_AlwaysSensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_AlwaysSensor::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* SCA_AlwaysSensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); } diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index e5ca26eac85..d8f5f3eede5 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -407,6 +407,9 @@ PyMethodDef SCA_IObject::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_IObject::Attributes[] = { + { NULL } //Sentinel +}; PyObject* SCA_IObject::_getattr(const char *attr) { diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index 0efa8da153a..18426d75582 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -137,6 +137,10 @@ PyMethodDef SCA_NANDController::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_NANDController::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* SCA_NANDController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index fa24be9ebce..1de6a641c3d 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -137,6 +137,10 @@ PyMethodDef SCA_NORController::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_NORController::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* SCA_NORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index 42a29e1959b..61fbc889d90 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -129,6 +129,11 @@ PyMethodDef SCA_ORController::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_ORController::Attributes[] = { + { NULL } //Sentinel +}; + + PyObject* SCA_ORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 92852ee03cb..c75e36acab2 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -264,6 +264,9 @@ PyMethodDef SCA_PythonController::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_PythonController::Attributes[] = { + { NULL } //Sentinel +}; bool SCA_PythonController::Compile() { diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index b019aedc93d..b2734dd1b33 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -141,6 +141,10 @@ PyMethodDef SCA_XNORController::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_XNORController::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* SCA_XNORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index 11ffa19b8f1..662ef523d56 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -141,6 +141,10 @@ PyMethodDef SCA_XORController::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef SCA_XORController::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* SCA_XORController::_getattr(const char *attr) { _getattr_up(SCA_IController); } diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index e8281201d24..60cb288436a 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -767,6 +767,9 @@ PyMethodDef BL_Shader::Methods[] = {NULL,NULL} //Sentinel }; +PyAttributeDef BL_Shader::Attributes[] = { + { NULL } //Sentinel +}; PyTypeObject BL_Shader::Type = { PyObject_HEAD_INIT(&PyType_Type) diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp index 31f1d2dd3ee..4e5f27df2da 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp @@ -143,6 +143,10 @@ PyMethodDef KX_NetworkMessageActuator::Methods[] = { {NULL,NULL} // Sentinel }; +PyAttributeDef KX_NetworkMessageActuator::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_NetworkMessageActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index cb9956d4616..ac89d8b0716 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -213,6 +213,10 @@ PyMethodDef KX_NetworkMessageSensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_NetworkMessageSensor::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_NetworkMessageSensor::_getattr(const char *attr) { _getattr_up(SCA_ISensor); // implicit return! } diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 5fa19924267..b9bd7647f89 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -748,6 +748,9 @@ PyMethodDef KX_BlenderMaterial::Methods[] = {NULL,NULL} //Sentinel }; +PyAttributeDef KX_BlenderMaterial::Attributes[] = { + { NULL } //Sentinel +}; PyTypeObject KX_BlenderMaterial::Type = { PyObject_HEAD_INIT(&PyType_Type) diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp index 7d238e28add..ef7883910fd 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.cpp +++ b/source/gameengine/Ketsji/KX_CDActuator.cpp @@ -197,7 +197,9 @@ PyMethodDef KX_CDActuator::Methods[] = { {NULL,NULL,NULL,NULL} //Sentinel }; - +PyAttributeDef KX_CDActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_CDActuator::_getattr(const char *attr) { diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 99e2d3b7c06..5caac2fc670 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -483,6 +483,10 @@ PyMethodDef KX_Camera::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_Camera::Attributes[] = { + { NULL } //Sentinel +}; + char KX_Camera::doc[] = "Module KX_Camera\n\n" "Constants:\n" "\tINSIDE\n" diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index 8a7ff41dfa6..fba9544d702 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -612,6 +612,10 @@ PyMethodDef KX_ConstraintActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_ConstraintActuator::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_ConstraintActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index 9ceb4a05b06..f014c1896fe 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -130,3 +130,7 @@ PyMethodDef KX_ConstraintWrapper::Methods[] = { {"getConstraintId",(PyCFunction) KX_ConstraintWrapper::sPyGetConstraintId, METH_VARARGS}, {NULL,NULL} //Sentinel }; + +PyAttributeDef KX_ConstraintWrapper::Attributes[] = { + { NULL } //Sentinel +}; diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 3090c668f03..3c0695b5952 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -246,6 +246,10 @@ PyMethodDef KX_GameActuator::Methods[] = {NULL,NULL} //Sentinel }; +PyAttributeDef KX_GameActuator::Attributes[] = { + { NULL } //Sentinel +}; + /* getFile */ const char KX_GameActuator::GetFile_doc[] = "getFile()\n" diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 9c6bd2edf0e..95df9d51a26 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1033,6 +1033,9 @@ PyMethodDef KX_GameObject::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_GameObject::Attributes[] = { + { NULL } //Sentinel +}; /* diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index ca8419666b5..623a939bf62 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -457,6 +457,10 @@ PyMethodDef KX_IpoActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_IpoActuator::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_IpoActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 36700265260..a2e93ecdd36 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -301,6 +301,10 @@ PyMethodDef KX_LightObject::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_LightObject::Attributes[] = { + { NULL } //Sentinel +}; + char KX_LightObject::doc[] = "Module KX_LightObject\n\n" "Constants:\n" "\tSPOT\n" diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 4b949903c88..a0c0a496c06 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -86,6 +86,10 @@ KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh), {NULL,NULL} //Sentinel }; +PyAttributeDef KX_MeshProxy::Attributes[] = { + { NULL } //Sentinel +}; + void KX_MeshProxy::SetMeshModified(bool v) { m_meshobj->SetMeshModified(v); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index afe4cd1e2a4..384034485e7 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -332,6 +332,10 @@ PyMethodDef KX_MouseFocusSensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_MouseFocusSensor::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_MouseFocusSensor::_getattr(const char *attr) { _getattr_up(SCA_MouseSensor); } diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index d859f670b07..066387abb93 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -318,6 +318,9 @@ PyMethodDef KX_NearSensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_NearSensor::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_NearSensor::_getattr(const char *attr) diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index b647c72fc10..0666261b470 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -332,6 +332,10 @@ PyMethodDef KX_ObjectActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_ObjectActuator::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_ObjectActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); }; diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 5a908186235..84d7ccb9c05 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -172,6 +172,10 @@ PyMethodDef KX_ParentActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_ParentActuator::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_ParentActuator::_getattr(const char *attr) { if (!strcmp(attr, "object")) { diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index ff962d57c9d..b4bdd77fb66 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -77,6 +77,10 @@ PyMethodDef KX_PolyProxy::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_PolyProxy::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_PolyProxy::_getattr(const char *attr) { if (!strcmp(attr, "matname")) diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 52c5b013e65..bbaf697b168 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -180,6 +180,9 @@ PyMethodDef KX_PolygonMaterial::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_PolygonMaterial::Attributes[] = { + { NULL } //Sentinel +}; PyTypeObject KX_PolygonMaterial::Type = { PyObject_HEAD_INIT(&PyType_Type) diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 2ba1126a633..c347faaee1a 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -230,6 +230,10 @@ PyMethodDef KX_RadarSensor::Methods[] = { {NULL,NULL,NULL,NULL} //Sentinel }; +PyAttributeDef KX_RadarSensor::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_RadarSensor::_getattr(const char *attr) { _getattr_up(KX_TouchSensor); } diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index c7cb53f64ed..ce12b983147 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -343,6 +343,10 @@ PyMethodDef KX_RaySensor::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_RaySensor::Attributes[] = { + { NULL } //Sentinel +}; + const char KX_RaySensor::GetHitObject_doc[] = "getHitObject()\n" "\tReturns the name of the object that was hit by this ray.\n"; diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 017ab5d6c97..68b704f4889 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -204,6 +204,9 @@ PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_SCA_AddObjectActuator::_getattr(const char *attr) { diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index 1aba05c1d83..394bb667728 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -85,6 +85,9 @@ PyMethodDef KX_SCA_DynamicActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_SCA_DynamicActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_SCA_DynamicActuator::_getattr(const char *attr) diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index 443921d22b0..9268a1df5f0 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -127,6 +127,9 @@ PyMethodDef KX_SCA_EndObjectActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_SCA_EndObjectActuator::_getattr(const char *attr) { diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index ccc3b8fdb18..502990b2b27 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -89,7 +89,9 @@ PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { {NULL,NULL} //Sentinel }; - +PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const char *attr) { diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 5ae1abc6a89..073cfc98bf1 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1525,6 +1525,10 @@ PyMethodDef KX_Scene::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_Scene::Attributes[] = { + { NULL } //Sentinel +}; + PyTypeObject KX_Scene::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 8e33177cf3a..1cad4e21352 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -268,7 +268,9 @@ PyMethodDef KX_SceneActuator::Methods[] = {NULL,NULL} //Sentinel }; - +PyAttributeDef KX_SceneActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_SceneActuator::_getattr(const char *attr) { diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 562c096d440..6de1d67bfdb 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -285,7 +285,9 @@ PyMethodDef KX_SoundActuator::Methods[] = { {NULL,NULL,NULL,NULL} //Sentinel }; - +PyAttributeDef KX_SoundActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_SoundActuator::_getattr(const char *attr) { diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index cd5c5d29ab1..0de4da79bd8 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -146,6 +146,10 @@ KX_StateActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_StateActuator::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_StateActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 9d4fa14ad8e..8637bc92d39 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -468,6 +468,9 @@ PyMethodDef KX_TrackToActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_TrackToActuator::Attributes[] = { + { NULL } //Sentinel +}; PyObject* KX_TrackToActuator::_getattr(const char *attr) diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 057e10f195a..8d5af1b9216 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -382,3 +382,6 @@ PyMethodDef KX_VehicleWrapper::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_VehicleWrapper::Attributes[] = { + { NULL } //Sentinel +}; diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 1c427768b66..da0e3dbdd8d 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -78,6 +78,10 @@ PyMethodDef KX_VertexProxy::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_VertexProxy::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_VertexProxy::_getattr(const char *attr) { diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index ca89a63de62..0ec280080bd 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -126,6 +126,10 @@ KX_VisibilityActuator::Methods[] = { {NULL,NULL} //Sentinel }; +PyAttributeDef KX_VisibilityActuator::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_VisibilityActuator::_getattr(const char *attr) { _getattr_up(SCA_IActuator); From fd1adb58eb2fecdae1eeb8444108583f05248700 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Feb 2009 09:14:10 +0000 Subject: [PATCH 221/252] better remove t1_generate_luts.c rather then in scons. --- extern/libopenjpeg/SConscript | 3 - extern/libopenjpeg/t1_generate_luts.c | 275 -------------------------- 2 files changed, 278 deletions(-) delete mode 100644 extern/libopenjpeg/t1_generate_luts.c diff --git a/extern/libopenjpeg/SConscript b/extern/libopenjpeg/SConscript index d14b8329580..a27ac0d13df 100644 --- a/extern/libopenjpeg/SConscript +++ b/extern/libopenjpeg/SConscript @@ -6,9 +6,6 @@ Import('env') sources = env.Glob('*.c') -# This file contains a main() - can override blenders -sources.remove('t1_generate_luts.c') - incs = '.' flags = [] defs = [] diff --git a/extern/libopenjpeg/t1_generate_luts.c b/extern/libopenjpeg/t1_generate_luts.c deleted file mode 100644 index 1925b951f1b..00000000000 --- a/extern/libopenjpeg/t1_generate_luts.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2007, Callum Lerwick - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "opj_includes.h" -#include - -static int t1_init_ctxno_zc(int f, int orient) { - int h, v, d, n, t, hv; - n = 0; - h = ((f & T1_SIG_W) != 0) + ((f & T1_SIG_E) != 0); - v = ((f & T1_SIG_N) != 0) + ((f & T1_SIG_S) != 0); - d = ((f & T1_SIG_NW) != 0) + ((f & T1_SIG_NE) != 0) + ((f & T1_SIG_SE) != 0) + ((f & T1_SIG_SW) != 0); - - switch (orient) { - case 2: - t = h; - h = v; - v = t; - case 0: - case 1: - if (!h) { - if (!v) { - if (!d) - n = 0; - else if (d == 1) - n = 1; - else - n = 2; - } else if (v == 1) { - n = 3; - } else { - n = 4; - } - } else if (h == 1) { - if (!v) { - if (!d) - n = 5; - else - n = 6; - } else { - n = 7; - } - } else - n = 8; - break; - case 3: - hv = h + v; - if (!d) { - if (!hv) { - n = 0; - } else if (hv == 1) { - n = 1; - } else { - n = 2; - } - } else if (d == 1) { - if (!hv) { - n = 3; - } else if (hv == 1) { - n = 4; - } else { - n = 5; - } - } else if (d == 2) { - if (!hv) { - n = 6; - } else { - n = 7; - } - } else { - n = 8; - } - break; - } - - return (T1_CTXNO_ZC + n); -} - -static int t1_init_ctxno_sc(int f) { - int hc, vc, n; - n = 0; - - hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) == - T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), - 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) == - (T1_SIG_E | T1_SGN_E)) + - ((f & (T1_SIG_W | T1_SGN_W)) == - (T1_SIG_W | T1_SGN_W)), 1); - - vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) == - T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), - 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) == - (T1_SIG_N | T1_SGN_N)) + - ((f & (T1_SIG_S | T1_SGN_S)) == - (T1_SIG_S | T1_SGN_S)), 1); - - if (hc < 0) { - hc = -hc; - vc = -vc; - } - if (!hc) { - if (vc == -1) - n = 1; - else if (!vc) - n = 0; - else - n = 1; - } else if (hc == 1) { - if (vc == -1) - n = 2; - else if (!vc) - n = 3; - else - n = 4; - } - - return (T1_CTXNO_SC + n); -} - -static int t1_init_spb(int f) { - int hc, vc, n; - - hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) == - T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), - 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) == - (T1_SIG_E | T1_SGN_E)) + - ((f & (T1_SIG_W | T1_SGN_W)) == - (T1_SIG_W | T1_SGN_W)), 1); - - vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) == - T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), - 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) == - (T1_SIG_N | T1_SGN_N)) + - ((f & (T1_SIG_S | T1_SGN_S)) == - (T1_SIG_S | T1_SGN_S)), 1); - - if (!hc && !vc) - n = 0; - else - n = (!(hc > 0 || (!hc && vc > 0))); - - return n; -} - -void dump_array16(int array[],int size){ - int i; - --size; - for (i = 0; i < size; ++i) { - printf("0x%04x, ", array[i]); - if(!((i+1)&0x7)) - printf("\n "); - } - printf("0x%04x\n};\n\n", array[size]); -} - -int main(){ - int i, j; - double u, v, t; - - int lut_ctxno_zc[1024]; - int lut_nmsedec_sig[1 << T1_NMSEDEC_BITS]; - int lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS]; - int lut_nmsedec_ref[1 << T1_NMSEDEC_BITS]; - int lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS]; - - printf("/* This file was automatically generated by t1_generate_luts.c */\n\n"); - - // lut_ctxno_zc - for (j = 0; j < 4; ++j) { - for (i = 0; i < 256; ++i) { - int orient = j; - if (orient == 2) { - orient = 1; - } else if (orient == 1) { - orient = 2; - } - lut_ctxno_zc[(orient << 8) | i] = t1_init_ctxno_zc(i, j); - } - } - - printf("static char lut_ctxno_zc[1024] = {\n "); - for (i = 0; i < 1023; ++i) { - printf("%i, ", lut_ctxno_zc[i]); - if(!((i+1)&0x1f)) - printf("\n "); - } - printf("%i\n};\n\n", lut_ctxno_zc[1023]); - - // lut_ctxno_sc - printf("static char lut_ctxno_sc[256] = {\n "); - for (i = 0; i < 255; ++i) { - printf("0x%x, ", t1_init_ctxno_sc(i << 4)); - if(!((i+1)&0xf)) - printf("\n "); - } - printf("0x%x\n};\n\n", t1_init_ctxno_sc(255 << 4)); - - // lut_spb - printf("static char lut_spb[256] = {\n "); - for (i = 0; i < 255; ++i) { - printf("%i, ", t1_init_spb(i << 4)); - if(!((i+1)&0x1f)) - printf("\n "); - } - printf("%i\n};\n\n", t1_init_spb(255 << 4)); - - /* FIXME FIXME FIXME */ - /* fprintf(stdout,"nmsedec luts:\n"); */ - for (i = 0; i < (1 << T1_NMSEDEC_BITS); ++i) { - t = i / pow(2, T1_NMSEDEC_FRACBITS); - u = t; - v = t - 1.5; - lut_nmsedec_sig[i] = - int_max(0, - (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); - lut_nmsedec_sig0[i] = - int_max(0, - (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); - u = t - 1.0; - if (i & (1 << (T1_NMSEDEC_BITS - 1))) { - v = t - 1.5; - } else { - v = t - 0.5; - } - lut_nmsedec_ref[i] = - int_max(0, - (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); - lut_nmsedec_ref0[i] = - int_max(0, - (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); - } - - printf("static short lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {\n "); - dump_array16(&lut_nmsedec_sig, 1 << T1_NMSEDEC_BITS); - - printf("static short lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {\n "); - dump_array16(&lut_nmsedec_sig0, 1 << T1_NMSEDEC_BITS); - - printf("static short lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {\n "); - dump_array16(&lut_nmsedec_ref, 1 << T1_NMSEDEC_BITS); - - printf("static short lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = {\n "); - dump_array16(&lut_nmsedec_ref0, 1 << T1_NMSEDEC_BITS); - - return 0; -} From 4d9252640139401be5a67fc2d267176be95eaca8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Feb 2009 12:43:24 +0000 Subject: [PATCH 222/252] build blenderplayer without opennl and decimation --- intern/decimation/SConscript | 2 +- intern/opennl/SConscript | 4 ++-- source/blender/blenkernel/bad_level_call_stubs/stubs.c | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/intern/decimation/SConscript b/intern/decimation/SConscript index cf199fb3bc5..0df93032394 100644 --- a/intern/decimation/SConscript +++ b/intern/decimation/SConscript @@ -5,4 +5,4 @@ sources = env.Glob('intern/*.cpp') incs = '. ../moto/include ../container ../memutil' -env.BlenderLib ('bf_decimation', sources, Split(incs) , [], libtype=['core','common','player'], priority = [10, 20, 25] ) +env.BlenderLib ('bf_decimation', sources, Split(incs) , [], libtype=['core','common'], priority = [10, 20] ) diff --git a/intern/opennl/SConscript b/intern/opennl/SConscript index e46cefbff58..f68810d2f16 100644 --- a/intern/opennl/SConscript +++ b/intern/opennl/SConscript @@ -6,7 +6,7 @@ sources = env.Glob('intern/*.c') + env.Glob('superlu/*.c') incs = 'extern superlu' if (env['OURPLATFORM'] == 'win32-mingw'): - env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core','intern','player'], priority=[1,80,22] ) + env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core','intern'], priority=[1,80] ) else: - env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core','player'], priority=[55,22] ) + env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core'], priority=[55] ) diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 91fb9031597..fecead66bda 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -242,6 +242,12 @@ void bglEnd(void) {} /* booleanops.c */ struct DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select, int int_op_type) { return 0; } +/* LOD_decimation.cpp */ +int LOD_LoadMesh(struct LOD_Decimation_Info* info) { return 0;}; +int LOD_PreprocessMesh(struct LOD_Decimation_Info* info) {return 0;}; +int LOD_CollapseEdge(struct LOD_Decimation_Info* info) {return 0;}; +int LOD_FreeDecimationData(struct LOD_Decimation_Info* info) {return 0;}; + // bobj read/write debug messages void elbeemDebugOut(char *msg) {} void fluidsimSettingsFree(struct FluidsimSettings* sb) {} From c9653cc083a85964cd85e47b180d32a0a2e00ef1 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Fri, 27 Feb 2009 00:08:16 +0000 Subject: [PATCH 223/252] [18327] Fix crash when activating nodes - faulty linking and header file lead to crashing whenever nodes were used. --- source/blender/nodes/CMP_node.h | 116 ++++++++++++++++---------------- source/blender/nodes/SConscript | 6 +- source/blender/nodes/SHD_node.h | 46 ++++++------- source/blender/nodes/TEX_node.h | 64 +++++++++--------- 4 files changed, 116 insertions(+), 116 deletions(-) diff --git a/source/blender/nodes/CMP_node.h b/source/blender/nodes/CMP_node.h index 84d311b6173..020bbdebfa2 100644 --- a/source/blender/nodes/CMP_node.h +++ b/source/blender/nodes/CMP_node.h @@ -38,71 +38,71 @@ /* ****************** types array for all composite nodes ****************** */ -bNodeType cmp_node_rlayers; -bNodeType cmp_node_image; -bNodeType cmp_node_texture; -bNodeType cmp_node_value; -bNodeType cmp_node_rgb; -bNodeType cmp_node_curve_time; +extern bNodeType cmp_node_rlayers; +extern bNodeType cmp_node_image; +extern bNodeType cmp_node_texture; +extern bNodeType cmp_node_value; +extern bNodeType cmp_node_rgb; +extern bNodeType cmp_node_curve_time; -bNodeType cmp_node_composite; -bNodeType cmp_node_viewer; -bNodeType cmp_node_splitviewer; -bNodeType cmp_node_output_file; +extern bNodeType cmp_node_composite; +extern bNodeType cmp_node_viewer; +extern bNodeType cmp_node_splitviewer; +extern bNodeType cmp_node_output_file; -bNodeType cmp_node_curve_rgb; -bNodeType cmp_node_mix_rgb; -bNodeType cmp_node_hue_sat; -bNodeType cmp_node_brightcontrast; -bNodeType cmp_node_gamma; -bNodeType cmp_node_invert; -bNodeType cmp_node_alphaover; -bNodeType cmp_node_zcombine; +extern bNodeType cmp_node_curve_rgb; +extern bNodeType cmp_node_mix_rgb; +extern bNodeType cmp_node_hue_sat; +extern bNodeType cmp_node_brightcontrast; +extern bNodeType cmp_node_gamma; +extern bNodeType cmp_node_invert; +extern bNodeType cmp_node_alphaover; +extern bNodeType cmp_node_zcombine; -bNodeType cmp_node_normal; -bNodeType cmp_node_curve_vec; -bNodeType cmp_node_map_value; -bNodeType cmp_node_normalize; +extern bNodeType cmp_node_normal; +extern bNodeType cmp_node_curve_vec; +extern bNodeType cmp_node_map_value; +extern bNodeType cmp_node_normalize; -bNodeType cmp_node_filter; -bNodeType cmp_node_blur; -bNodeType cmp_node_dblur; -bNodeType cmp_node_bilateralblur; -bNodeType cmp_node_vecblur; -bNodeType cmp_node_dilateerode; -bNodeType cmp_node_defocus; +extern bNodeType cmp_node_filter; +extern bNodeType cmp_node_blur; +extern bNodeType cmp_node_dblur; +extern bNodeType cmp_node_bilateralblur; +extern bNodeType cmp_node_vecblur; +extern bNodeType cmp_node_dilateerode; +extern bNodeType cmp_node_defocus; -bNodeType cmp_node_valtorgb; -bNodeType cmp_node_rgbtobw; -bNodeType cmp_node_setalpha; -bNodeType cmp_node_idmask; -bNodeType cmp_node_math; -bNodeType cmp_node_seprgba; -bNodeType cmp_node_combrgba; -bNodeType cmp_node_sephsva; -bNodeType cmp_node_combhsva; -bNodeType cmp_node_sepyuva; -bNodeType cmp_node_combyuva; -bNodeType cmp_node_sepycca; -bNodeType cmp_node_combycca; -bNodeType cmp_node_premulkey; +extern bNodeType cmp_node_valtorgb; +extern bNodeType cmp_node_rgbtobw; +extern bNodeType cmp_node_setalpha; +extern bNodeType cmp_node_idmask; +extern bNodeType cmp_node_math; +extern bNodeType cmp_node_seprgba; +extern bNodeType cmp_node_combrgba; +extern bNodeType cmp_node_sephsva; +extern bNodeType cmp_node_combhsva; +extern bNodeType cmp_node_sepyuva; +extern bNodeType cmp_node_combyuva; +extern bNodeType cmp_node_sepycca; +extern bNodeType cmp_node_combycca; +extern bNodeType cmp_node_premulkey; -bNodeType cmp_node_diff_matte; -bNodeType cmp_node_chroma; -bNodeType cmp_node_channel_matte; -bNodeType cmp_node_color_spill; -bNodeType cmp_node_luma_matte; +extern bNodeType cmp_node_diff_matte; +extern bNodeType cmp_node_chroma; +extern bNodeType cmp_node_channel_matte; +extern bNodeType cmp_node_color_spill; +extern bNodeType cmp_node_luma_matte; -bNodeType cmp_node_translate; -bNodeType cmp_node_rotate; -bNodeType cmp_node_scale; -bNodeType cmp_node_flip; -bNodeType cmp_node_crop; -bNodeType cmp_node_displace; -bNodeType cmp_node_mapuv; +extern bNodeType cmp_node_translate; +extern bNodeType cmp_node_rotate; +extern bNodeType cmp_node_scale; +extern bNodeType cmp_node_flip; +extern bNodeType cmp_node_crop; +extern bNodeType cmp_node_displace; +extern bNodeType cmp_node_mapuv; -bNodeType cmp_node_glare; -bNodeType cmp_node_tonemap; -bNodeType cmp_node_lensdist; +extern bNodeType cmp_node_glare; +extern bNodeType cmp_node_tonemap; +extern bNodeType cmp_node_lensdist; #endif diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index b47eebd0811..42dbbe4880e 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -40,6 +40,6 @@ if env['WITH_BF_QUICKTIME']: incs += ' ' + env['BF_QUICKTIME_INC'] env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 200, 300] ) -env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) -env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) -env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core'], priority = [200, 175] ) +env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] ) +env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] ) +env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] ) diff --git a/source/blender/nodes/SHD_node.h b/source/blender/nodes/SHD_node.h index 10af3f162d6..d75d7c9f568 100644 --- a/source/blender/nodes/SHD_node.h +++ b/source/blender/nodes/SHD_node.h @@ -39,29 +39,29 @@ /* the type definitions array */ /* ****************** types array for all shaders ****************** */ -bNodeType sh_node_output; -bNodeType sh_node_material; -bNodeType sh_node_camera; -bNodeType sh_node_value; -bNodeType sh_node_rgb; -bNodeType sh_node_mix_rgb; -bNodeType sh_node_valtorgb; -bNodeType sh_node_rgbtobw; -bNodeType sh_node_texture; -bNodeType sh_node_normal; -bNodeType sh_node_geom; -bNodeType sh_node_mapping; -bNodeType sh_node_curve_vec; -bNodeType sh_node_curve_rgb; -bNodeType sh_node_math; -bNodeType sh_node_vect_math; -bNodeType sh_node_squeeze; -bNodeType node_dynamic_typeinfo; -bNodeType sh_node_material_ext; -bNodeType sh_node_invert; -bNodeType sh_node_seprgb; -bNodeType sh_node_combrgb; -bNodeType sh_node_hue_sat; +extern bNodeType sh_node_output; +extern bNodeType sh_node_material; +extern bNodeType sh_node_camera; +extern bNodeType sh_node_value; +extern bNodeType sh_node_rgb; +extern bNodeType sh_node_mix_rgb; +extern bNodeType sh_node_valtorgb; +extern bNodeType sh_node_rgbtobw; +extern bNodeType sh_node_texture; +extern bNodeType sh_node_normal; +extern bNodeType sh_node_geom; +extern bNodeType sh_node_mapping; +extern bNodeType sh_node_curve_vec; +extern bNodeType sh_node_curve_rgb; +extern bNodeType sh_node_math; +extern bNodeType sh_node_vect_math; +extern bNodeType sh_node_squeeze; +extern bNodeType node_dynamic_typeinfo; +extern bNodeType sh_node_material_ext; +extern bNodeType sh_node_invert; +extern bNodeType sh_node_seprgb; +extern bNodeType sh_node_combrgb; +extern bNodeType sh_node_hue_sat; #endif diff --git a/source/blender/nodes/TEX_node.h b/source/blender/nodes/TEX_node.h index 90e171e9cca..c52fc757507 100644 --- a/source/blender/nodes/TEX_node.h +++ b/source/blender/nodes/TEX_node.h @@ -38,40 +38,40 @@ /* ****************** types array for all texture nodes ****************** */ -bNodeType tex_node_math; -bNodeType tex_node_mix_rgb; -bNodeType tex_node_valtorgb; -bNodeType tex_node_valtonor; -bNodeType tex_node_rgbtobw; -bNodeType tex_node_output; -bNodeType tex_node_viewer; -bNodeType tex_node_checker; -bNodeType tex_node_texture; -bNodeType tex_node_bricks; -bNodeType tex_node_image; -bNodeType tex_node_curve_rgb; -bNodeType tex_node_curve_time; -bNodeType tex_node_invert; -bNodeType tex_node_hue_sat; -bNodeType tex_node_coord; -bNodeType tex_node_distance; +extern bNodeType tex_node_math; +extern bNodeType tex_node_mix_rgb; +extern bNodeType tex_node_valtorgb; +extern bNodeType tex_node_valtonor; +extern bNodeType tex_node_rgbtobw; +extern bNodeType tex_node_output; +extern bNodeType tex_node_viewer; +extern bNodeType tex_node_checker; +extern bNodeType tex_node_texture; +extern bNodeType tex_node_bricks; +extern bNodeType tex_node_image; +extern bNodeType tex_node_curve_rgb; +extern bNodeType tex_node_curve_time; +extern bNodeType tex_node_invert; +extern bNodeType tex_node_hue_sat; +extern bNodeType tex_node_coord; +extern bNodeType tex_node_distance; -bNodeType tex_node_rotate; -bNodeType tex_node_translate; -bNodeType tex_node_scale; +extern bNodeType tex_node_rotate; +extern bNodeType tex_node_translate; +extern bNodeType tex_node_scale; -bNodeType tex_node_compose; -bNodeType tex_node_decompose; +extern bNodeType tex_node_compose; +extern bNodeType tex_node_decompose; -bNodeType tex_node_proc_voronoi; -bNodeType tex_node_proc_blend; -bNodeType tex_node_proc_magic; -bNodeType tex_node_proc_marble; -bNodeType tex_node_proc_clouds; -bNodeType tex_node_proc_wood; -bNodeType tex_node_proc_musgrave; -bNodeType tex_node_proc_noise; -bNodeType tex_node_proc_stucci; -bNodeType tex_node_proc_distnoise; +extern bNodeType tex_node_proc_voronoi; +extern bNodeType tex_node_proc_blend; +extern bNodeType tex_node_proc_magic; +extern bNodeType tex_node_proc_marble; +extern bNodeType tex_node_proc_clouds; +extern bNodeType tex_node_proc_wood; +extern bNodeType tex_node_proc_musgrave; +extern bNodeType tex_node_proc_noise; +extern bNodeType tex_node_proc_stucci; +extern bNodeType tex_node_proc_distnoise; #endif From e872843c85434efad2c1a082c4ecad2008ab1ef5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 27 Feb 2009 18:49:25 +0000 Subject: [PATCH 224/252] blender.desktop file from Rudolf Kastl --- release/freedesktop/blender.desktop | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 release/freedesktop/blender.desktop diff --git a/release/freedesktop/blender.desktop b/release/freedesktop/blender.desktop new file mode 100644 index 00000000000..3d14cc4aca0 --- /dev/null +++ b/release/freedesktop/blender.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Blender +Comment=3D modeling, animation, rendering and post-production +Exec=blender -w +Icon=blender.png +Terminal=false +Type=Application +Categories=Graphics;3DGraphics; +MimeType=application/x-blender; From 8d3dcfb104bcfc4fa9fdfecaa8e5c8fd9a900e98 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 27 Feb 2009 23:53:09 +0000 Subject: [PATCH 225/252] BGE Python API * Scene's and GameObjects can now be printed (raised an exception) * Added GameLogic.getSceneList() --- source/gameengine/Ketsji/KX_GameObject.h | 3 ++- source/gameengine/Ketsji/KX_PythonInit.cpp | 28 ++++++++++++++++++++++ source/gameengine/Ketsji/KX_Scene.h | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index d95e3751d33..211c9b7ca7d 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -758,7 +758,8 @@ public: virtual PyObject* _getattr(const char *attr); virtual int _setattr(const char *attr, PyObject *value); // _setattr method - + virtual PyObject* _repr(void) { return PyString_FromString(GetName().ReadPtr()); } + KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); KX_PYMETHOD_O(KX_GameObject,SetWorldPosition); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index b3e8d15189f..93f57986181 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -329,6 +329,32 @@ static PyObject* gPyGetCurrentScene(PyObject* self) return (PyObject*) gp_KetsjiScene; } +static STR_String gPyGetSceneList_doc = +"getSceneList()\n" +"Return a list of converted scenes.\n"; +static PyObject* gPyGetSceneList(PyObject* self) +{ + KX_KetsjiEngine* m_engine = KX_GetActiveEngine(); + //CListValue* list = new CListValue(); + PyObject* list; + KX_SceneList* scenes = m_engine->CurrentScenes(); + int numScenes = scenes->size(); + int i; + + list = PyList_New(numScenes); + + for (i=0;iat(i); + //list->Add(scene); + PyList_SET_ITEM(list, i, scene); + Py_INCREF(scene); + + } + + return (PyObject*)list; +} + static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) { #define pprint(x) std::cout << x << std::endl; @@ -408,6 +434,8 @@ static struct PyMethodDef game_methods[] = { METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::sPyGetCurrentController__doc__}, {"getCurrentScene", (PyCFunction) gPyGetCurrentScene, METH_NOARGS, (PY_METHODCHAR)gPyGetCurrentScene_doc.Ptr()}, + {"getSceneList", (PyCFunction) gPyGetSceneList, + METH_NOARGS, (PY_METHODCHAR)gPyGetSceneList_doc.Ptr()}, {"addActiveActuator",(PyCFunction) SCA_PythonController::sPyAddActiveActuator, METH_VARARGS, (PY_METHODCHAR)SCA_PythonController::sPyAddActiveActuator__doc__}, {"getRandomFloat",(PyCFunction) gPyGetRandomFloat, diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index e4d4b6fe2cd..e49a87b0402 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -567,7 +567,9 @@ public: virtual PyObject* _getattr(const char *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ virtual int _setattr(const char *attr, PyObject *pyvalue); virtual int _delattr(const char *attr); + virtual PyObject* _repr(void) { return PyString_FromString(GetName().ReadPtr()); } + /** * Sets the time the scene was suspended */ From 541d49bc2c2ad9f26314df0fa4a6c96cfdf2852e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 28 Feb 2009 09:25:42 +0000 Subject: [PATCH 226/252] * blender doesn't need the -w anymore to start in a window * NULL can be used instead of () args for calling python functions from C. --- release/freedesktop/blender.desktop | 2 +- source/blender/python/api2_2x/Draw.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/release/freedesktop/blender.desktop b/release/freedesktop/blender.desktop index 3d14cc4aca0..39e0e3afe8e 100644 --- a/release/freedesktop/blender.desktop +++ b/release/freedesktop/blender.desktop @@ -2,7 +2,7 @@ Encoding=UTF-8 Name=Blender Comment=3D modeling, animation, rendering and post-production -Exec=blender -w +Exec=blender Icon=blender.png Terminal=false Type=Application diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index c238fe5601c..2af2261808b 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -659,7 +659,7 @@ static void exec_callback( SpaceScript * sc, PyObject * callback, } Py_XDECREF( result ); - Py_DECREF( args ); + Py_XDECREF( args ); } /* BPY_spacescript_do_pywin_draw, the static spacescript_do_pywin_buttons and @@ -688,7 +688,7 @@ void BPY_spacescript_do_pywin_draw( SpaceScript * sc ) BPy_Set_DrawButtonsList(sc->but_refs); glPushAttrib( GL_ALL_ATTRIB_BITS ); - exec_callback( sc, script->py_draw, Py_BuildValue( "()" ) ); + exec_callback( sc, script->py_draw, NULL ); glPopAttrib( ); } else { glClearColor( 0.4375, 0.4375, 0.4375, 0.0 ); From 6c409ed541d84b662d16ee34e9128cc64d27d0d8 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 28 Feb 2009 21:00:27 +0000 Subject: [PATCH 227/252] BGE API cleanup: apply patch from Moguri: Near, Radar, Touch sensor updated. --- source/gameengine/Ketsji/KX_NearSensor.cpp | 41 +++++-- source/gameengine/Ketsji/KX_NearSensor.h | 27 ++++- source/gameengine/Ketsji/KX_PythonInit.cpp | 9 ++ source/gameengine/Ketsji/KX_RadarSensor.cpp | 123 ++++++++++++++------ source/gameengine/Ketsji/KX_RadarSensor.h | 24 ++-- source/gameengine/Ketsji/KX_TouchSensor.cpp | 9 +- source/gameengine/Ketsji/KX_TouchSensor.h | 2 + source/gameengine/PyDoc/GameLogic.py | 8 ++ source/gameengine/PyDoc/KX_NearSensor.py | 5 + source/gameengine/PyDoc/KX_RadarSensor.py | 18 +++ source/gameengine/PyDoc/KX_Scene.py | 13 +++ source/gameengine/PyDoc/KX_TouchSensor.py | 19 +-- 12 files changed, 229 insertions(+), 69 deletions(-) diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 066387abb93..993a6b3d86c 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -42,8 +42,8 @@ #endif KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr, KX_GameObject* gameobj, - double margin, - double resetmargin, + float margin, + float resetmargin, bool bFindMaterial, const STR_String& touchedpropname, class KX_Scene* scene, @@ -276,8 +276,16 @@ bool KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData } +/* ------------------------------------------------------------------------- */ +/* Python Functions */ +/* ------------------------------------------------------------------------- */ + +//No methods + +/* ------------------------------------------------------------------------- */ +/* Python Integration Hooks */ +/* ------------------------------------------------------------------------- */ -// python embedding PyTypeObject KX_NearSensor::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -311,20 +319,31 @@ PyParentObject KX_NearSensor::Parents[] = { PyMethodDef KX_NearSensor::Methods[] = { - {"setProperty", (PyCFunction) KX_NearSensor::sPySetProperty, METH_O, (PY_METHODCHAR)SetProperty_doc}, - {"getProperty", (PyCFunction) KX_NearSensor::sPyGetProperty, METH_NOARGS, (PY_METHODCHAR)GetProperty_doc}, - {"getHitObject",(PyCFunction) KX_NearSensor::sPyGetHitObject, METH_NOARGS, (PY_METHODCHAR)GetHitObject_doc}, - {"getHitObjectList", (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_NOARGS, (PY_METHODCHAR)GetHitObjectList_doc}, + //No methods {NULL,NULL} //Sentinel }; PyAttributeDef KX_NearSensor::Attributes[] = { - { NULL } //Sentinel + KX_PYATTRIBUTE_FLOAT_RW_CHECK("distance", 0, 100, KX_NearSensor, m_Margin, CheckResetDistance), + KX_PYATTRIBUTE_FLOAT_RW_CHECK("resetDistance", 0, 100, KX_NearSensor, m_ResetMargin, CheckResetDistance), + {NULL} //Sentinel }; -PyObject* -KX_NearSensor::_getattr(const char *attr) + +PyObject* KX_NearSensor::_getattr(const char *attr) { - _getattr_up(KX_TouchSensor); + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + + _getattr_up(KX_TouchSensor); } +int KX_NearSensor::_setattr(const char *attr, PyObject* value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + + return KX_TouchSensor::_setattr(attr, value); +} diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index 58c7cc7da91..ee03992e734 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -42,15 +42,15 @@ class KX_NearSensor : public KX_TouchSensor { Py_Header; protected: - double m_Margin; - double m_ResetMargin; + float m_Margin; + float m_ResetMargin; KX_Scene* m_scene; KX_ClientObjectInfo* m_client_info; public: KX_NearSensor(class SCA_EventManager* eventmgr, class KX_GameObject* gameobj, - double margin, - double resetmargin, + float margin, + float resetmargin, bool bFindMaterial, const STR_String& touchedpropname, class KX_Scene* scene, @@ -78,8 +78,25 @@ public: virtual bool BroadPhaseFilterCollision(void*obj1,void*obj2); virtual void RegisterSumo(KX_TouchEventManager *touchman); virtual void UnregisterSumo(KX_TouchEventManager* touchman); - + + /* --------------------------------------------------------------------- */ + /* Python interface ---------------------------------------------------- */ + /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); + + //No methods + + //This method is used to make sure the distance does not exceed the reset distance + static int CheckResetDistance(void *self, const PyAttributeDef*) + { + KX_NearSensor* sensor = reinterpret_cast(self); + + if (sensor->m_Margin > sensor->m_ResetMargin) + sensor->m_ResetMargin = sensor->m_Margin; + + return 0; + } }; diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 93f57986181..d974d67bf33 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -47,6 +47,7 @@ #include "KX_PyConstraintBinding.h" #include "KX_KetsjiEngine.h" +#include "KX_RadarSensor.h" #include "SCA_IInputDevice.h" #include "SCA_PropertySensor.h" @@ -1060,6 +1061,14 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_STATE29, (1<<28)); KX_MACRO_addTypesToDict(d, KX_STATE30, (1<<29)); + /* Radar Sensor */ + KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_POS_X, KX_RadarSensor::KX_RADAR_AXIS_POS_X); + KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_POS_Y, KX_RadarSensor::KX_RADAR_AXIS_POS_Y); + KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_POS_Z, KX_RadarSensor::KX_RADAR_AXIS_POS_Z); + KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_X, KX_RadarSensor::KX_RADAR_AXIS_NEG_Y); + KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_Y, KX_RadarSensor::KX_RADAR_AXIS_NEG_X); + KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_Z, KX_RadarSensor::KX_RADAR_AXIS_NEG_Z); + // Check for errors if (PyErr_Occurred()) { diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index c347faaee1a..fa8998cd81d 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -171,8 +171,18 @@ void KX_RadarSensor::SynchronizeTransform() { } } - m_cone_origin = trans.getOrigin(); - m_cone_target = trans(MT_Point3(0, -m_coneheight/2.0 ,0)); + + //Using a temp variable to translate MT_Point3 to float[3]. + //float[3] works better for the Python interface. + MT_Point3 temp = trans.getOrigin(); + m_cone_origin[0] = temp[0]; + m_cone_origin[1] = temp[1]; + m_cone_origin[2] = temp[2]; + + temp = trans(MT_Point3(0, -m_coneheight/2.0 ,0)); + m_cone_target[0] = temp[0]; + m_cone_target[1] = temp[1]; + m_cone_target[2] = temp[2]; if (m_physCtrl) @@ -187,10 +197,58 @@ void KX_RadarSensor::SynchronizeTransform() } /* ------------------------------------------------------------------------- */ -/* Python functions */ +/* Python Functions */ /* ------------------------------------------------------------------------- */ -/* Integration hooks ------------------------------------------------------- */ +//Deprecated -----> +/* getConeOrigin */ +const char KX_RadarSensor::GetConeOrigin_doc[] = +"getConeOrigin()\n" +"\tReturns the origin of the cone with which to test. The origin\n" +"\tis in the middle of the cone."; +PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self) { + ShowDeprecationWarning("getConeOrigin()", "the coneOrigin property"); + + PyObject *retVal = PyList_New(3); + + PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_origin[0])); + PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_origin[1])); + PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_origin[2])); + + return retVal; +} + +/* getConeOrigin */ +const char KX_RadarSensor::GetConeTarget_doc[] = +"getConeTarget()\n" +"\tReturns the center of the bottom face of the cone with which to test.\n"; +PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self) { + ShowDeprecationWarning("getConeTarget()", "the coneTarget property"); + + PyObject *retVal = PyList_New(3); + + PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_target[0])); + PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_target[1])); + PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_target[2])); + + return retVal; +} + +/* getConeHeight */ +const char KX_RadarSensor::GetConeHeight_doc[] = +"getConeHeight()\n" +"\tReturns the height of the cone with which to test.\n"; +PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self) { + + ShowDeprecationWarning("getConeHeight()", "the distance property"); + + return PyFloat_FromDouble(m_coneheight); +} +//<----- Deprecated + +/* ------------------------------------------------------------------------- */ +/* Python Integration Hooks */ +/* ------------------------------------------------------------------------- */ PyTypeObject KX_RadarSensor::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -221,46 +279,39 @@ PyParentObject KX_RadarSensor::Parents[] = { }; PyMethodDef KX_RadarSensor::Methods[] = { + //Deprecated -----> {"getConeOrigin", (PyCFunction) KX_RadarSensor::sPyGetConeOrigin, - METH_NOARGS, (PY_METHODCHAR)GetConeOrigin_doc}, + METH_VARARGS, (PY_METHODCHAR)GetConeOrigin_doc}, {"getConeTarget", (PyCFunction) KX_RadarSensor::sPyGetConeTarget, - METH_NOARGS, (PY_METHODCHAR)GetConeTarget_doc}, + METH_VARARGS, (PY_METHODCHAR)GetConeTarget_doc}, {"getConeHeight", (PyCFunction) KX_RadarSensor::sPyGetConeHeight, - METH_NOARGS, (PY_METHODCHAR)GetConeHeight_doc}, - {NULL,NULL,NULL,NULL} //Sentinel + METH_VARARGS, (PY_METHODCHAR)GetConeHeight_doc}, + //<----- + {NULL} //Sentinel }; PyAttributeDef KX_RadarSensor::Attributes[] = { - { NULL } //Sentinel + KX_PYATTRIBUTE_FLOAT_ARRAY_RO("coneOrigin", KX_RadarSensor, m_cone_origin, 3), + KX_PYATTRIBUTE_FLOAT_ARRAY_RO("coneTarget", KX_RadarSensor, m_cone_target, 3), + KX_PYATTRIBUTE_FLOAT_RW("angle", 0, 360, KX_RadarSensor, m_coneradius), + KX_PYATTRIBUTE_INT_RW("axis", 0, 5, true, KX_RadarSensor, m_axis), + {NULL} //Sentinel }; -PyObject* KX_RadarSensor::_getattr(const char *attr) { - _getattr_up(KX_TouchSensor); +PyObject* KX_RadarSensor::_getattr(const char *attr) +{ + PyObject* object = _getattr_self(Attributes, this, attr); + if (object != NULL) + return object; + + _getattr_up(KX_NearSensor); } -/* getConeOrigin */ -const char KX_RadarSensor::GetConeOrigin_doc[] = -"getConeOrigin()\n" -"\tReturns the origin of the cone with which to test. The origin\n" -"\tis in the middle of the cone."; -PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self) { - return PyObjectFrom(m_cone_origin); +int KX_RadarSensor::_setattr(const char *attr, PyObject* value) +{ + int ret = _setattr_self(Attributes, this, attr, value); + if (ret >= 0) + return ret; + + return KX_NearSensor::_setattr(attr, value); } - -/* getConeOrigin */ -const char KX_RadarSensor::GetConeTarget_doc[] = -"getConeTarget()\n" -"\tReturns the center of the bottom face of the cone with which to test.\n"; -PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self) { - return PyObjectFrom(m_cone_target); -} - -/* getConeOrigin */ -const char KX_RadarSensor::GetConeHeight_doc[] = -"getConeHeight()\n" -"\tReturns the height of the cone with which to test.\n"; -PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self) { - return PyFloat_FromDouble(m_coneheight); -} - - diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index e4c6d73f22d..6dfe0c42f5d 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -40,23 +40,23 @@ class KX_RadarSensor : public KX_NearSensor protected: Py_Header; - MT_Scalar m_coneradius; + float m_coneradius; /** * Height of the cone. */ - MT_Scalar m_coneheight; + float m_coneheight; int m_axis; /** * The previous position of the origin of the cone. */ - MT_Point3 m_cone_origin; + float m_cone_origin[3]; /** * The previous direction of the cone (origin to bottom plane). */ - MT_Point3 m_cone_target; + float m_cone_target[3]; public: @@ -80,13 +80,23 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* _getattr(const char *attr); + enum RadarAxis { + KX_RADAR_AXIS_POS_X = 0, + KX_RADAR_AXIS_POS_Y, + KX_RADAR_AXIS_POS_Z, + KX_RADAR_AXIS_NEG_X, + KX_RADAR_AXIS_NEG_Y, + KX_RADAR_AXIS_NEG_Z + }; + virtual PyObject* _getattr(const char *attr); + virtual int _setattr(const char *attr, PyObject* value); + + //Deprecated -----> KX_PYMETHOD_DOC_NOARGS(KX_RadarSensor,GetConeOrigin); KX_PYMETHOD_DOC_NOARGS(KX_RadarSensor,GetConeTarget); KX_PYMETHOD_DOC_NOARGS(KX_RadarSensor,GetConeHeight); - + //<----- }; #endif //__KX_RADAR_SENSOR_H diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 32fcc148395..705b54edd37 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -269,6 +269,7 @@ PyParentObject KX_TouchSensor::Parents[] = { }; PyMethodDef KX_TouchSensor::Methods[] = { + //Deprecated -----> {"setProperty", (PyCFunction) KX_TouchSensor::sPySetProperty, METH_O, (PY_METHODCHAR)SetProperty_doc}, {"getProperty", @@ -277,12 +278,13 @@ PyMethodDef KX_TouchSensor::Methods[] = { (PyCFunction) KX_TouchSensor::sPyGetHitObject, METH_NOARGS, (PY_METHODCHAR)GetHitObject_doc}, {"getHitObjectList", (PyCFunction) KX_TouchSensor::sPyGetHitObjectList, METH_NOARGS, (PY_METHODCHAR)GetHitObjectList_doc}, + //<----- {NULL,NULL} //Sentinel }; PyAttributeDef KX_TouchSensor::Attributes[] = { - KX_PYATTRIBUTE_STRING_RW("propertyName",0,100,false,KX_TouchSensor,m_touchedpropname), - KX_PYATTRIBUTE_BOOL_RW("materialCheck",KX_TouchSensor,m_bFindMaterial), + KX_PYATTRIBUTE_STRING_RW("property",0,100,false,KX_TouchSensor,m_touchedpropname), + KX_PYATTRIBUTE_BOOL_RW("useMaterial",KX_TouchSensor,m_bFindMaterial), KX_PYATTRIBUTE_BOOL_RW("pulseCollisions",KX_TouchSensor,m_bTouchPulse), KX_PYATTRIBUTE_DUMMY("objectHit"), KX_PYATTRIBUTE_DUMMY("objectHitList"), @@ -372,6 +374,9 @@ PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self) return m_colliders->AddRef(); } +/*getTouchMaterial and setTouchMaterial were never added to the api, +they can probably be removed with out anyone noticing*/ + /* 5. getTouchMaterial */ const char KX_TouchSensor::GetTouchMaterial_doc[] = "getTouchMaterial()\n" diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index c523736967b..18ce9406a9b 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -123,6 +123,7 @@ public: virtual PyObject* _getattr(const char *attr); virtual int _setattr(const char *attr, PyObject *value); + //Deprecated -----> /* 1. setProperty */ KX_PYMETHOD_DOC_O(KX_TouchSensor,SetProperty); /* 2. getProperty */ @@ -137,6 +138,7 @@ public: /* 6. setTouchMaterial */ KX_PYMETHOD_DOC_O(KX_TouchSensor,SetTouchMaterial); #endif + //<----- }; diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index f743acf06fe..0524a9df355 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -140,6 +140,14 @@ Documentation for the GameLogic Module. @var KX_SOUNDACT_LOOPEND: See L{KX_SoundActuator} @var KX_SOUNDACT_LOOPBIDIRECTIONAL: See L{KX_SoundActuator} @var KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: See L{KX_SoundActuator} + +@group Radar Sensor: KX_RADAR_AXIS_POS_X, KX_RADAR_AXIS_POS_Y, KX_RADAR_AXIS_POS_Z, KX_RADAR_AXIS_NEG_X, KX_RADAR_AXIS_NEG_Y, KX_RADAR_AXIS_NEG_Z +@var KX_RADAR_AXIS_POS_X: See L{KX_RadarSensor} +@var KX_RADAR_AXIS_POS_Y: See L{KX_RadarSensor} +@var KX_RADAR_AXIS_POS_Z: See L{KX_RadarSensor} +@var KX_RADAR_AXIS_NEG_X: See L{KX_RadarSensor} +@var KX_RADAR_AXIS_NEG_Y: See L{KX_RadarSensor} +@var KX_RADAR_AXIS_NEG_Z: See L{KX_RadarSensor} """ diff --git a/source/gameengine/PyDoc/KX_NearSensor.py b/source/gameengine/PyDoc/KX_NearSensor.py index fef2e4b2acc..a8c408827fe 100644 --- a/source/gameengine/PyDoc/KX_NearSensor.py +++ b/source/gameengine/PyDoc/KX_NearSensor.py @@ -5,5 +5,10 @@ from KX_TouchSensor import * class KX_NearSensor(KX_TouchSensor): """ A near sensor is a specialised form of touch sensor. + + @ivar distance: The near sensor activates when an object is within this distance. + @type distance: float + @ivar resetDistance: The near sensor deactivates when the object exceeds this distance. + @type resetDistance: float """ diff --git a/source/gameengine/PyDoc/KX_RadarSensor.py b/source/gameengine/PyDoc/KX_RadarSensor.py index 64be858371a..b68bf4ea0f3 100644 --- a/source/gameengine/PyDoc/KX_RadarSensor.py +++ b/source/gameengine/PyDoc/KX_RadarSensor.py @@ -5,8 +5,26 @@ from KX_NearSensor import * class KX_RadarSensor(KX_NearSensor): """ Radar sensor is a near sensor with a conical sensor object. + + @ivar coneOrigin: The origin of the cone with which to test. The origin + is in the middle of the cone. + (Read only) + @type coneOrigin: list of floats [x, y, z] + @ivar coneTarget: The center of the bottom face of the cone with which to test. + (Read only) + @type coneTarget: list of floats [x, y, z] + @ivar distance: The height of the cone with which to test. + @type distance: float + @ivar angle: The angle of the cone (in degrees) with which to test. + @type angle: float from 0 to 360 + @ivar axis: The axis on which the radar cone is cast + @type axis: int from 0 to 5 + KX_RADAR_AXIS_POS_X, KX_RADAR_AXIS_POS_Y, KX_RADAR_AXIS_POS_Z, + KX_RADAR_AXIS_NEG_X, KX_RADAR_AXIS_NEG_Y, KX_RADAR_AXIS_NEG_Z """ + + #--The following methods are deprecated, please use properties instead. def getConeOrigin(): """ Returns the origin of the cone with which to test. The origin diff --git a/source/gameengine/PyDoc/KX_Scene.py b/source/gameengine/PyDoc/KX_Scene.py index 24b81bbf55e..5e357e6eefc 100644 --- a/source/gameengine/PyDoc/KX_Scene.py +++ b/source/gameengine/PyDoc/KX_Scene.py @@ -70,3 +70,16 @@ class KX_Scene: @rtype: string """ + def addObject(object, other, time=0) + """ + Adds an object to the scene like the Add Object Actuator would, and returns the created object. + + @param object: The object to add + @type object: L{KX_GameObject} or string + @param other: The object's center to use when adding the object + @type other: L{KX_GameObject} or string + @param time: The lifetime of the added object, in frames. A time of 0 means the object will last forever. + @type time: int + + @rtype: L{KX_GameObject} + """ diff --git a/source/gameengine/PyDoc/KX_TouchSensor.py b/source/gameengine/PyDoc/KX_TouchSensor.py index 4f020930c4c..d7277be4c2a 100644 --- a/source/gameengine/PyDoc/KX_TouchSensor.py +++ b/source/gameengine/PyDoc/KX_TouchSensor.py @@ -7,10 +7,11 @@ class KX_TouchSensor(SCA_ISensor): """ Touch sensor detects collisions between objects. - @ivar propertyName: The name of the property or material this sensor detects (depending on the materialCheck property). - @type propertyName: string - @ivar materialCheck: when enabled this sensor checks for object materials rather then properties. - @type materialCheck: bool + @ivar property: The property or material to collide with. + @type property: string + @ivar useMaterial: Determines if the sensor is looking for a property or material. + KX_True = Find material; KX_False = Find property + @type useMaterial: boolean @ivar pulseCollisions: The last collided object. @type pulseCollisions: bool @ivar objectHit: The last collided object. (Read Only) @@ -18,24 +19,26 @@ class KX_TouchSensor(SCA_ISensor): @ivar objectHitList: A list of colliding objects. (Read Only) @type objectHitList: list """ + + #--The following methods are deprecated, please use properties instead. def setProperty(name): """ - DEPRECATED: use the propertyName property + DEPRECATED: use the property property Set the property or material to collide with. Use setTouchMaterial() to switch between properties and materials. @type name: string """ + def getProperty(): """ - DEPRECATED: use the propertyName property + DEPRECATED: use the property property Returns the property or material to collide with. Use getTouchMaterial() to find out whether this sensor looks for properties or materials. (B{deprecated}) @rtype: string """ - def getHitObject(): """ DEPRECATED: use the objectHit property @@ -54,7 +57,7 @@ class KX_TouchSensor(SCA_ISensor): """ def getTouchMaterial(): """ - DEPRECATED: use the materialCheck property + DEPRECATED: use the useMaterial property Returns KX_TRUE if this sensor looks for a specific material, KX_FALSE if it looks for a specific property. (B{deprecated}) """ From 926515094204ebbaf2a391ee3d89567964e6a08b Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 28 Feb 2009 21:37:49 +0000 Subject: [PATCH 228/252] MSVC9 project file: add ffmpeg avdevice lib to linker for the blenderplayer. --- projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj index b539b64d374..fe20152388a 100644 --- a/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj +++ b/projectfiles_vc9/gameengine/gameplayer/ghost/GP_ghost.vcproj @@ -72,7 +72,7 @@ Date: Sat, 28 Feb 2009 21:44:24 +0000 Subject: [PATCH 229/252] BGE patch #18181 commited: Fixing some blenderplayer arguments (-c, -w, -f). --- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 75 +++++++++---------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 70272d57357..87b6b2450f7 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -162,33 +162,39 @@ void usage(const char* program) consoleoption = ""; #endif - printf("usage: %s [-w l t w h] %s[-g gamengineoptions] " + printf("usage: %s [-w [w h l t]] [-f [fw fh fb ff]] %s[-g gamengineoptions] " "[-s stereomode] filename.blend\n", program, consoleoption); - printf(" -h: Prints this command summary\n"); + printf(" -h: Prints this command summary\n\n"); printf(" -w: display in a window\n"); + printf(" --Optional parameters--\n"); + printf(" w = window width\n"); + printf(" h = window height\n\n"); printf(" l = window left coordinate\n"); printf(" t = window top coordinate\n"); - printf(" w = window width\n"); - printf(" h = window height\n"); + printf(" Note: If w or h is defined, both must be defined.\n"); + printf(" Also, if l or t is defined, all options must be used.\n\n"); printf(" -f: start game in full screen mode\n"); + printf(" --Optional parameters--\n"); printf(" fw = full screen mode pixel width\n"); - printf(" fh = full screen mode pixel height\n"); + printf(" fh = full screen mode pixel height\n\n"); printf(" fb = full screen mode bits per pixel\n"); printf(" ff = full screen mode frequency\n"); + printf(" Note: If fw or fh is defined, both must be defined.\n"); + printf(" Also, if fb is used, fw and fh must be used. ff requires all options.\n\n"); printf(" -s: start player in stereo\n"); printf(" stereomode: hwpageflip (Quad buffered shutter glasses)\n"); printf(" syncdoubling (Above Below)\n"); printf(" sidebyside (Left Right)\n"); printf(" anaglyph (Red-Blue glasses)\n"); printf(" vinterlace (Vertical interlace for autostereo display)\n"); - printf(" depending on the type of stereo you want\n"); + printf(" depending on the type of stereo you want\n\n"); #ifndef _WIN32 - printf(" -i: parent windows ID \n"); + printf(" -i: parent windows ID \n\n"); #endif #ifdef _WIN32 - printf(" -c: keep console window open\n"); + printf(" -c: keep console window open\n\n"); #endif - printf(" -d: turn debugging on\n"); + printf(" -d: turn debugging on\n\n"); printf(" -g: game engine options:\n\n"); printf(" Name Default Description\n"); printf(" ------------------------------------------------------------------------\n"); @@ -200,7 +206,7 @@ void usage(const char* program) printf(" blender_material 0 Enable material settings\n"); printf(" ignore_deprecation_warnings 0 Ignore deprecation warnings\n"); printf("\n"); - printf("example: %s -w 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program); + printf("example: %s -w 320 200 10 10 -g noaudio c:\\loadtest.blend\n", program); printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } @@ -431,54 +437,41 @@ int main(int argc, char** argv) G.f |= G_DEBUG; /* std output printf's */ MEM_set_memory_debug(); break; - - case 'p': - // Parse window position and size options - if (argv[i][2] == 0) { - i++; - if ((i + 4) < argc) - { - windowLeft = atoi(argv[i++]); - windowTop = atoi(argv[i++]); - windowWidth = atoi(argv[i++]); - windowHeight = atoi(argv[i++]); - windowParFound = true; - } - else - { - error = true; - printf("error: too few options for window argument.\n"); - } - } else { /* mac specific */ - - if (strncmp(argv[i], "-psn_", 5)==0) - i++; /* skip process serial number */ - } - break; + case 'f': i++; fullScreen = true; fullScreenParFound = true; - if ((i + 2) < argc && argv[i][0] != '-' && argv[i+1][0] != '-') + if ((i + 2) <= argc && argv[i][0] != '-' && argv[i+1][0] != '-') { fullScreenWidth = atoi(argv[i++]); fullScreenHeight = atoi(argv[i++]); - if ((i + 1) < argc && argv[i][0] != '-') + if ((i + 1) <= argc && argv[i][0] != '-') { fullScreenBpp = atoi(argv[i++]); - if ((i + 1) < argc && argv[i][0] != '-') + if ((i + 1) <= argc && argv[i][0] != '-') fullScreenFrequency = atoi(argv[i++]); } } break; case 'w': // Parse window position and size options + i++; + fullScreen = false; + windowParFound = true; + + if ((i + 2) <= argc && argv[i][0] != '-' && argv[i+1][0] != '-') { - fullScreen = false; - fullScreenParFound = true; - i++; + windowWidth = atoi(argv[i++]); + windowHeight = atoi(argv[i++]); + if ((i +2) <= argc && argv[i][0] != '-' && argv[i+1][0] != '-') + { + windowLeft = atoi(argv[i++]); + windowTop = atoi(argv[i++]); + } } break; + case 'h': usage(argv[0]); return 0; @@ -652,7 +645,7 @@ int main(int argc, char** argv) #ifdef NDEBUG if (closeConsole) { - //::FreeConsole(); // Close a console window + ::FreeConsole(); // Close a console window } #endif // NDEBUG #endif // WIN32 From d4adc43fc1746389ef89dce5c32163ba1d6011aa Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 28 Feb 2009 22:25:23 +0000 Subject: [PATCH 230/252] BGE patch #18309 commited: Add an addObject() method to KX_Scene. --- source/gameengine/Ketsji/KX_Scene.cpp | 47 ++++++++++++++++++++------- source/gameengine/Ketsji/KX_Scene.h | 1 + 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 073cfc98bf1..0fded15f1a1 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1517,18 +1517,6 @@ double KX_Scene::getSuspendedDelta() //---------------------------------------------------------------------------- //Python -PyMethodDef KX_Scene::Methods[] = { - KX_PYMETHODTABLE_NOARGS(KX_Scene, getLightList), - KX_PYMETHODTABLE_NOARGS(KX_Scene, getObjectList), - KX_PYMETHODTABLE_NOARGS(KX_Scene, getName), - - {NULL,NULL} //Sentinel -}; - -PyAttributeDef KX_Scene::Attributes[] = { - { NULL } //Sentinel -}; - PyTypeObject KX_Scene::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -1554,6 +1542,19 @@ PyParentObject KX_Scene::Parents[] = { NULL }; +PyMethodDef KX_Scene::Methods[] = { + KX_PYMETHODTABLE(KX_Scene, getLightList), + KX_PYMETHODTABLE(KX_Scene, getObjectList), + KX_PYMETHODTABLE(KX_Scene, getName), + KX_PYMETHODTABLE(KX_Scene, addObject), + + {NULL,NULL} //Sentinel +}; + +PyAttributeDef KX_Scene::Attributes[] = { + { NULL } //Sentinel +}; + PyObject* KX_Scene::_getattr(const char *attr) { if (!strcmp(attr, "name")) @@ -1622,3 +1623,25 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName, { return PyString_FromString(GetName()); } + +KX_PYMETHODDEF_DOC(KX_Scene, addObject, +"addObject(object, other, time=0)\n" +"Returns the added object.\n") +{ + PyObject *pyob, *pyother; + KX_GameObject *ob, *other; + + int time = 0; + + if (!PyArg_ParseTuple(args, "OO|i", &pyob, &pyother, &time)) + return NULL; + + if (!ConvertPythonToGameObject(pyob, &ob, false) + || !ConvertPythonToGameObject(pyother, &other, false)) + return NULL; + + + SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); + replica->AddRef(); + return replica; +} \ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index e49a87b0402..962db1a9b96 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -550,6 +550,7 @@ public: KX_PYMETHOD_DOC_NOARGS(KX_Scene, getLightList); KX_PYMETHOD_DOC_NOARGS(KX_Scene, getObjectList); KX_PYMETHOD_DOC_NOARGS(KX_Scene, getName); + KX_PYMETHOD_DOC(KX_Scene, addObject); /* KX_PYMETHOD_DOC(KX_Scene, getActiveCamera); KX_PYMETHOD_DOC(KX_Scene, getActiveCamera); From 892a667959f62bac3b405bdb88f3796f22a30997 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 1 Mar 2009 15:03:45 +0000 Subject: [PATCH 231/252] Limit cascading rotations (rotation on each child of a chain) to Individual Center mode, as I thought I had done at first. :| --- source/blender/src/transform_conversions.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index dadeb71f73e..76f315cde04 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -646,7 +646,7 @@ static void bone_children_clear_transflag(TransInfo *t, ListBase *lb) { bone->flag |= BONE_HINGE_CHILD_TRANSFORM; } - else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)) + else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL) { bone->flag |= BONE_TRANSFORM_CHILD; } @@ -3531,7 +3531,7 @@ static void set_trans_object_base_flags(TransInfo *t) if(parsel) { - if (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) + if ((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL) { base->flag |= BA_TRANSFORM_CHILD; } From cc2e3980f8469d1dec876f7bbff7ab31bffa553a Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 1 Mar 2009 21:23:04 +0000 Subject: [PATCH 232/252] * fix linking problem when building WITH_BF_PLAYER=True --- source/blender/nodes/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index 42dbbe4880e..d38303d7d20 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -39,7 +39,7 @@ if env['WITH_BF_QUICKTIME']: defs += ' WITH_QUICKTIME' incs += ' ' + env['BF_QUICKTIME_INC'] -env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 200, 300] ) +env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 200, 400] ) env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] ) env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] ) env.BlenderLib ( libname = 'bf_texnodes', sources = texsources, includes = Split(incs), defines = Split(defs), libtype=['intern', 'core', 'player'], priority = [200, 175, 300] ) From f8ef887880ac217cc831b2ab9677e1f9e825537b Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 2 Mar 2009 17:43:35 +0000 Subject: [PATCH 233/252] minor update to be compatible with Bullet 2.74 physics: btPoint3 has been deprecated, it was already a typedef to btVector3 replace std::vector by btAlignedObjectArray when storing Bullet objects, because MSVC STL implementation has some bugs, preventing to contain aligned objects (btVector3 is 16-byte aligned, to allow SIMD) --- .../Physics/Bullet/CcdPhysicsController.cpp | 27 ++++++++++--------- .../Physics/Bullet/CcdPhysicsController.h | 2 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index d09ad58fe3b..fc76af15301 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1240,7 +1240,7 @@ void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,flo void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ) { - btPoint3 pos(posX,posY,posZ); + btVector3 pos(posX,posY,posZ); m_worldTransform.setOrigin( pos ); } @@ -1328,7 +1328,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo for (int i=0;iVertexCount();i++) { const float* vtx = poly->GetVertex(i)->getXYZ(); - btPoint3 point(vtx[0],vtx[1],vtx[2]); + btVector3 point(vtx[0],vtx[1],vtx[2]); //avoid duplicates (could better directly use vertex offsets, rather than a vertex compare) bool found = false; for (int j=0;jGetVertex(2)->getXYZ(); - btPoint3 vertex0(vtx[0],vtx[1],vtx[2]); + btVector3 vertex0(vtx[0],vtx[1],vtx[2]); vtx = poly->GetVertex(1)->getXYZ(); - btPoint3 vertex1(vtx[0],vtx[1],vtx[2]); + btVector3 vertex1(vtx[0],vtx[1],vtx[2]); vtx = poly->GetVertex(0)->getXYZ(); - btPoint3 vertex2(vtx[0],vtx[1],vtx[2]); + btVector3 vertex2(vtx[0],vtx[1],vtx[2]); m_vertexArray.push_back(vertex0); m_vertexArray.push_back(vertex1); @@ -1365,13 +1365,13 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo if (poly->VertexCount() == 4) { const float* vtx = poly->GetVertex(3)->getXYZ(); - btPoint3 vertex0(vtx[0],vtx[1],vtx[2]); + btVector3 vertex0(vtx[0],vtx[1],vtx[2]); vtx = poly->GetVertex(2)->getXYZ(); - btPoint3 vertex1(vtx[0],vtx[1],vtx[2]); + btVector3 vertex1(vtx[0],vtx[1],vtx[2]); vtx = poly->GetVertex(0)->getXYZ(); - btPoint3 vertex2(vtx[0],vtx[1],vtx[2]); + btVector3 vertex2(vtx[0],vtx[1],vtx[2]); m_vertexArray.push_back(vertex0); m_vertexArray.push_back(vertex1); @@ -1442,7 +1442,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() break; case PHY_SHAPE_POLYTOPE: - collisionShape = new btConvexHullShape(&m_vertexArray.begin()->getX(), m_vertexArray.size()); + collisionShape = new btConvexHullShape(&m_vertexArray[0].getX(), m_vertexArray.size()); break; case PHY_SHAPE_MESH: @@ -1459,10 +1459,11 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() // m_vertexArray is necessarily a multiple of 3 - for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + for (int i=0;iaddTriangle(*it++,*it++,*it++); + collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i]); } + btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(collisionMeshData); collisionShape = gimpactShape; @@ -1476,9 +1477,9 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() collisionMeshData->m_weldingThreshold = m_weldingThreshold; // m_vertexArray is necessarily a multiple of 3 - for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + for (int i=0;iaddTriangle(*it++,*it++,*it++); + collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i]); } // this shape will be shared and not deleted until shapeInfo is deleted m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index c771aa2624b..deb3c0880e9 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -161,7 +161,7 @@ public: btTransform m_childTrans; btVector3 m_childScale; void* m_userData; - std::vector m_vertexArray; // Contains both vertex array for polytope shape and + btAlignedObjectArray 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 diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index eb01385bc01..63ad427852e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -414,7 +414,7 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) const btTransform& t = ctrl->GetCollisionObject()->getWorldTransform(); - btPoint3 minAabb,maxAabb; + btVector3 minAabb,maxAabb; shapeinterface->getAabb(t,minAabb,maxAabb); From 982a5cc60dd93b21ce110b3fff831d05720047bf Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 Mar 2009 03:41:24 +0000 Subject: [PATCH 234/252] Upgraded to Bullet 2.74. The upgrade introduced a few bugs, which need to be fixed before Blender 2.49. In particular, the Bullet vehicle seems broken, and some soft-body demos don't work. No new features or benefits are added yet, but a few improvements are planned before Blender 2.49 release. Please update the build systems, and add those 3 files: extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.cpp extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp I'll watch the Blender mailing list, in case this commit causes some issues. --- extern/bullet2/src/Bullet-C-Api.h | 18 +- .../BroadphaseCollision/btAxisSweep3.cpp | 9 +- .../BroadphaseCollision/btAxisSweep3.h | 182 +- .../btBroadphaseInterface.h | 22 +- .../BroadphaseCollision/btBroadphaseProxy.h | 45 +- .../BroadphaseCollision/btDbvt.cpp | 1512 ++++++------ .../BroadphaseCollision/btDbvt.h | 1345 ++++++----- .../BroadphaseCollision/btDbvtBroadphase.cpp | 755 +++--- .../BroadphaseCollision/btDbvtBroadphase.h | 116 +- .../BroadphaseCollision/btDispatcher.h | 17 +- .../btMultiSapBroadphase.cpp | 25 +- .../btMultiSapBroadphase.h | 9 +- .../btOverlappingPairCache.cpp | 82 +- .../btOverlappingPairCache.h | 37 +- .../BroadphaseCollision/btQuantizedBvh.cpp | 193 +- .../BroadphaseCollision/btQuantizedBvh.h | 69 +- .../btSimpleBroadphase.cpp | 58 +- .../BroadphaseCollision/btSimpleBroadphase.h | 31 +- .../src/BulletCollision/CMakeLists.txt | 383 +-- .../SphereTriangleDetector.cpp | 18 +- .../SphereTriangleDetector.h | 8 +- .../btActivatingCollisionAlgorithm.cpp | 47 + .../btActivatingCollisionAlgorithm.h | 36 + .../btBoxBoxCollisionAlgorithm.cpp | 2 +- .../btBoxBoxCollisionAlgorithm.h | 6 +- .../CollisionDispatch/btBoxBoxDetector.cpp | 14 +- .../btCollisionConfiguration.h | 2 +- .../CollisionDispatch/btCollisionCreateFunc.h | 1 - .../btCollisionDispatcher.cpp | 19 +- .../CollisionDispatch/btCollisionObject.cpp | 1 + .../CollisionDispatch/btCollisionObject.h | 44 +- .../CollisionDispatch/btCollisionWorld.cpp | 311 ++- .../CollisionDispatch/btCollisionWorld.h | 47 +- .../btCompoundCollisionAlgorithm.cpp | 71 +- .../btCompoundCollisionAlgorithm.h | 11 +- .../btConvexConcaveCollisionAlgorithm.cpp | 6 +- .../btConvexConcaveCollisionAlgorithm.h | 7 +- .../btConvexConvexAlgorithm.cpp | 204 +- .../btConvexConvexAlgorithm.h | 41 +- .../btConvexPlaneCollisionAlgorithm.cpp | 85 +- .../btConvexPlaneCollisionAlgorithm.h | 29 +- .../btDefaultCollisionConfiguration.cpp | 12 +- .../btDefaultCollisionConfiguration.h | 16 +- .../CollisionDispatch/btGhostObject.cpp | 171 ++ .../CollisionDispatch/btGhostObject.h | 174 ++ .../CollisionDispatch/btManifoldResult.cpp | 6 +- .../CollisionDispatch/btManifoldResult.h | 3 + .../btSimulationIslandManager.cpp | 182 +- .../btSimulationIslandManager.h | 16 +- .../btSphereBoxCollisionAlgorithm.cpp | 2 +- .../btSphereBoxCollisionAlgorithm.h | 4 +- .../btSphereSphereCollisionAlgorithm.cpp | 4 +- .../btSphereSphereCollisionAlgorithm.h | 6 +- .../btSphereTriangleCollisionAlgorithm.cpp | 6 +- .../btSphereTriangleCollisionAlgorithm.h | 6 +- .../CollisionDispatch/btUnionFind.cpp | 2 - .../CollisionDispatch/btUnionFind.h | 8 +- .../CollisionShapes/btBoxShape.h | 36 +- .../btBvhTriangleMeshShape.cpp | 54 +- .../CollisionShapes/btBvhTriangleMeshShape.h | 7 +- .../CollisionShapes/btCapsuleShape.cpp | 3 +- .../CollisionShapes/btCapsuleShape.h | 6 +- .../CollisionShapes/btCollisionShape.cpp | 10 +- .../CollisionShapes/btCollisionShape.h | 15 +- .../CollisionShapes/btCompoundShape.cpp | 65 +- .../CollisionShapes/btCompoundShape.h | 26 +- .../CollisionShapes/btConcaveShape.h | 10 + .../CollisionShapes/btConeShape.cpp | 6 +- .../CollisionShapes/btConeShape.h | 3 - .../CollisionShapes/btConvexHullShape.cpp | 45 +- .../CollisionShapes/btConvexHullShape.h | 42 +- .../CollisionShapes/btConvexInternalShape.cpp | 5 +- .../CollisionShapes/btConvexInternalShape.h | 11 +- .../btConvexPointCloudShape.cpp | 156 ++ .../CollisionShapes/btConvexPointCloudShape.h | 96 + .../CollisionShapes/btConvexShape.cpp | 361 +++ .../CollisionShapes/btConvexShape.h | 26 +- .../btConvexTriangleMeshShape.cpp | 18 +- .../btConvexTriangleMeshShape.h | 10 +- .../CollisionShapes/btCylinderShape.cpp | 2 +- .../CollisionShapes/btCylinderShape.h | 6 +- .../CollisionShapes/btEmptyShape.cpp | 3 +- .../CollisionShapes/btEmptyShape.h | 6 +- .../btHeightfieldTerrainShape.cpp | 255 +- .../btHeightfieldTerrainShape.h | 108 +- .../CollisionShapes/btMinkowskiSumShape.cpp | 10 +- .../CollisionShapes/btMinkowskiSumShape.h | 2 - .../CollisionShapes/btMultiSphereShape.cpp | 3 +- .../CollisionShapes/btMultiSphereShape.h | 1 - .../btMultimaterialTriangleMeshShape.h | 11 +- .../CollisionShapes/btOptimizedBvh.cpp | 26 +- .../btPolyhedralConvexShape.cpp | 5 +- .../CollisionShapes/btPolyhedralConvexShape.h | 25 +- .../btScaledBvhTriangleMeshShape.cpp | 11 +- .../btScaledBvhTriangleMeshShape.h | 7 +- .../CollisionShapes/btSphereShape.cpp | 6 - .../CollisionShapes/btSphereShape.h | 9 +- .../CollisionShapes/btStaticPlaneShape.cpp | 3 +- .../CollisionShapes/btStaticPlaneShape.h | 5 - .../CollisionShapes/btStridingMeshInterface.h | 23 +- .../CollisionShapes/btTetrahedronShape.cpp | 35 +- .../CollisionShapes/btTetrahedronShape.h | 21 +- .../CollisionShapes/btTriangleBuffer.h | 2 +- .../btTriangleIndexVertexArray.cpp | 4 +- .../btTriangleIndexVertexArray.h | 8 +- .../btTriangleIndexVertexMaterialArray.cpp | 1 + .../CollisionShapes/btTriangleMesh.cpp | 52 +- .../CollisionShapes/btTriangleMesh.h | 8 +- .../CollisionShapes/btTriangleMeshShape.cpp | 5 +- .../CollisionShapes/btTriangleMeshShape.h | 2 +- .../CollisionShapes/btTriangleShape.h | 17 +- .../CollisionShapes/btUniformScalingShape.cpp | 3 +- .../CollisionShapes/btUniformScalingShape.h | 1 - .../BulletCollision/Gimpact/btBoxCollision.h | 8 +- .../BulletCollision/Gimpact/btClipPolygon.h | 4 - .../Gimpact/btContactProcessing.cpp | 6 +- .../Gimpact/btContactProcessing.h | 24 +- .../BulletCollision/Gimpact/btGImpactBvh.cpp | 15 +- .../BulletCollision/Gimpact/btGImpactBvh.h | 47 +- .../Gimpact/btGImpactCollisionAlgorithm.cpp | 13 +- .../Gimpact/btGImpactCollisionAlgorithm.h | 6 +- .../Gimpact/btGImpactQuantizedBvh.cpp | 17 +- .../Gimpact/btGImpactQuantizedBvh.h | 21 +- .../BulletCollision/Gimpact/btGImpactShape.h | 17 +- .../Gimpact/btGenericPoolAllocator.cpp | 6 +- .../Gimpact/btGenericPoolAllocator.h | 5 - .../Gimpact/btGeometryOperations.h | 4 - .../BulletCollision/Gimpact/btQuantization.h | 4 - .../Gimpact/btTriangleShapeEx.cpp | 8 +- .../Gimpact/btTriangleShapeEx.h | 10 +- .../src/BulletCollision/Gimpact/gim_array.h | 8 +- .../Gimpact/gim_basic_geometry_operations.h | 4 - .../src/BulletCollision/Gimpact/gim_bitset.h | 6 - .../Gimpact/gim_box_collision.h | 4 - .../BulletCollision/Gimpact/gim_box_set.cpp | 4 +- .../src/BulletCollision/Gimpact/gim_box_set.h | 7 - .../Gimpact/gim_clip_polygon.h | 4 - .../src/BulletCollision/Gimpact/gim_contact.h | 16 +- .../BulletCollision/Gimpact/gim_geom_types.h | 7 +- .../BulletCollision/Gimpact/gim_hash_table.h | 26 +- .../BulletCollision/Gimpact/gim_linear_math.h | 11 - .../src/BulletCollision/Gimpact/gim_math.h | 32 +- .../src/BulletCollision/Gimpact/gim_memory.h | 45 +- .../BulletCollision/Gimpact/gim_radixsort.h | 8 +- .../Gimpact/gim_tri_collision.cpp | 6 +- .../Gimpact/gim_tri_collision.h | 6 +- .../btContinuousConvexCollision.cpp | 8 +- .../btConvexPenetrationDepthSolver.h | 3 +- .../NarrowPhaseCollision/btGjkEpa2.cpp | 1456 ++++++------ .../btGjkEpaPenetrationDepthSolver.cpp | 13 +- .../btGjkEpaPenetrationDepthSolver.h | 2 +- .../btGjkPairDetector.cpp | 70 +- .../NarrowPhaseCollision/btGjkPairDetector.h | 11 +- .../NarrowPhaseCollision/btManifoldPoint.h | 8 + .../btMinkowskiPenetrationDepthSolver.cpp | 19 +- .../btMinkowskiPenetrationDepthSolver.h | 3 +- .../btPersistentManifold.cpp | 11 +- .../btPersistentManifold.h | 20 +- .../btRaycastCallback.cpp | 20 +- .../NarrowPhaseCollision/btRaycastCallback.h | 13 +- .../btSimplexSolverInterface.h | 7 +- .../btVoronoiSimplexSolver.cpp | 24 +- .../btVoronoiSimplexSolver.h | 22 +- .../bullet2/src/BulletDynamics/CMakeLists.txt | 93 +- .../btConeTwistConstraint.cpp | 976 ++++++-- .../ConstraintSolver/btConeTwistConstraint.h | 109 +- .../ConstraintSolver/btContactConstraint.cpp | 14 +- .../ConstraintSolver/btContactConstraint.h | 2 +- .../ConstraintSolver/btContactSolverInfo.h | 16 +- .../btGeneric6DofConstraint.cpp | 901 +++++--- .../btGeneric6DofConstraint.h | 55 +- .../ConstraintSolver/btHingeConstraint.cpp | 683 ++++-- .../ConstraintSolver/btHingeConstraint.h | 30 +- .../btPoint2PointConstraint.cpp | 207 +- .../btPoint2PointConstraint.h | 9 +- .../btSequentialImpulseConstraintSolver.cpp | 2001 +++++++--------- .../btSequentialImpulseConstraintSolver.h | 75 +- .../ConstraintSolver/btSliderConstraint.cpp | 462 +++- .../ConstraintSolver/btSliderConstraint.h | 15 +- .../ConstraintSolver/btSolverBody.h | 162 +- .../ConstraintSolver/btSolverConstraint.h | 62 +- .../ConstraintSolver/btTypedConstraint.cpp | 64 +- .../ConstraintSolver/btTypedConstraint.h | 65 +- .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 22 +- .../Dynamics/btDiscreteDynamicsWorld.cpp | 370 ++- .../Dynamics/btDiscreteDynamicsWorld.h | 37 +- .../BulletDynamics/Dynamics/btDynamicsWorld.h | 8 + .../BulletDynamics/Dynamics/btRigidBody.cpp | 12 +- .../src/BulletDynamics/Dynamics/btRigidBody.h | 33 +- .../Dynamics/btSimpleDynamicsWorld.cpp | 6 +- .../Dynamics/btSimpleDynamicsWorld.h | 4 +- .../Vehicle/btRaycastVehicle.cpp | 12 +- .../BulletDynamics/Vehicle/btRaycastVehicle.h | 13 +- .../bullet2/src/BulletSoftBody/CMakeLists.txt | 38 +- .../bullet2/src/BulletSoftBody/btSoftBody.cpp | 2049 +++++++++-------- .../bullet2/src/BulletSoftBody/btSoftBody.h | 291 +-- .../btSoftBodyConcaveCollisionAlgorithm.cpp | 120 +- .../btSoftBodyConcaveCollisionAlgorithm.h | 12 +- .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 478 ++-- .../src/BulletSoftBody/btSoftBodyHelpers.h | 86 +- .../src/BulletSoftBody/btSoftBodyInternals.h | 737 +++--- ...oftBodyRigidBodyCollisionConfiguration.cpp | 18 +- ...tSoftBodyRigidBodyCollisionConfiguration.h | 2 +- .../btSoftRigidCollisionAlgorithm.cpp | 6 +- .../btSoftRigidCollisionAlgorithm.h | 8 +- .../btSoftRigidDynamicsWorld.cpp | 41 +- .../BulletSoftBody/btSoftRigidDynamicsWorld.h | 18 +- .../btSoftSoftCollisionAlgorithm.h | 2 +- .../bullet2/src/BulletSoftBody/btSparseSDF.h | 178 +- extern/bullet2/src/LinearMath/CMakeLists.txt | 28 +- extern/bullet2/src/LinearMath/btAabbUtil2.h | 52 +- .../src/LinearMath/btAlignedAllocator.cpp | 30 +- .../src/LinearMath/btAlignedAllocator.h | 7 +- .../src/LinearMath/btAlignedObjectArray.h | 26 +- .../bullet2/src/LinearMath/btConvexHull.cpp | 54 +- extern/bullet2/src/LinearMath/btConvexHull.h | 20 +- extern/bullet2/src/LinearMath/btIDebugDraw.h | 181 ++ extern/bullet2/src/LinearMath/btMatrix3x3.h | 240 +- extern/bullet2/src/LinearMath/btQuadWord.h | 186 +- extern/bullet2/src/LinearMath/btQuaternion.h | 166 +- extern/bullet2/src/LinearMath/btQuickprof.cpp | 66 +- extern/bullet2/src/LinearMath/btQuickprof.h | 26 +- extern/bullet2/src/LinearMath/btScalar.h | 32 +- extern/bullet2/src/LinearMath/btStackAlloc.h | 1 + extern/bullet2/src/LinearMath/btTransform.h | 66 +- .../bullet2/src/LinearMath/btTransformUtil.h | 123 +- extern/bullet2/src/LinearMath/btVector3.h | 345 ++- .../Physics/Bullet/CcdPhysicsController.cpp | 6 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 4 +- 229 files changed, 14283 insertions(+), 8330 deletions(-) create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h index 8074aed3038..a4a8a70524e 100644 --- a/extern/bullet2/src/Bullet-C-Api.h +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -38,37 +38,37 @@ typedef plReal plQuaternion[4]; extern "C" { #endif -/* Particular physics SDK */ +/** Particular physics SDK (C-API) */ PL_DECLARE_HANDLE(plPhysicsSdkHandle); -/* Dynamics world, belonging to some physics SDK */ +/** Dynamics world, belonging to some physics SDK (C-API)*/ PL_DECLARE_HANDLE(plDynamicsWorldHandle); -/* Rigid Body that can be part of a Dynamics World */ +/** Rigid Body that can be part of a Dynamics World (C-API)*/ PL_DECLARE_HANDLE(plRigidBodyHandle); -/* Collision Shape/Geometry, property of a Rigid Body */ +/** Collision Shape/Geometry, property of a Rigid Body (C-API)*/ PL_DECLARE_HANDLE(plCollisionShapeHandle); -/* Constraint for Rigid Bodies */ +/** Constraint for Rigid Bodies (C-API)*/ PL_DECLARE_HANDLE(plConstraintHandle); -/* Triangle Mesh interface */ +/** Triangle Mesh interface (C-API)*/ PL_DECLARE_HANDLE(plMeshInterfaceHandle); -/* Broadphase Scene/Proxy Handles */ +/** Broadphase Scene/Proxy Handles (C-API)*/ 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 */ +/** 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); diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp index d7eea33ea41..77763305b1b 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp @@ -19,10 +19,9 @@ // 3. This notice may not be removed or altered from any source distribution. #include "btAxisSweep3.h" -#include -btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache) -:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache) +btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator) { // 1 handle is reserved as sentinel btAssert(maxHandles > 1 && maxHandles < 32767); @@ -30,8 +29,8 @@ btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAab } -bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache ) -:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache) +bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator) { // 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 d0ad09a385a..cad21b4cad2 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -19,12 +19,12 @@ #ifndef AXIS_SWEEP_3_H #define AXIS_SWEEP_3_H -#include "LinearMath/btPoint3.h" #include "LinearMath/btVector3.h" #include "btOverlappingPairCache.h" #include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" #include "btOverlappingPairCallback.h" +#include "btDbvtBroadphase.h" //#define DEBUG_BROADPHASE 1 #define USE_OVERLAP_TEST_ON_REMOVES 1 @@ -42,6 +42,7 @@ protected: public: + BT_DECLARE_ALIGNED_ALLOCATOR(); class Edge { @@ -61,8 +62,7 @@ public: // 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_pad; - + btBroadphaseProxy* m_dbvtProxy;//for faster raycast //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} @@ -71,8 +71,8 @@ public: protected: - btPoint3 m_worldAabbMin; // overall system bounds - btPoint3 m_worldAabbMax; // overall system bounds + btVector3 m_worldAabbMin; // overall system bounds + btVector3 m_worldAabbMax; // overall system bounds btVector3 m_quantize; // scaling factor for quantization @@ -94,6 +94,12 @@ protected: int m_invalidPair; + ///additional dynamic aabb structure, used to accelerate ray cast queries. + ///can be disabled using a optional argument in the constructor + btDbvtBroadphase* m_raycastAccelerator; + btOverlappingPairCache* m_nullPairCache; + + // allocation/deallocation BP_FP_INT_TYPE allocHandle(); void freeHandle(BP_FP_INT_TYPE handle); @@ -108,7 +114,7 @@ protected: //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); - 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 ); @@ -117,7 +123,7 @@ protected: public: - 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); + btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false); virtual ~btAxisSweep3Internal(); @@ -128,17 +134,26 @@ public: virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& 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); + void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} + virtual void resetPool(btDispatcher* dispatcher); + 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); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)); + + void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const; + ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result + void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); @@ -206,7 +221,7 @@ void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinalit } if (checkCardinality) - assert(numEdges == m_numHandles*2+1); + btAssert(numEdges == m_numHandles*2+1); } #endif //DEBUG_BROADPHASE @@ -217,7 +232,12 @@ btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btV BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy); Handle* handle = getHandle(handleId); - + + if (m_raycastAccelerator) + { + btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0); + handle->m_dbvtProxy = rayProxy; + } return handle; } @@ -227,6 +247,8 @@ template void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) { Handle* handle = static_cast(proxy); + if (m_raycastAccelerator) + m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher); removeHandle(static_cast(handle->m_uniqueId), dispatcher); } @@ -234,22 +256,80 @@ template void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) { Handle* handle = static_cast(proxy); + handle->m_aabbMin = aabbMin; + handle->m_aabbMax = aabbMax; updateHandle(static_cast(handle->m_uniqueId), aabbMin, aabbMax,dispatcher); + if (m_raycastAccelerator) + m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher); } +template +void btAxisSweep3Internal::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) +{ + if (m_raycastAccelerator) + { + m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax); + } else + { + //choose axis? + BP_FP_INT_TYPE axis = 0; + //for each proxy + for (BP_FP_INT_TYPE i=1;i +void btAxisSweep3Internal::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + Handle* pHandle = static_cast(proxy); + aabbMin = pHandle->m_aabbMin; + aabbMax = pHandle->m_aabbMax; +} + + +template +void btAxisSweep3Internal::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + Handle* pHandle = static_cast(proxy); + + unsigned short vecInMin[3]; + unsigned short vecInMax[3]; + + vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ; + vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ; + vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ; + vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ; + vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ; + vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ; + + aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ())); + aabbMin += m_worldAabbMin; + + aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ())); + aabbMax += m_worldAabbMin; +} + - 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 ) +btAxisSweep3Internal::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator) :m_bpHandleMask(handleMask), m_handleSentinel(handleSentinel), m_pairCache(pairCache), m_userPairCallback(0), m_ownsPairCache(false), -m_invalidPair(0) +m_invalidPair(0), +m_raycastAccelerator(0) { BP_FP_INT_TYPE maxHandles = static_cast(userMaxHandles+1);//need to add one sentinel handle @@ -260,7 +340,14 @@ m_invalidPair(0) m_ownsPairCache = true; } - //assert(bounds.HasVolume()); + if (!disableRaycastAccelerator) + { + m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache(); + m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache); + m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs + } + + //btAssert(bounds.HasVolume()); // init bounds m_worldAabbMin = worldAabbMin; @@ -320,7 +407,14 @@ m_invalidPair(0) template btAxisSweep3Internal::~btAxisSweep3Internal() { - + if (m_raycastAccelerator) + { + m_nullPairCache->~btOverlappingPairCache(); + btAlignedFree(m_nullPairCache); + m_raycastAccelerator->~btDbvtBroadphase(); + btAlignedFree (m_raycastAccelerator); + } + for (int i = 2; i >= 0; i--) { btAlignedFree(m_pEdgesRawPtr[i]); @@ -335,27 +429,31 @@ btAxisSweep3Internal::~btAxisSweep3Internal() } template -void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const +void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const { - btPoint3 clampedPoint(point); - - - +#ifdef OLD_CLAMPING_METHOD + ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax] + ///see http://code.google.com/p/bullet/issues/detail?id=87 + btVector3 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); - +#else + btVector3 v = (point - m_worldAabbMin) * m_quantize; + out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax); + out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax); + out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax); +#endif //OLD_CLAMPING_METHOD } template BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() { - assert(m_firstFreeHandle); + btAssert(m_firstFreeHandle); BP_FP_INT_TYPE handle = m_firstFreeHandle; m_firstFreeHandle = getHandle(handle)->GetNextFree(); @@ -367,7 +465,7 @@ BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() template void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) { - assert(handle > 0 && handle < m_maxHandles); + btAssert(handle > 0 && handle < m_maxHandles); getHandle(handle)->SetNextFree(m_firstFreeHandle); m_firstFreeHandle = handle; @@ -377,7 +475,7 @@ void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) 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) +BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) { // quantize the bounds BP_FP_INT_TYPE min[3], max[3]; @@ -440,7 +538,7 @@ void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,bt //explicitly remove the pairs containing the proxy //we could do it also in the sortMinUp (passing true) - //todo: compare performance + ///@todo: compare performance if (!m_pairCache->hasDeferredRemoval()) { m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher); @@ -489,6 +587,21 @@ void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,bt } +template +void btAxisSweep3Internal::resetPool(btDispatcher* dispatcher) +{ + if (m_numHandles == 0) + { + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++) + m_pHandles[i].SetNextFree(static_cast(i + 1)); + m_pHandles[m_maxHandles - 1].SetNextFree(0); + } + } +} + + extern int gOverlappingPairs; //#include @@ -529,6 +642,7 @@ void btAxisSweep3Internal::calculateOverlappingPairs(btDispatche if (!isDuplicate) { + ///important to use an AABB test that is consistent with the broadphase bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); if (hasOverlap) @@ -574,10 +688,6 @@ void btAxisSweep3Internal::calculateOverlappingPairs(btDispatche //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); } - - - - } @@ -616,10 +726,10 @@ bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, } template -void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher) +void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) { -// assert(bounds.IsFinite()); - //assert(bounds.HasVolume()); +// btAssert(bounds.IsFinite()); + //btAssert(bounds.HasVolume()); Handle* pHandle = getHandle(handle); @@ -895,7 +1005,7 @@ class btAxisSweep3 : public btAxisSweep3Internal { public: - btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0); + btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false); }; @@ -906,7 +1016,7 @@ class bt32BitAxisSweep3 : public btAxisSweep3Internal { public: - bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0); + bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false); }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h index 200ac365329..b7bbaf512ae 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -21,8 +21,22 @@ subject to the following restrictions: struct btDispatcherInfo; class btDispatcher; #include "btBroadphaseProxy.h" + class btOverlappingPairCache; + + +struct btBroadphaseRayCallback +{ + ///added some cached data to accelerate ray-AABB tests + btVector3 m_rayDirectionInverse; + unsigned int m_signs[3]; + btScalar m_lambda_max; + + virtual ~btBroadphaseRayCallback() {} + virtual bool process(const btBroadphaseProxy* proxy) = 0; +}; + #include "LinearMath/btVector3.h" ///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs. @@ -36,7 +50,10 @@ public: 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 void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0; + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0; @@ -47,6 +64,9 @@ public: ///will add some transform later virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0; + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher) {}; + virtual void printStats() = 0; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index a074a0b150b..be261ec4080 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -17,20 +17,24 @@ subject to the following restrictions: #define BROADPHASE_PROXY_H #include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btVector3.h" #include "LinearMath/btAlignedAllocator.h" /// btDispatcher uses these types /// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave /// to facilitate type checking +/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code enum BroadphaseNativeTypes { -// polyhedral convex shapes + // polyhedral convex shapes BOX_SHAPE_PROXYTYPE, TRIANGLE_SHAPE_PROXYTYPE, TETRAHEDRAL_SHAPE_PROXYTYPE, CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE, CONVEX_HULL_SHAPE_PROXYTYPE, + CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE, + CUSTOM_POLYHEDRAL_SHAPE_TYPE, //implicit convex shapes IMPLICIT_CONVEX_SHAPES_START_HERE, SPHERE_SHAPE_PROXYTYPE, @@ -42,6 +46,7 @@ IMPLICIT_CONVEX_SHAPES_START_HERE, UNIFORM_SCALING_SHAPE_PROXYTYPE, MINKOWSKI_SUM_SHAPE_PROXYTYPE, MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, + CUSTOM_CONVEX_SHAPE_TYPE, //concave shapes CONCAVE_SHAPES_START_HERE, //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! @@ -58,13 +63,18 @@ CONCAVE_SHAPES_START_HERE, EMPTY_SHAPE_PROXYTYPE, STATIC_PLANE_PROXYTYPE, + CUSTOM_CONCAVE_SHAPE_TYPE, CONCAVE_SHAPES_END_HERE, COMPOUND_SHAPE_PROXYTYPE, SOFTBODY_SHAPE_PROXYTYPE, + HFFLUID_SHAPE_PROXYTYPE, + HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE, + INVALID_SHAPE_PROXYTYPE, MAX_BROADPHASE_COLLISION_TYPES + }; @@ -83,20 +93,20 @@ BT_DECLARE_ALIGNED_ALLOCATOR(); KinematicFilter = 4, DebrisFilter = 8, SensorTrigger = 16, + CharacterFilter = 32, 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; - void* m_multiSapParentProxy; - - int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. + btVector3 m_aabbMin; + btVector3 m_aabbMax; + SIMD_FORCE_INLINE int getUid() const { return m_uniqueId; @@ -107,10 +117,12 @@ BT_DECLARE_ALIGNED_ALLOCATOR(); { } - btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) + btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) :m_clientObject(userPtr), m_collisionFilterGroup(collisionFilterGroup), - m_collisionFilterMask(collisionFilterMask) + m_collisionFilterMask(collisionFilterMask), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax) { m_multiSapParentProxy = multiSapParentProxy; } @@ -159,7 +171,7 @@ ATTRIBUTE_ALIGNED16(struct) btBroadphasePair m_pProxy0(0), m_pProxy1(0), m_algorithm(0), - m_userInfo(0) + m_internalInfo1(0) { } @@ -169,14 +181,14 @@ BT_DECLARE_ALIGNED_ALLOCATOR(); : m_pProxy0(other.m_pProxy0), m_pProxy1(other.m_pProxy1), m_algorithm(other.m_algorithm), - m_userInfo(other.m_userInfo) + m_internalInfo1(other.m_internalInfo1) { } btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1) { //keep them sorted, so the std::set operations work - if (&proxy0 < &proxy1) + if (proxy0.m_uniqueId < proxy1.m_uniqueId) { m_pProxy0 = &proxy0; m_pProxy1 = &proxy1; @@ -188,7 +200,7 @@ BT_DECLARE_ALIGNED_ALLOCATOR(); } m_algorithm = 0; - m_userInfo = 0; + m_internalInfo1 = 0; } @@ -196,7 +208,7 @@ BT_DECLARE_ALIGNED_ALLOCATOR(); btBroadphaseProxy* m_pProxy1; mutable btCollisionAlgorithm* m_algorithm; - mutable void* m_userInfo; + union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version. }; @@ -217,8 +229,13 @@ class btBroadphasePairSortPredicate bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) { - return a.m_pProxy0 > b.m_pProxy0 || - (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 > b.m_pProxy1) || + const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1; + const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1; + const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1; + const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1; + + return uidA0 > uidB0 || + (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) || (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); } }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp index 7c41c8d8f71..a6e36b47049 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp @@ -23,188 +23,188 @@ typedef btAlignedObjectArray tConstNodeArray; // struct btDbvtNodeEnumerator : btDbvt::ICollide { -tConstNodeArray nodes; -void Process(const btDbvtNode* n) { nodes.push_back(n); } + 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); + return(node->parent->childs[1]==node); } // static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a, - const btDbvtVolume& b) + const btDbvtVolume& b) { -#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE -DBVT_ALIGN char locals[sizeof(btDbvtAabbMm)]; -btDbvtVolume& res=*(btDbvtVolume*)locals; +#if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE) + ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]); + btDbvtVolume& res=*(btDbvtVolume*)locals; #else -btDbvtVolume res; + btDbvtVolume res; #endif -Merge(a,b,res); -return(res); + 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()+ + 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()) + if(node->isinternal()) { - getmaxdepth(node->childs[0],depth+1,maxdepth); - getmaxdepth(node->childs[0],depth+1,maxdepth); + 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) + btDbvtNode* node) { -btAlignedFree(pdbvt->m_free); -pdbvt->m_free=node; + btAlignedFree(pdbvt->m_free); + pdbvt->m_free=node; } - + // static void recursedeletenode( btDbvt* pdbvt, - btDbvtNode* node) + btDbvtNode* node) { -if(!node->isleaf()) + if(!node->isleaf()) { - recursedeletenode(pdbvt,node->childs[0]); - recursedeletenode(pdbvt,node->childs[1]); + recursedeletenode(pdbvt,node->childs[0]); + recursedeletenode(pdbvt,node->childs[1]); } -if(node==pdbvt->m_root) pdbvt->m_root=0; -deletenode(pdbvt,node); + if(node==pdbvt->m_root) pdbvt->m_root=0; + deletenode(pdbvt,node); } // static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, - btDbvtNode* parent, - void* data) + btDbvtNode* parent, + void* data) { -btDbvtNode* node; -if(pdbvt->m_free) + 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); + 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* parent, + const btDbvtVolume& volume, + void* data) { -btDbvtNode* node=createnode(pdbvt,parent,data); -node->volume=volume; -return(node); + 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* parent, + const btDbvtVolume& volume0, + const btDbvtVolume& volume1, + void* data) { -btDbvtNode* node=createnode(pdbvt,parent,data); -Merge(volume0,volume1,node->volume); -return(node); + btDbvtNode* node=createnode(pdbvt,parent,data); + Merge(volume0,volume1,node->volume); + return(node); } // static void insertleaf( btDbvt* pdbvt, - btDbvtNode* root, - btDbvtNode* leaf) + btDbvtNode* root, + btDbvtNode* leaf) { -if(!pdbvt->m_root) + if(!pdbvt->m_root) { - pdbvt->m_root = leaf; - leaf->parent = 0; + pdbvt->m_root = leaf; + leaf->parent = 0; } else { - if(!root->isleaf()) + if(!root->isleaf()) { - do { - root=root->childs[Select( leaf->volume, - root->childs[0]->volume, - root->childs[1]->volume)]; + 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) + 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); + 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; + 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; + 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) + btDbvtNode* leaf) { -if(leaf==pdbvt->m_root) + if(leaf==pdbvt->m_root) { - pdbvt->m_root=0; - return(0); + pdbvt->m_root=0; + return(0); } else { - btDbvtNode* parent=leaf->parent; - btDbvtNode* prev=parent->parent; - btDbvtNode* sibling=parent->childs[1-indexof(leaf)]; - if(prev) + 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) + 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)) + const btDbvtVolume pb=prev->volume; + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + if(NotEqual(pb,prev->volume)) { - prev=prev->parent; + prev=prev->parent; } else break; } - return(prev?prev:pdbvt->m_root); + return(prev?prev:pdbvt->m_root); } else { - pdbvt->m_root=sibling; - sibling->parent=0; - deletenode(pdbvt,parent); - return(pdbvt->m_root); + pdbvt->m_root=sibling; + sibling->parent=0; + deletenode(pdbvt,parent); + return(pdbvt->m_root); } } } @@ -215,33 +215,33 @@ static void fetchleaves(btDbvt* pdbvt, tNodeArray& leaves, int depth=-1) { -if(root->isinternal()&&depth) + if(root->isinternal()&&depth) { - fetchleaves(pdbvt,root->childs[0],leaves,depth-1); - fetchleaves(pdbvt,root->childs[1],leaves,depth-1); - deletenode(pdbvt,root); + fetchleaves(pdbvt,root->childs[0],leaves,depth-1); + fetchleaves(pdbvt,root->childs[1],leaves,depth-1); + deletenode(pdbvt,root); } else { - leaves.push_back(root); + leaves.push_back(root); } } // static void split( const tNodeArray& leaves, - tNodeArray& left, - tNodeArray& right, - const btVector3& org, - const btVector3& axis) + 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]); + if(dot(axis,leaves[i]->volume.Center()-org)<0) + left.push_back(leaves[i]); else - right.push_back(leaves[i]); + right.push_back(leaves[i]); } } @@ -249,49 +249,49 @@ for(int i=0,ni=leaves.size();ivolume; + ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]); + btDbvtVolume& volume=*(btDbvtVolume*)locals; + volume=leaves[0]->volume; #else -btDbvtVolume volume=leaves[0]->volume; + btDbvtVolume volume=leaves[0]->volume; #endif -for(int i=1,ni=leaves.size();ivolume,volume); + Merge(volume,leaves[i]->volume,volume); } -return(volume); + return(volume); } // static void bottomup( btDbvt* pdbvt, - tNodeArray& leaves) + tNodeArray& leaves) { -while(leaves.size()>1) + while(leaves.size()>1) { - btScalar minsize=SIMD_INFINITY; - int minidx[2]={-1,-1}; - for(int i=0;ivolume,leaves[j]->volume)); - if(szvolume,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(); + btDbvtNode* n[] = {leaves[minidx[0]],leaves[minidx[1]]}; + btDbvtNode* p = createnode(pdbvt,0,n[0]->volume,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(); } } @@ -300,175 +300,181 @@ 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) + 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) + 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) + const btVector3 x=leaves[i]->volume.Center()-org; + for(int j=0;j<3;++j) { - ++splitcount[j][dot(x,axis[j])>0?1:0]; + ++splitcount[j][dot(x,axis[j])>0?1:0]; } } - for( i=0;i<3;++i) + for( i=0;i<3;++i) { - if((splitcount[i][0]>0)&&(splitcount[i][1]>0)) + if((splitcount[i][0]>0)&&(splitcount[i][1]>0)) { - const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1])); - if(midp=0) + if(bestaxis>=0) { - sets[0].reserve(splitcount[bestaxis][0]); - sets[1].reserve(splitcount[bestaxis][1]); - split(leaves,sets[0],sets[1],org,axis[bestaxis]); + 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); + btDbvtNode* node=createnode(pdbvt,0,vol,0); + node->childs[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]); + bottomup(pdbvt,leaves); + return(leaves[0]); } } -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) + 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); + 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); + return(n); } -// +#if 0 static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count) { -while(n&&(count--)) n=n->parent; -return(n); + while(n&&(count--)) n=n->parent; + return(n); } +#endif // // Api // // - btDbvt::btDbvt() +btDbvt::btDbvt() { -m_root = 0; -m_free = 0; -m_lkhd = -1; -m_leaves = 0; -m_opath = 0; + m_root = 0; + m_free = 0; + m_lkhd = -1; + m_leaves = 0; + m_opath = 0; } // - btDbvt::~btDbvt() +btDbvt::~btDbvt() { -clear(); + clear(); } // void btDbvt::clear() { -if(m_root) recursedeletenode(this,m_root); -btAlignedFree(m_free); -m_free=0; + if(m_root) + recursedeletenode(this,m_root); + btAlignedFree(m_free); + m_free=0; + m_lkhd = -1; + m_stkStack.clear(); + m_opath = 0; + } // void btDbvt::optimizeBottomUp() { -if(m_root) + if(m_root) { - tNodeArray leaves; - leaves.reserve(m_leaves); - fetchleaves(this,m_root,leaves); - bottomup(this,leaves); - m_root=leaves[0]; + 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) + if(m_root) { - tNodeArray leaves; - leaves.reserve(m_leaves); - fetchleaves(this,m_root,leaves); - m_root=topdown(this,leaves,bu_treshold); + 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)) + if(passes<0) passes=m_leaves; + if(m_root&&(passes>0)) { - do { - btDbvtNode* node=m_root; - unsigned bit=0; - while(node->isinternal()) + 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); + node=sort(node,m_root)->childs[(m_opath>>bit)&1]; + bit=(bit+1)&(sizeof(unsigned)*8-1); } - update(node); - ++m_opath; + update(node); + ++m_opath; } while(--passes); } } @@ -476,104 +482,104 @@ if(m_root&&(passes>0)) // btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data) { -btDbvtNode* leaf=createnode(this,0,volume,data); -insertleaf(this,m_root,leaf); -++m_leaves; -return(leaf); + 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) + btDbvtNode* root=removeleaf(this,leaf); + if(root) { - if(lookahead>=0) + if(lookahead>=0) { - for(int i=0;(iparent;++i) + for(int i=0;(iparent;++i) { - root=root->parent; + root=root->parent; } } else root=m_root; } -insertleaf(this,root,leaf); + insertleaf(this,root,leaf); } // -void btDbvt::update(btDbvtNode* leaf,const btDbvtVolume& volume) +void btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume) { -btDbvtNode* root=removeleaf(this,leaf); -if(root) + btDbvtNode* root=removeleaf(this,leaf); + if(root) { - if(m_lkhd>=0) + if(m_lkhd>=0) { - for(int i=0;(iparent;++i) + for(int i=0;(iparent;++i) { - root=root->parent; + root=root->parent; } } else root=m_root; } -leaf->volume=volume; -insertleaf(this,root,leaf); + leaf->volume=volume; + insertleaf(this,root,leaf); } // -bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin) +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); + 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) +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); + if(leaf->volume.Contain(volume)) return(false); + volume.SignedExpand(velocity); + update(leaf,volume); + return(true); } // -bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin) +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); + 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; + 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;iPrepare(m_root,nodes.nodes.size()); + for(int i=0;iparent) p=nodes.nodes.findLinearSearch(n->parent); - if(n->isinternal()) + const btDbvtNode* n=nodes.nodes[i]; + int p=-1; + if(n->parent) 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); + 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); + iwriter->WriteLeaf(n,i,p); } } } @@ -581,29 +587,29 @@ for(int i=0;i 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; + 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()) + 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)); + stack.push_back(sStkCLN(e.node->childs[0],n)); + stack.push_back(sStkCLN(e.node->childs[1],n)); } else { - iclone->CloneLeaf(n); + iclone->CloneLeaf(n); } } while(stack.size()>0); } @@ -612,31 +618,31 @@ if(m_root!=0) // int btDbvt::maxdepth(const btDbvtNode* node) { -int depth=0; -if(node) getmaxdepth(node,1,depth); -return(depth); + 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])); + if(node->isinternal()) + return(countLeaves(node->childs[0])+countLeaves(node->childs[1])); else - return(1); + return(1); } // void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves) { -if(node->isinternal()) + if(node->isinternal()) { - extractLeaves(node->childs[0],leaves); - extractLeaves(node->childs[1],leaves); + extractLeaves(node->childs[0],leaves); + extractLeaves(node->childs[1],leaves); } else { - leaves.push_back(node); + leaves.push_back(node); } } @@ -657,19 +663,19 @@ q6600,2.4ghz /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 +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) +[7] btDbvt::rayTest: 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) @@ -684,606 +690,606 @@ Benchmarking dbvt... struct btDbvtBenchmark { -struct NilPolicy : btDbvt::ICollide + 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) + 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) + ++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; + int m_pcount; + btScalar m_depth; + bool m_checksort; }; -struct P14 : btDbvt::ICollide + struct P14 : btDbvt::ICollide { - struct Node + struct Node { - const btDbvtNode* leaf; - btScalar depth; + const btDbvtNode* leaf; + btScalar depth; }; - void Process(const btDbvtNode* leaf,btScalar depth) + void Process(const btDbvtNode* leaf,btScalar depth) { - Node n; - n.leaf = leaf; - n.depth = depth; + Node n; + n.leaf = leaf; + n.depth = depth; } - static int sortfnc(const Node& a,const Node& b) + static int sortfnc(const Node& a,const Node& b) { - if(a.depthb.depth) return(-1); - return(0); + if(a.depthb.depth) return(-1); + return(0); } - btAlignedObjectArray m_nodes; + btAlignedObjectArray m_nodes; }; -struct P15 : btDbvt::ICollide + struct P15 : btDbvt::ICollide { - struct Node + struct Node { - const btDbvtNode* leaf; - btScalar depth; + const btDbvtNode* leaf; + btScalar depth; }; - void Process(const btDbvtNode* leaf) + void Process(const btDbvtNode* leaf) { - Node n; - n.leaf = leaf; - n.depth = dot(leaf->volume.Center(),m_axis); + Node n; + n.leaf = leaf; + n.depth = dot(leaf->volume.Center(),m_axis); } - static int sortfnc(const Node& a,const Node& b) + static int sortfnc(const Node& a,const Node& b) { - if(a.depthb.depth) return(-1); - return(0); + if(a.depthb.depth) return(-1); + return(0); } - btAlignedObjectArray m_nodes; - btVector3 m_axis; + btAlignedObjectArray m_nodes; + btVector3 m_axis; }; -static btScalar RandUnit() + static btScalar RandUnit() { - return(rand()/(btScalar)RAND_MAX); + return(rand()/(btScalar)RAND_MAX); } -static btVector3 RandVector3() + static btVector3 RandVector3() { - return(btVector3(RandUnit(),RandUnit(),RandUnit())); + return(btVector3(RandUnit(),RandUnit(),RandUnit())); } -static btVector3 RandVector3(btScalar cs) + static btVector3 RandVector3(btScalar cs) { - return(RandVector3()*cs-btVector3(cs,cs,cs)/2); + return(RandVector3()*cs-btVector3(cs,cs,cs)/2); } -static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es) + static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es) { - return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es)); + return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es)); } -static btTransform RandTransform(btScalar cs) + 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); + 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) + 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 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(cfgBenchmark5_Iterations); + for(int i=0;i transforms; - btDbvtBenchmark::NilPolicy policy; - transforms.resize(cfgBenchmark6_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 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; + 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)); + dbvt.update(const_cast(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); + 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) + if(cfgBenchmark10_Enable) {// Benchmark 10 - srand(380843); - btDbvt dbvt; - btAlignedObjectArray leaves; - btAlignedObjectArray vectors; - vectors.resize(cfgBenchmark10_Iterations); - for(int i=0;i 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 btVector3& d=vectors[j]; + btDbvtNode* l=const_cast(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); + 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) + 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 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::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::P14 policy; + vectors.resize(cfgBenchmark14_Iterations); + for(int i=0;i vectors; - btDbvtBenchmark::P15 policy; - vectors.resize(cfgBenchmark15_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 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 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 +#ifdef WIN32 +#if (defined (_MSC_VER) && _MSC_VER >= 1400) +#define DBVT_USE_TEMPLATE 1 +#else +#define DBVT_USE_TEMPLATE 0 #endif #else #define DBVT_USE_TEMPLATE 0 @@ -52,16 +53,11 @@ subject to the following restrictions: // 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 +//SSE gives errors on a MSVC 7.1 +#ifdef BT_USE_SSE #define DBVT_SELECT_IMPL DBVT_IMPL_SSE #define DBVT_MERGE_IMPL DBVT_IMPL_SSE #define DBVT_INT0_IMPL DBVT_IMPL_SSE @@ -86,7 +82,7 @@ subject to the following restrictions: #define DBVT_VIRTUAL_DTOR(a) #define DBVT_PREFIX template #define DBVT_IPOLICY T& policy -#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)0; +#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker; #else #define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} #define DBVT_VIRTUAL virtual @@ -133,46 +129,41 @@ subject to the following restrictions: /* 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); + 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 btVector3& b); + + 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; + DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const; private: -btVector3 mi,mx; + btVector3 mi,mx; }; // Types @@ -185,88 +176,94 @@ struct btDbvtNode 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; - }; + 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*,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 - }; - + SIMPLE_STACKSIZE = 64, + DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2 + }; + // Fields btDbvtNode* m_root; btDbvtNode* m_free; int m_lkhd; int m_leaves; unsigned m_opath; + + + btAlignedObjectArray m_stkStack; + + // Methods - btDbvt(); - ~btDbvt(); + btDbvt(); + ~btDbvt(); void clear(); bool empty() const { return(0==m_root); } void optimizeBottomUp(); @@ -274,95 +271,118 @@ struct btDbvt 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 update(btDbvtNode* leaf,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 +#if DBVT_ENABLE_BENCHMARK static void benchmark(); - #else +#else static void benchmark(){} - #endif +#endif // DBVT_IPOLICY must support ICollide policy/interface DBVT_PREFIX - static void enumNodes( const btDbvtNode* root, - DBVT_IPOLICY); + static void enumNodes( const btDbvtNode* root, + DBVT_IPOLICY); DBVT_PREFIX - static void enumLeaves( const btDbvtNode* root, - DBVT_IPOLICY); + static void enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY); DBVT_PREFIX - static void collideTT( const btDbvtNode* root0, - const btDbvtNode* root1, - DBVT_IPOLICY); + 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); + void collideTTpersistentStack( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY); +#if 0 DBVT_PREFIX - static void collideTT( const btDbvtNode* root0, - const btTransform& xform0, - const btDbvtNode* root1, - const btTransform& xform1, - DBVT_IPOLICY); + void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY); DBVT_PREFIX - static void collideTV( const btDbvtNode* root, - const btDbvtVolume& volume, - DBVT_IPOLICY); + void collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY); +#endif + DBVT_PREFIX - static void collideRAY( const btDbvtNode* root, - const btVector3& origin, - const btVector3& direction, - DBVT_IPOLICY); + void collideTV( const btDbvtNode* root, + const btDbvtVolume& volume, + DBVT_IPOLICY); + ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc) + ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time DBVT_PREFIX - static void collideKDOP(const btDbvtNode* root, - const btVector3* normals, - const btScalar* offsets, - int count, - DBVT_IPOLICY); + static void rayTest( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + DBVT_IPOLICY); + ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections + ///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts DBVT_PREFIX - static void collideOCL( const btDbvtNode* root, - const btVector3* normals, - const btScalar* offsets, - const btVector3& sortaxis, - int count, - DBVT_IPOLICY, - bool fullsort=true); + void rayTestInternal( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayDirectionInverse, + unsigned int signs[3], + btScalar lambda_max, + const btVector3& aabbMin, + const btVector3& aabbMax, + DBVT_IPOLICY) const; + DBVT_PREFIX - static void collideTU( const btDbvtNode* root, - DBVT_IPOLICY); + 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); } + return(h); + } static DBVT_INLINE int allocate( btAlignedObjectArray& ifree, - btAlignedObjectArray& stock, - const sStkNPS& value) - { + 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); } + { 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&) {} - }; +private: + btDbvt(const btDbvt&) {} +}; // // Inline's @@ -371,69 +391,69 @@ struct btDbvt // inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e) { -btDbvtAabbMm box; -box.mi=c-e;box.mx=c+e; -return(box); + 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))); + 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); + 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]); + if(e.x()>0) 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())&& + return( (mi.x()<=a.mi.x())&& (mi.y()<=a.mi.y())&& (mi.z()<=a.mi.z())&& (mx.x()>=a.mx.x())&& @@ -444,64 +464,64 @@ return( (mi.x()<=a.mi.x())&& // DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const { -btVector3 pi,px; -switch(s) + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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); + 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)); + 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) + for(int i=0;i<3;++i) { - if(d[i]<0) + 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) + 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); + 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())&& + 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())&& @@ -510,27 +530,13 @@ return( (a.mi.x()<=b.mx.x())&& #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) + const btVector3& b) { -return( (b.x()>=a.mi.x())&& + return( (b.x()>=a.mi.x())&& (b.y()>=a.mi.y())&& (b.z()>=a.mi.z())&& (b.x()<=a.mx.x())&& @@ -538,55 +544,40 @@ return( (b.x()>=a.mi.x())&& (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 btDbvtAabbMm& b) { -const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx); -return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z())); + 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) + 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 + static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; + ///@todo: the intrinsic version is 11% slower +#if DBVT_USE_INTRINSIC_SSE + + union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory + { + __m128 ssereg; + float floats[4]; + int ints[4]; + }; + __m128 omi(_mm_load_ps(o.mi)); omi=_mm_add_ps(omi,_mm_load_ps(o.mx)); __m128 ami(_mm_load_ps(a.mi)); @@ -600,74 +591,78 @@ static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7ffffff __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)); + __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]; + + btSSEUnion tmp; + tmp.ssereg = _mm_cmple_ss(bmi,ami); + return tmp.ints[0]&1; + +#else + ATTRIBUTE_ALIGNED16(__int32 r[1]); __asm - { + { mov eax,o - mov ecx,a - mov edx,b - movaps xmm0,[eax] + mov ecx,a + mov edx,b + movaps xmm0,[eax] movaps xmm5,mask - addps xmm0,[eax+16] + 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 - } + 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 +#endif #else -return(Proximity(o,a)b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i]; + if(a.mi[i]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) + const btDbvtAabbMm& b) { -return( (a.mi.x()!=b.mi.x())|| + 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())|| @@ -682,235 +677,383 @@ return( (a.mi.x()!=b.mi.x())|| // DBVT_PREFIX inline void btDbvt::enumNodes( const btDbvtNode* root, - DBVT_IPOLICY) + DBVT_IPOLICY) { -DBVT_CHECKTYPE -policy.Process(root); -if(root->isinternal()) + DBVT_CHECKTYPE + policy.Process(root); + if(root->isinternal()) { - enumNodes(root->childs[0],policy); - enumNodes(root->childs[1],policy); + enumNodes(root->childs[0],policy); + enumNodes(root->childs[1],policy); } } // DBVT_PREFIX inline void btDbvt::enumLeaves( const btDbvtNode* root, - DBVT_IPOLICY) + DBVT_IPOLICY) { -DBVT_CHECKTYPE -if(root->isinternal()) - { - enumLeaves(root->childs[0],policy); - enumLeaves(root->childs[1],policy); - } - else - { - policy.Process(root); - } + 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) + 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()) + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + btAlignedObjectArray stkStack; + stkStack.resize(DOUBLE_STACKSIZE); + stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=stkStack[--depth]; + if(depth>treshold) { - 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]); + stkStack.resize(stkStack.size()*2); + treshold=stkStack.size()-4; } - } - else if(Intersect(p.a->volume,p.b->volume)) - { - if(p.a->isinternal()) + if(p.a==p.b) { - if(p.b->isinternal()) + if(p.a->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]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); + stkStack[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()) + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } } else { - stack[depth++]=sStkNN(p.a->childs[0],p.b); - stack[depth++]=sStkNN(p.a->childs[1],p.b); + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,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); - } + } while(depth); + } } + + +DBVT_PREFIX +inline void btDbvt::collideTTpersistentStack( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + + m_stkStack.resize(DOUBLE_STACKSIZE); + m_stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=m_stkStack[--depth]; + if(depth>treshold) + { + m_stkStack.resize(m_stkStack.size()*2); + treshold=m_stkStack.size()-4; + } + if(p.a==p.b) + { + if(p.a->isinternal()) + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); + m_stkStack[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()) + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + +#if 0 // DBVT_PREFIX inline void btDbvt::collideTT( const btDbvtNode* root0, - const btDbvtNode* root1, - const btTransform& xform, - DBVT_IPOLICY) + 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) + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + btAlignedObjectArray stkStack; + stkStack.resize(DOUBLE_STACKSIZE); + stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=stkStack[--depth]; + if(Intersect(p.a->volume,p.b->volume,xform)) { - 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]); + if(depth>treshold) + { + stkStack.resize(stkStack.size()*2); + treshold=stkStack.size()-4; + } + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } } else { - stack[depth++]=sStkNN(p.a->childs[0],p.b); - stack[depth++]=sStkNN(p.a->childs[1],p.b); + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,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); - } + } while(depth); + } } - // DBVT_PREFIX inline void btDbvt::collideTT( const btDbvtNode* root0, - const btTransform& xform0, - const btDbvtNode* root1, - const btTransform& xform1, - DBVT_IPOLICY) + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY) { -const btTransform xform=xform0.inverse()*xform1; -collideTT(root0,root1,xform,policy); + const btTransform xform=xform0.inverse()*xform1; + collideTT(root0,root1,xform,policy); } +#endif // DBVT_PREFIX inline void btDbvt::collideTV( const btDbvtNode* root, - const btDbvtVolume& vol, - DBVT_IPOLICY) + 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()) + DBVT_CHECKTYPE + if(root) + { + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); + btAlignedObjectArray stack; + stack.resize(0); + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(n->volume,volume)) { - stack.push_back(n->childs[0]); - stack.push_back(n->childs[1]); + 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::rayTestInternal( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayDirectionInverse, + unsigned int signs[3], + btScalar lambda_max, + const btVector3& aabbMin, + const btVector3& aabbMax, + DBVT_IPOLICY) const +{ + DBVT_CHECKTYPE + if(root) + { + btVector3 resultNormal; + + int depth=1; + int treshold=DOUBLE_STACKSIZE-2; + btAlignedObjectArray stack; + stack.resize(DOUBLE_STACKSIZE); + stack[0]=root; + btVector3 bounds[2]; + do + { + const btDbvtNode* node=stack[--depth]; + bounds[0] = node->volume.Mins()+aabbMin; + bounds[1] = node->volume.Maxs()+aabbMax; + btScalar tmin=1.f,lambda_min=0.f; + unsigned int result1=false; + result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max); + if(result1) + { + if(node->isinternal()) + { + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-2; + } + stack[depth++]=node->childs[0]; + stack[depth++]=node->childs[1]; } else { - policy.Process(n); + policy.Process(node); } } - } while(stack.size()>0); + } while(depth); } } // DBVT_PREFIX -inline void btDbvt::collideRAY( const btDbvtNode* root, - const btVector3& origin, - const btVector3& direction, - DBVT_IPOLICY) +inline void btDbvt::rayTest( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + 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()) + DBVT_CHECKTYPE + if(root) + { + btVector3 rayDir = (rayTo-rayFrom); + rayDir.normalize (); + + ///what about division by zero? --> just set rayDirection[i] to INF/1e30 + btVector3 rayDirectionInverse; + rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; + rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; + rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; + unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0}; + + btScalar lambda_max = rayDir.dot(rayTo-rayFrom); + + btVector3 resultNormal; + + btAlignedObjectArray stack; + + int depth=1; + int treshold=DOUBLE_STACKSIZE-2; + + stack.resize(DOUBLE_STACKSIZE); + stack[0]=root; + btVector3 bounds[2]; + do { + const btDbvtNode* node=stack[--depth]; + + bounds[0] = node->volume.Mins(); + bounds[1] = node->volume.Maxs(); + + btScalar tmin=1.f,lambda_min=0.f; + unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max); + +#ifdef COMPARE_BTRAY_AABB2 + btScalar param=1.f; + bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal); + btAssert(result1 == result2); +#endif //TEST_BTRAY_AABB2 + + if(result1) { - stack.push_back(node->childs[0]); - stack.push_back(node->childs[1]); + if(node->isinternal()) + { + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-2; + } + stack[depth++]=node->childs[0]; + stack[depth++]=node->childs[1]; + } + else + { + policy.Process(node); + } } - else - { - policy.Process(node); - } - } - } while(stack.size()); - } + } while(depth); + + } } // @@ -921,174 +1064,174 @@ inline void btDbvt::collideKDOP(const btDbvtNode* root, int count, DBVT_IPOLICY) { -DBVT_CHECKTYPE -if(root) - { - const int inside=(1< stack; - int signs[sizeof(unsigned)*8]; - btAssert(count=0)?1:0)+ + 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.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)&&(ichilds[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) + const int side=se.node->volume.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()) + if(!out) { - 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)) + if((se.mask!=inside)&&(se.node->isinternal())) { - /* 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]); + stack.push_back(sStkNP(se.node->childs[0],se.mask)); + stack.push_back(sStkNP(se.node->childs[1],se.mask)); } else { - stack.push_back(allocate(ifree,stock,nes[q])); - stack.push_back(allocate(ifree,stock,nes[1-q])); + if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); } } - else - { - policy.Process(se.node,se.value); - } + } 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); } - } while(stack.size()); - } + 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_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); - } + 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); + } } // diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp index e00fc6aa5e3..f231717af17 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp @@ -26,19 +26,19 @@ subject to the following restrictions: #if DBVT_BP_PROFILE struct ProfileScope - { +{ __forceinline ProfileScope(btClock& clock,unsigned long& value) : - m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds()) - { - } + 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_) @@ -52,35 +52,35 @@ struct ProfileScope 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; + 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]; + 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); + 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; + static const struct ZeroDummy : T {} zerodummy; + value=zerodummy; } // @@ -90,25 +90,26 @@ value=zerodummy; /* Tree collider */ struct btDbvtTreeCollider : btDbvt::ICollide { -btDbvtBroadphase* pbp; -btDbvtProxy* proxy; - btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} -void Process(const btDbvtNode* na,const btDbvtNode* nb) + btDbvtBroadphase* pbp; + btDbvtProxy* proxy; + btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} + void Process(const btDbvtNode* na,const btDbvtNode* nb) { - if(na!=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; + btDbvtProxy* pa=(btDbvtProxy*)na->data; + btDbvtProxy* pb=(btDbvtProxy*)nb->data; +#if DBVT_BP_SORTPAIRS + if(pa->m_uniqueId>pb->m_uniqueId) + btSwap(pa,pb); +#endif + pbp->m_paircache->addOverlappingPair(pa,pb); + ++pbp->m_newpairs; } } -void Process(const btDbvtNode* n) + void Process(const btDbvtNode* n) { - Process(n,proxy->leaf); + Process(n,proxy->leaf); } }; @@ -119,147 +120,197 @@ void Process(const btDbvtNode* n) // 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_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; + m_stageRoots[i]=0; } #if DBVT_BP_PROFILE -clear(m_profiling); + clear(m_profiling); #endif } // btDbvtBroadphase::~btDbvtBroadphase() { -if(m_releasepaircache) -{ - m_paircache->~btOverlappingPairCache(); - btAlignedFree(m_paircache); -} + 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*/) + 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) + btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr, + collisionFilterGroup, + collisionFilterMask); + + btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); + + //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); + proxy->stage = m_stageCurrent; + proxy->m_uniqueId = ++m_gid; + proxy->leaf = m_sets[0].insert(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); - btDbvt::collideTV(m_sets[1].m_root,proxy->aabb,collider); + btDbvtTreeCollider collider(this); + collider.proxy=proxy; + m_sets[0].collideTV(m_sets[0].m_root,aabb,collider); + m_sets[1].collideTV(m_sets[1].m_root,aabb,collider); } -return(proxy); + return(proxy); } // void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy, - btDispatcher* dispatcher) + btDispatcher* dispatcher) { -btDbvtProxy* proxy=(btDbvtProxy*)absproxy; -if(proxy->stage==STAGECOUNT) - m_sets[1].remove(proxy->leaf); + 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; + m_sets[0].remove(proxy->leaf); + listremove(proxy,m_stageRoots[proxy->stage]); + m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher); + btAlignedFree(proxy); + m_needcleanup=true; +} + +void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + aabbMin = proxy->m_aabbMin; + aabbMax = proxy->m_aabbMax; +} + +struct BroadphaseRayTester : btDbvt::ICollide +{ + btBroadphaseRayCallback& m_rayCallback; + BroadphaseRayTester(btBroadphaseRayCallback& orgCallback) + :m_rayCallback(orgCallback) + { + } + void Process(const btDbvtNode* leaf) + { + btDbvtProxy* proxy=(btDbvtProxy*)leaf->data; + m_rayCallback.process(proxy); + } +}; + +void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) +{ + BroadphaseRayTester callback(rayCallback); + + m_sets[0].rayTestInternal( m_sets[0].m_root, + rayFrom, + rayTo, + rayCallback.m_rayDirectionInverse, + rayCallback.m_signs, + rayCallback.m_lambda_max, + aabbMin, + aabbMax, + callback); + + m_sets[1].rayTestInternal( m_sets[1].m_root, + rayFrom, + rayTo, + rayCallback.m_rayDirectionInverse, + rayCallback.m_signs, + rayCallback.m_lambda_max, + aabbMin, + aabbMax, + callback); + } // void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy, - const btVector3& aabbMin, - const btVector3& aabbMax, - btDispatcher* /*dispatcher*/) + const btVector3& aabbMin, + const btVector3& aabbMax, + btDispatcher* /*dispatcher*/) { -btDbvtProxy* proxy=(btDbvtProxy*)absproxy; -ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); #if DBVT_BP_PREVENTFALSEUPDATE -if(NotEqual(aabb,proxy->leaf->volume)) + if(NotEqual(aabb,proxy->leaf->volume)) #endif { - bool docollide=false; - if(proxy->stage==STAGECOUNT) + 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; + 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)) + ++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 - ) + + const btVector3 delta=aabbMin-proxy->m_aabbMin; + btVector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*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; + ++m_updates_done; + docollide=true; } } else {/* Teleporting */ - m_sets[0].update(proxy->leaf,aabb); - ++m_updates_done; - docollide=true; + 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) + listremove(proxy,m_stageRoots[proxy->stage]); + proxy->m_aabbMin = aabbMin; + proxy->m_aabbMax = aabbMax; + proxy->stage = m_stageCurrent; + listappend(proxy,m_stageRoots[m_stageCurrent]); + if(docollide) { - m_needcleanup=true; - if(!m_deferedcollide) + 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); + btDbvtTreeCollider collider(this); + m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider); } } } @@ -268,132 +319,226 @@ if(NotEqual(aabb,proxy->leaf->volume)) // void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) { -collide(dispatcher); + collide(dispatcher); #if DBVT_BP_PROFILE -if(0==(m_pid%DBVT_BP_PROFILING_RATE)) + 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(); + 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 + + performDeferredRemoval(dispatcher); + +} + +void btDbvtBroadphase::performDeferredRemoval(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()); + + int invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;ileaf->volume,pb->leaf->volume); + + if (hasOverlap) + { + needsRemoval = false; + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_paircache->cleanOverlappingPair(pair,dispatcher); + + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + invalidPair++; + } + + } + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + overlappingPairArray.resize(overlappingPairArray.size() - invalidPair); + } } // 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) + /*printf("---------------------------------------------------------\n"); + printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves); + printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves); + printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs()); { - 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); + int i; + for (i=0;igetNumOverlappingPairs();i++) + { + printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(), + getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid()); + } + printf("\n"); } -/* dynamic -> fixed set */ -m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; -btDbvtProxy* current=m_stageRoots[m_stageCurrent]; -if(current) +*/ + + + + SPC(m_profiling.m_total); + /* optimize */ + m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); + if(m_fixedleft) { - 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; + 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); + ATTRIBUTE_ALIGNED16(btDbvtVolume) curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax); + current->leaf = m_sets[1].insert(curAabb,current); + current->stage = STAGECOUNT; + current = next; } while(current); - m_fixedleft=m_sets[1].m_leaves; - m_needcleanup=true; + m_fixedleft=m_sets[1].m_leaves; + m_needcleanup=true; } -/* collide dynamics */ + /* collide dynamics */ { - btDbvtTreeCollider collider(this); - if(m_deferedcollide) + btDbvtTreeCollider collider(this); + if(m_deferedcollide) { - SPC(m_profiling.m_fdcollide); - btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider); + SPC(m_profiling.m_fdcollide); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider); } - if(m_deferedcollide) + if(m_deferedcollide) { - SPC(m_profiling.m_ddcollide); - btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider); + SPC(m_profiling.m_ddcollide); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider); } } -/* clean up */ -if(m_needcleanup) + /* clean up */ + if(m_needcleanup) { - SPC(m_profiling.m_cleanup); - btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray(); - if(pairs.size()>0) + 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;i(m_newpairs,(pairs.size()*m_cupdates)/100)); + for(int i=0;ileaf->volume,pb->leaf->volume)) + btBroadphasePair& p=pairs[(m_cid+i)%pairs.size()]; + btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0; + btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1; + if(!Intersect(pa->leaf->volume,pb->leaf->volume)) { - #if DBVT_BP_SORTPAIRS - if(pa>pb) btSwap(pa,pb); - #endif - m_paircache->removeOverlappingPair(pa,pb,dispatcher); - --ni;--i; +#if DBVT_BP_SORTPAIRS + if(pa->m_uniqueId>pb->m_uniqueId) + 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; + 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_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; + m_updates_done/=2; + m_updates_call/=2; } // void btDbvtBroadphase::optimize() { -m_sets[0].optimizeTopDown(); -m_sets[1].optimizeTopDown(); + m_sets[0].optimizeTopDown(); + m_sets[1].optimizeTopDown(); } // btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() { -return(m_paircache); + return(m_paircache); } // const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const { -return(m_paircache); + return(m_paircache); } // @@ -402,16 +547,49 @@ void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aab 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(); + 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::resetPool(btDispatcher* dispatcher) +{ + + int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves; + if (!totalObjects) + { + //reset internal dynamic tree data structures + m_sets[0].clear(); + m_sets[1].clear(); + + m_deferedcollide = false; + m_needcleanup = 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_gid = 0; + m_pid = 0; + m_cid = 0; + for(int i=0;i<=STAGECOUNT;++i) + { + m_stageRoots[i]=0; + } + } } // @@ -422,9 +600,9 @@ void btDbvtBroadphase::printStats() #if DBVT_BP_ENABLE_BENCHMARK struct btBroadphaseBenchmark - { +{ struct Experiment - { + { const char* name; int object_count; int update_count; @@ -432,109 +610,109 @@ struct btBroadphaseBenchmark 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; + btSin(time)*amplitude/2; center[1] = btCos(time*(btScalar)1.38)*amplitude+ - btSin(time)*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 + else printf("%s : %u us (%u ms)\r\n",name,us,ms); - } - }; + } +}; void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi) { -static const btBroadphaseBenchmark::Experiment experiments[]= + 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},*/ + {"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;iexp 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::Object* po=new btBroadphaseBenchmark::Object(); + po->center[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); + objects[i]->update(speed,amplitude,pbi); } - btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock); - /* Updates */ - wallclock.reset(); - for(int i=0;iupdate(speed,amplitude,pbi); + objects[j]->update(speed,amplitude,pbi); } - pbi->calculateOverlappingPairs(0); + 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]; + pbi->destroyProxy(objects[i]->proxy,0); + delete objects[i]; } - objects.resize(0); - btBroadphaseBenchmark::OutputTime("\tRelease",wallclock); + objects.resize(0); + btBroadphaseBenchmark::OutputTime("\tRelease",wallclock); } } @@ -546,3 +724,4 @@ void btDbvtBroadphase::benchmark(btBroadphaseInterface*) #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 index 1f16043a7a8..fe70bc39c43 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h @@ -24,15 +24,15 @@ subject to the following restrictions: // #define DBVT_BP_PROFILE 0 -#define DBVT_BP_SORTPAIRS 1 +//#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" +#define DBVT_BP_PROFILING_RATE 256 +#include "LinearMath/btQuickprof.h" #endif // @@ -40,16 +40,16 @@ subject to the following restrictions: // 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) + /* Fields */ + //btDbvtAabbMm aabb; + btDbvtNode* leaf; + btDbvtProxy* links[2]; + int stage; + /* ctor */ + btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : + btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask) { - links[0]=links[1]=0; + links[0]=links[1]=0; } }; @@ -60,57 +60,67 @@ typedef btAlignedObjectArray btDbvtProxyArray; ///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 { + /* 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? + }; + /* 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? #if DBVT_BP_PROFILE -btClock m_clock; -struct { + 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; + } 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*); + /* 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); + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)); + + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + void calculateOverlappingPairs(btDispatcher* dispatcher); + btOverlappingPairCache* getOverlappingPairCache(); + const btOverlappingPairCache* getOverlappingPairCache() const; + void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; + void printStats(); + static void benchmark(btBroadphaseInterface*); + + + void performDeferredRemoval(btDispatcher* dispatcher); + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + }; #endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h index 6db71a0170e..ee57aa96151 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -46,22 +46,25 @@ struct btDispatcherInfo m_enableSPU(true), m_useEpa(true), m_allowedCcdPenetration(btScalar(0.04)), + m_useConvexConservativeDistanceUtil(true), + m_convexConservativeDistanceThreshold(0.0f), m_stackAllocator(0) { } btScalar m_timeStep; - int m_stepCount; - int m_dispatchFunc; + int m_stepCount; + int m_dispatchFunc; mutable btScalar m_timeOfImpact; - bool m_useContinuous; + bool m_useContinuous; class btIDebugDraw* m_debugDraw; - bool m_enableSatConvex; - bool m_enableSPU; - bool m_useEpa; + bool m_enableSatConvex; + bool m_enableSPU; + bool m_useEpa; btScalar m_allowedCcdPenetration; + bool m_useConvexConservativeDistanceUtil; + btScalar m_convexConservativeDistanceThreshold; btStackAlloc* m_stackAllocator; - }; ///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs. diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp index 3f866ab7c5f..6712f528e97 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp @@ -149,6 +149,22 @@ amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ(); +void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + btMultiSapProxy* multiProxy = static_cast(proxy); + aabbMin = multiProxy->m_aabbMin; + aabbMax = multiProxy->m_aabbMax; +} + +void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) +{ + for (int i=0;i void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) @@ -208,7 +224,9 @@ void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aab - m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + if (m_optimizedAabbTree) + m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + int i; for ( i=0;im_bridgeProxies.size();i++) @@ -464,3 +482,8 @@ void btMultiSapBroadphase::printStats() */ } + +void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher) +{ + // not yet +} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h index a0c002de856..91c504eee22 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h @@ -26,6 +26,7 @@ class btSimpleBroadphase; typedef btAlignedObjectArray btSapBroadphaseArray; +///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead. ///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. @@ -72,7 +73,7 @@ public: 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), + :btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask), m_aabbMin(aabbMin), m_aabbMax(aabbMax), m_shapeType(shapeType) @@ -108,6 +109,9 @@ public: 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); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase); @@ -139,6 +143,9 @@ public: void quicksort (btBroadphasePairArray& a, int lo, int hi); + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + }; #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..b209bcb9a20 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -19,6 +19,7 @@ subject to the following restrictions: #include "btDispatcher.h" #include "btCollisionAlgorithm.h" +#include "LinearMath/btAabbUtil2.h" #include @@ -33,7 +34,8 @@ int gFindPairs =0; btHashedOverlappingPairCache::btHashedOverlappingPairCache(): m_overlapFilterCallback(0), - m_blockedForChanges(false) + m_blockedForChanges(false), + m_ghostPairCallback(0) { int initialAllocatedSize= 2; m_overlappingPairArray.reserve(initialAllocatedSize); @@ -45,7 +47,6 @@ btHashedOverlappingPairCache::btHashedOverlappingPairCache(): btHashedOverlappingPairCache::~btHashedOverlappingPairCache() { - //todo/test: show we erase/delete data, or is it automatic } @@ -135,7 +136,8 @@ void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroad btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) { gFindPairs++; - if(proxy0>proxy1) btSwap(proxy0,proxy1); + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); int proxyId1 = proxy0->getUid(); int proxyId2 = proxy1->getUid(); @@ -211,7 +213,8 @@ void btHashedOverlappingPairCache::growTables() btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) { - if(proxy0>proxy1) btSwap(proxy0,proxy1); + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); int proxyId1 = proxy0->getUid(); int proxyId2 = proxy1->getUid(); @@ -238,6 +241,11 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx int count = m_overlappingPairArray.size(); int oldCapacity = m_overlappingPairArray.capacity(); void* mem = &m_overlappingPairArray.expand(); + + //this is where we add an actual pair, so also call the 'ghost' + if (m_ghostPairCallback) + m_ghostPairCallback->addOverlappingPair(proxy0,proxy1); + int newCapacity = m_overlappingPairArray.capacity(); if (oldCapacity < newCapacity) @@ -251,7 +259,7 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx // pair->m_pProxy0 = proxy0; // pair->m_pProxy1 = proxy1; pair->m_algorithm = 0; - pair->m_userInfo = 0; + pair->m_internalTmpValue = 0; m_next[count] = m_hashTable[hash]; @@ -265,7 +273,8 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) { gRemovePairs++; - if(proxy0>proxy1) btSwap(proxy0,proxy1); + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); int proxyId1 = proxy0->getUid(); int proxyId2 = proxy1->getUid(); @@ -282,7 +291,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro cleanOverlappingPair(*pair,dispatcher); - void* userData = pair->m_userInfo; + void* userData = pair->m_internalInfo1; btAssert(pair->m_pProxy0->getUid() == proxyId1); btAssert(pair->m_pProxy1->getUid() == proxyId2); @@ -317,6 +326,9 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro int lastPairIndex = m_overlappingPairArray.size() - 1; + if (m_ghostPairCallback) + m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher); + // If the removed pair is the last pair, we are done. if (lastPairIndex == pairIndex) { @@ -384,6 +396,35 @@ void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* } } +void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) +{ + ///need to keep hashmap in sync with pair address, so rebuild all + btBroadphasePairArray tmpPairs; + int i; + for (i=0;iremoveOverlappingPair(proxy0, proxy1,dispatcher); m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); m_overlappingPairArray.pop_back(); @@ -419,15 +462,19 @@ void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) { //don't add overlap with own - assert(proxy0 != proxy1); + btAssert(proxy0 != proxy1); if (!needsBroadphaseCollision(proxy0,proxy1)) return 0; void* mem = &m_overlappingPairArray.expand(); btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); + gOverlappingPairs++; gAddedPairs++; + + if (m_ghostPairCallback) + m_ghostPairCallback->addOverlappingPair(proxy0, proxy1); return pair; } @@ -446,7 +493,7 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP if (findIndex < m_overlappingPairArray.size()) { - //assert(it != m_overlappingPairSet.end()); + //btAssert(it != m_overlappingPairSet.end()); btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; return pair; } @@ -476,8 +523,9 @@ void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* if (callback->processOverlap(*pair)) { cleanOverlappingPair(*pair,dispatcher); - - m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1); + pair->m_pProxy0 = 0; + pair->m_pProxy1 = 0; + m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); m_overlappingPairArray.pop_back(); gOverlappingPairs--; } else @@ -493,7 +541,8 @@ void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* btSortedOverlappingPairCache::btSortedOverlappingPairCache(): m_blockedForChanges(false), m_hasDeferredRemoval(true), - m_overlapFilterCallback(0) + m_overlapFilterCallback(0), + m_ghostPairCallback(0) { int initialAllocatedSize= 2; m_overlappingPairArray.reserve(initialAllocatedSize); @@ -501,7 +550,6 @@ btSortedOverlappingPairCache::btSortedOverlappingPairCache(): btSortedOverlappingPairCache::~btSortedOverlappingPairCache() { - //todo/test: show we erase/delete data, or is it automatic } void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) @@ -577,3 +625,9 @@ void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroad processAllOverlappingPairs(&removeCallback,dispatcher); } + +void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) +{ + //should already be sorted +} + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index 66679bd218a..eda45c47b5b 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -21,7 +21,6 @@ subject to the following restrictions: #include "btBroadphaseProxy.h" #include "btOverlappingPairCallback.h" -#include "LinearMath/btPoint3.h" #include "LinearMath/btAlignedObjectArray.h" class btDispatcher; @@ -83,6 +82,11 @@ public: virtual bool hasDeferredRemoval() = 0; + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0; + + virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0; + + }; /// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com @@ -253,10 +257,19 @@ private: return false; } -public: + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + m_ghostPairCallback = ghostPairCallback; + } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher); + + +protected: btAlignedObjectArray m_hashTable; btAlignedObjectArray m_next; + btOverlappingPairCallback* m_ghostPairCallback; }; @@ -280,6 +293,8 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache //if set, use the callback instead of the built in filter in needBroadphaseCollision btOverlapFilterCallback* m_overlapFilterCallback; + btOverlappingPairCallback* m_ghostPairCallback; + public: btSortedOverlappingPairCache(); @@ -355,12 +370,19 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache return m_hasDeferredRemoval; } + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + m_ghostPairCallback = ghostPairCallback; + } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher); + }; -///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing. +///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing. class btNullPairCache : public btOverlappingPairCache { @@ -414,6 +436,11 @@ public: return true; } + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */) + { + + } + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) { return 0; @@ -427,6 +454,10 @@ public: virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) { } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher) + { + } }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp index a30bd1fd9e1..8bef8f0d43e 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp @@ -18,14 +18,18 @@ subject to the following restrictions: #include "LinearMath/btAabbUtil2.h" #include "LinearMath/btIDebugDraw.h" +#define RAYAABB2 -btQuantizedBvh::btQuantizedBvh() : m_useQuantization(false), +btQuantizedBvh::btQuantizedBvh() : + m_bulletVersion(BT_BULLET_VERSION), + m_useQuantization(false), //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) m_traversalMode(TRAVERSAL_STACKLESS) //m_traversalMode(TRAVERSAL_RECURSIVE) ,m_subtreeHeaderCount(0) //PCK: add this line -{ - +{ + m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY); + m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY); } @@ -119,7 +123,7 @@ void btQuantizedBvh::buildTree (int startIndex,int endIndex) int numIndices =endIndex-startIndex; int curIndex = m_curNodeIndex; - assert(numIndices>0); + btAssert(numIndices>0); if (numIndices==1) { @@ -140,8 +144,11 @@ void btQuantizedBvh::buildTree (int startIndex,int endIndex) int internalNodeIndex = m_curNodeIndex; - setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin); - setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax); + //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value. + //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values + setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization + setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization + for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); @@ -434,6 +445,96 @@ void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantize +void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const +{ + btAssert(!m_useQuantization); + + const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0]; + int escapeIndex, curIndex = 0; + int walkIterations = 0; + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap=0; + unsigned rayBoxOverlap=0; + btScalar lambda_max = 1.0; + + /* 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; + +#ifdef RAYAABB2 + btVector3 rayDir = (rayTarget-raySource); + rayDir.normalize (); + lambda_max = rayDir.dot(rayTarget-raySource); + ///what about division by zero? --> just set rayDirection[i] to 1.0 + btVector3 rayDirectionInverse; + rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; + rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; + rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; + unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0}; +#endif + + btVector3 bounds[2]; + + while (curIndex < m_curNodeIndex) + { + btScalar param = 1.0; + //catch bugs in tree data + btAssert (walkIterations < m_curNodeIndex); + + walkIterations++; + + bounds[0] = rootNode->m_aabbMinOrg; + bounds[1] = rootNode->m_aabbMaxOrg; + /* Add box cast extents */ + bounds[0] += aabbMin; + bounds[1] += aabbMax; + + aabbOverlap = TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg); + //perhaps profile if it is worth doing the aabbOverlap test first + +#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 = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false; + +#else + btVector3 normal; + rayBoxOverlap = btRayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal); +#endif + + isLeafNode = rootNode->m_escapeIndex == -1; + + //PCK: unsigned instead of bool + if (isLeafNode && (rayBoxOverlap != 0)) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + //PCK: unsigned instead of bool + if ((rayBoxOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const @@ -454,9 +555,8 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* 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); @@ -502,7 +602,7 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* #endif//VISUALLY_ANALYZE_BVH //catch bugs in tree data - assert (walkIterations < subTreeSize); + btAssert (walkIterations < subTreeSize); walkIterations++; //PCK: unsigned instead of bool @@ -533,7 +633,9 @@ void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* ///thanks Joerg/hiker for the reproduction case! ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 + //BT_PROFILE("btRayAabb2"); rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max); + #else rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal); #endif @@ -597,7 +699,7 @@ void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallb #endif//VISUALLY_ANALYZE_BVH //catch bugs in tree data - assert (walkIterations < subTreeSize); + btAssert (walkIterations < subTreeSize); walkIterations++; //PCK: unsigned instead of bool @@ -652,30 +754,25 @@ void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallba 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); - } + reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,btVector3(0,0,0),btVector3(0,0,0)); } 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) + //always use stackless + + if (m_useQuantization) { 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 */ + } + else + { + walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex); + } + /* + { + //recursive traversal btVector3 qaabbMin = raySource; btVector3 qaabbMax = raySource; qaabbMin.setMin(rayTarget); @@ -684,6 +781,8 @@ void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCa qaabbMax += aabbMax; reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax); } + */ + } @@ -716,17 +815,19 @@ void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNod //PCK: include #include +#if 0 //PCK: consts static const unsigned BVH_ALIGNMENT = 16; static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1; static const unsigned BVH_ALIGNMENT_BLOCKS = 2; - +#endif unsigned int btQuantizedBvh::getAlignmentSerializationPadding() { - return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; + // I changed this to 0 since the extra padding is not needed or used. + return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; } unsigned btQuantizedBvh::calculateSerializeBufferSize() @@ -742,7 +843,7 @@ unsigned btQuantizedBvh::calculateSerializeBufferSize() bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) { - assert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); + btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); m_subtreeHeaderCount = m_SubtreeHeaders.size(); /* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) @@ -829,6 +930,11 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe } } nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0); } else { @@ -859,6 +965,11 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe } } nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0); } sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; @@ -896,12 +1007,23 @@ bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBuffe 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]; + + // need to clear padding in destination buffer + targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0; + targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0; + targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0; } } - nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0); + + // this wipes the virtual function table pointer at the start of the buffer for the class + *((void**)o_alignedDataBuffer) = NULL; + return true; } @@ -1015,11 +1137,12 @@ btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, un btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) : m_bvhAabbMin(self.m_bvhAabbMin), m_bvhAabbMax(self.m_bvhAabbMax), -m_bvhQuantization(self.m_bvhQuantization) +m_bvhQuantization(self.m_bvhQuantization), +m_bulletVersion(BT_BULLET_VERSION) { - } + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h index 8a149b533fa..ced457b6036 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h @@ -158,41 +158,43 @@ typedef btAlignedObjectArray BvhSubtreeInfoArray; ///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; + + btVector3 m_bvhAabbMin; + btVector3 m_bvhAabbMax; + btVector3 m_bvhQuantization; + + int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess. + + int m_curNodeIndex; + //quantization data + bool m_useQuantization; + + + + NodeArray m_leafNodes; + NodeArray m_contiguousNodes; + QuantizedNodeArray m_quantizedLeafNodes; + QuantizedNodeArray m_quantizedContiguousNodes; + 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 @@ -296,6 +298,7 @@ protected: 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; + void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, 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; @@ -307,30 +310,14 @@ protected: 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: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + btQuantizedBvh(); virtual ~btQuantizedBvh(); @@ -363,7 +350,7 @@ public: 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 + ///@todo: double-check this if (isMax) { out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1)); diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp index a57952ffa06..caed63db005 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -55,6 +55,7 @@ btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* o m_maxHandles = maxProxies; m_numHandles = 0; m_firstFreeHandle = 0; + m_LastHandleIndex = -1; { @@ -88,7 +89,7 @@ btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, btAssert(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]); + btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); int newHandleIndex = allocHandle(); btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); @@ -137,14 +138,32 @@ void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* } +void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); + aabbMin = sbp->m_aabbMin; + aabbMax = sbp->m_aabbMax; +} + void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/) { btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); - sbp->m_min = aabbMin; - sbp->m_max = aabbMax; + sbp->m_aabbMin = aabbMin; + sbp->m_aabbMax = aabbMax; } - +void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) +{ + for (int i=0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy = &m_pHandles[i]; + if(!proxy->m_clientObject) + { + continue; + } + rayCallback.process(proxy); + } +} @@ -154,9 +173,9 @@ void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbM bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1) { - return proxy0->m_min[0] <= proxy1->m_max[0] && proxy1->m_min[0] <= proxy0->m_max[0] && - proxy0->m_min[1] <= proxy1->m_max[1] && proxy1->m_min[1] <= proxy0->m_max[1] && - proxy0->m_min[2] <= proxy1->m_max[2] && proxy1->m_min[2] <= proxy0->m_max[2]; + return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] && + proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] && + proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2]; } @@ -176,18 +195,25 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) { //first check for new overlapping pairs int i,j; - if (m_numHandles >= 0) { - - for (i=0;im_clientObject) + { + continue; + } + new_largest_index = i; + for (j=i+1; j <= m_LastHandleIndex; j++) { btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j]; btAssert(proxy0 != proxy1); + if(!proxy1->m_clientObject) + { + continue; + } btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); @@ -211,6 +237,8 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) } } + m_LastHandleIndex = new_largest_index; + if (m_ownsPairCache && m_pairCache->hasDeferredRemoval()) { @@ -296,5 +324,7 @@ bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseP return aabbOverlap(p0,p1); } - - +void btSimpleBroadphase::resetPool(btDispatcher* dispatcher) +{ + //not yet +} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h index e2ebb825725..cc7613bf6a0 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -22,8 +22,6 @@ subject to the following restrictions: struct btSimpleBroadphaseProxy : public btBroadphaseProxy { - btVector3 m_min; - btVector3 m_max; int m_nextFree; // int m_handleId; @@ -31,9 +29,8 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy 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), - m_min(minpt),m_max(maxpt) + btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) + :btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy) { (void)shapeType; } @@ -56,6 +53,7 @@ protected: int m_numHandles; // number of active handles int m_maxHandles; // max number of handles + int m_LastHandleIndex; btSimpleBroadphaseProxy* m_pHandles; // handles pool @@ -68,6 +66,10 @@ protected: int freeHandle = m_firstFreeHandle; m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); m_numHandles++; + if(freeHandle > m_LastHandleIndex) + { + m_LastHandleIndex = freeHandle; + } return freeHandle; } @@ -75,10 +77,15 @@ protected: { int handle = int(proxy-m_pHandles); btAssert(handle >= 0 && handle < m_maxHandles); - + if(handle == m_LastHandleIndex) + { + m_LastHandleIndex--; + } proxy->SetNextFree(m_firstFreeHandle); m_firstFreeHandle = handle; + proxy->m_clientObject = 0; + m_numHandles--; } @@ -95,6 +102,15 @@ protected: return proxy0; } + inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const + { + const btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); + return proxy0; + } + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + void validate(); @@ -117,6 +133,9 @@ public: virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); btOverlappingPairCache* getOverlappingPairCache() { diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt index d77ca6444c7..4b4304f43b0 100644 --- a/extern/bullet2/src/BulletCollision/CMakeLists.txt +++ b/extern/bullet2/src/BulletCollision/CMakeLists.txt @@ -1,153 +1,234 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src } +INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src } ) + +SET(BulletCollision_SRCS + BroadphaseCollision/btAxisSweep3.cpp + BroadphaseCollision/btBroadphaseProxy.cpp + BroadphaseCollision/btCollisionAlgorithm.cpp + BroadphaseCollision/btDispatcher.cpp + BroadphaseCollision/btDbvtBroadphase.cpp + BroadphaseCollision/btDbvt.cpp + BroadphaseCollision/btMultiSapBroadphase.cpp + BroadphaseCollision/btOverlappingPairCache.cpp + BroadphaseCollision/btQuantizedBvh.cpp + BroadphaseCollision/btSimpleBroadphase.cpp + CollisionDispatch/btActivatingCollisionAlgorithm.cpp + CollisionDispatch/btCollisionDispatcher.cpp + CollisionDispatch/btCollisionObject.cpp + CollisionDispatch/btCollisionWorld.cpp + CollisionDispatch/btCompoundCollisionAlgorithm.cpp + CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp + CollisionDispatch/btDefaultCollisionConfiguration.cpp + CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxDetector.cpp + CollisionDispatch/btGhostObject.cpp + CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp + CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp + CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp + CollisionDispatch/btConvexConvexAlgorithm.cpp + CollisionDispatch/btEmptyCollisionAlgorithm.cpp + CollisionDispatch/btManifoldResult.cpp + CollisionDispatch/btSimulationIslandManager.cpp + CollisionDispatch/btUnionFind.cpp + CollisionDispatch/SphereTriangleDetector.cpp + CollisionShapes/btBoxShape.cpp + CollisionShapes/btBvhTriangleMeshShape.cpp + CollisionShapes/btCapsuleShape.cpp + CollisionShapes/btCollisionShape.cpp + CollisionShapes/btCompoundShape.cpp + CollisionShapes/btConcaveShape.cpp + CollisionShapes/btConeShape.cpp + CollisionShapes/btConvexHullShape.cpp + CollisionShapes/btConvexPointCloudShape.cpp + CollisionShapes/btConvexShape.cpp + CollisionShapes/btConvexInternalShape.cpp + CollisionShapes/btConvexTriangleMeshShape.cpp + CollisionShapes/btCylinderShape.cpp + CollisionShapes/btEmptyShape.cpp + CollisionShapes/btHeightfieldTerrainShape.cpp + CollisionShapes/btMinkowskiSumShape.cpp + CollisionShapes/btMultimaterialTriangleMeshShape.cpp + CollisionShapes/btMultiSphereShape.cpp + CollisionShapes/btOptimizedBvh.cpp + CollisionShapes/btPolyhedralConvexShape.cpp + CollisionShapes/btScaledBvhTriangleMeshShape.cpp + CollisionShapes/btTetrahedronShape.cpp + CollisionShapes/btSphereShape.cpp + CollisionShapes/btShapeHull.cpp + CollisionShapes/btStaticPlaneShape.cpp + CollisionShapes/btStridingMeshInterface.cpp + CollisionShapes/btTriangleCallback.cpp + CollisionShapes/btTriangleBuffer.cpp + CollisionShapes/btTriangleIndexVertexArray.cpp + CollisionShapes/btTriangleIndexVertexMaterialArray.cpp + CollisionShapes/btTriangleMesh.cpp + CollisionShapes/btTriangleMeshShape.cpp + CollisionShapes/btUniformScalingShape.cpp + Gimpact/btContactProcessing.cpp + Gimpact/btGImpactShape.cpp + Gimpact/gim_contact.cpp + Gimpact/btGImpactBvh.cpp + Gimpact/btGenericPoolAllocator.cpp + Gimpact/gim_memory.cpp + Gimpact/btGImpactCollisionAlgorithm.cpp + Gimpact/btTriangleShapeEx.cpp + Gimpact/gim_tri_collision.cpp + Gimpact/btGImpactQuantizedBvh.cpp + Gimpact/gim_box_set.cpp + NarrowPhaseCollision/btContinuousConvexCollision.cpp + NarrowPhaseCollision/btGjkEpa2.cpp + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp + NarrowPhaseCollision/btConvexCast.cpp + NarrowPhaseCollision/btGjkConvexCast.cpp + NarrowPhaseCollision/btGjkPairDetector.cpp + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp + NarrowPhaseCollision/btPersistentManifold.cpp + NarrowPhaseCollision/btRaycastCallback.cpp + NarrowPhaseCollision/btSubSimplexConvexCast.cpp + NarrowPhaseCollision/btVoronoiSimplexSolver.cpp ) - -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 + +SET(Root_HDRS + ../btBulletCollisionCommon.h ) +SET(BroadphaseCollision_HDRS + BroadphaseCollision/btAxisSweep3.h + BroadphaseCollision/btBroadphaseInterface.h + BroadphaseCollision/btBroadphaseProxy.h + BroadphaseCollision/btCollisionAlgorithm.h + BroadphaseCollision/btDispatcher.h + BroadphaseCollision/btDbvtBroadphase.h + BroadphaseCollision/btDbvt.h + BroadphaseCollision/btMultiSapBroadphase.h + BroadphaseCollision/btOverlappingPairCache.h + BroadphaseCollision/btOverlappingPairCallback.h + BroadphaseCollision/btQuantizedBvh.h + BroadphaseCollision/btSimpleBroadphase.h +) +SET(CollisionDispatch_HDRS + CollisionDispatch/btActivatingCollisionAlgorithm.h + CollisionDispatch/btCollisionConfiguration.h + CollisionDispatch/btCollisionCreateFunc.h + CollisionDispatch/btCollisionDispatcher.h + CollisionDispatch/btCollisionObject.h + CollisionDispatch/btCollisionWorld.h + CollisionDispatch/btCompoundCollisionAlgorithm.h + CollisionDispatch/btConvexConcaveCollisionAlgorithm.h + CollisionDispatch/btDefaultCollisionConfiguration.h + CollisionDispatch/btSphereSphereCollisionAlgorithm.h + CollisionDispatch/btBoxBoxCollisionAlgorithm.h + CollisionDispatch/btBoxBoxDetector.h + CollisionDispatch/btGhostObject.h + CollisionDispatch/btSphereBoxCollisionAlgorithm.h + CollisionDispatch/btConvexPlaneCollisionAlgorithm.h + CollisionDispatch/btSphereTriangleCollisionAlgorithm.h + CollisionDispatch/btConvexConvexAlgorithm.h + CollisionDispatch/btEmptyCollisionAlgorithm.h + CollisionDispatch/btManifoldResult.h + CollisionDispatch/btSimulationIslandManager.h + CollisionDispatch/btUnionFind.h + CollisionDispatch/SphereTriangleDetector.h +) +SET(CollisionShapes_HDRS + CollisionShapes/btBoxShape.h + CollisionShapes/btBvhTriangleMeshShape.h + CollisionShapes/btCapsuleShape.h + CollisionShapes/btCollisionMargin + CollisionShapes/btCollisionShape.h + CollisionShapes/btCompoundShape.h + CollisionShapes/btConcaveShape.h + CollisionShapes/btConeShape.h + CollisionShapes/btConvexHullShape.h + CollisionShapes/btConvexPointCloudShape.h + CollisionShapes/btConvexShape.h + CollisionShapes/btConvexInternalShape.h + CollisionShapes/btConvexTriangleMeshShape.h + CollisionShapes/btCylinderShape.h + CollisionShapes/btEmptyShape.h + CollisionShapes/btHeightfieldTerrainShape.h + CollisionShapes/btMinkowskiSumShape.h + CollisionShapes/btMaterial.h + CollisionShapes/btMultimaterialTriangleMeshShape.h + CollisionShapes/btMultiSphereShape.h + CollisionShapes/btOptimizedBvh.h + CollisionShapes/btPolyhedralConvexShape.h + CollisionShapes/btScaledBvhTriangleMeshShape.h + CollisionShapes/btTetrahedronShape.h + CollisionShapes/btSphereShape.h + CollisionShapes/btShapeHull.h + CollisionShapes/btStaticPlaneShape.h + CollisionShapes/btStridingMeshInterface.h + CollisionShapes/btTriangleCallback.h + CollisionShapes/btTriangleBuffer.h + CollisionShapes/btTriangleIndexVertexArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.h + CollisionShapes/btTriangleMesh.h + CollisionShapes/btTriangleMeshShape.h + CollisionShapes/btUniformScalingShape.h +) +SET(Gimpact_HDRS + Gimpact/btGImpactShape.h + Gimpact/gim_contact.h + Gimpact/btGImpactBvh.h + Gimpact/btGenericPoolAllocator.h + Gimpact/gim_memory.h + Gimpact/btGImpactCollisionAlgorithm.h + Gimpact/btTriangleShapeEx.h + Gimpact/gim_tri_collision.h + Gimpact/btGImpactQuantizedBvh.h + Gimpact/gim_box_set.h +) +SET(NarrowPhaseCollision_HDRS + NarrowPhaseCollision/btContinuousConvexCollision.h + NarrowPhaseCollision/btConvexCast.h + NarrowPhaseCollision/btConvexPenetrationDepthSolver.h + NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h + NarrowPhaseCollision/btGjkConvexCast.h + NarrowPhaseCollision/btGjkEpa2.h + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h + NarrowPhaseCollision/btGjkPairDetector.h + NarrowPhaseCollision/btManifoldPoint.h + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h + NarrowPhaseCollision/btPersistentManifold.h + NarrowPhaseCollision/btPointCollector.h + NarrowPhaseCollision/btRaycastCallback.h + NarrowPhaseCollision/btSimplexSolverInterface.h + NarrowPhaseCollision/btSubSimplexConvexCast.h + NarrowPhaseCollision/btVoronoiSimplexSolver.h +) + +SET(BulletCollision_HDRS + ${Root_HDRS} + ${BroadphaseCollision_HDRS} + ${CollisionDispatch_HDRS} + ${CollisionShapes_HDRS} + ${Gimpact_HDRS} + ${NarrowPhaseCollision_HDRS} +) + + +ADD_LIBRARY(BulletCollision ${BulletCollision_SRCS} ${BulletCollision_HDRS}) +SET_TARGET_PROPERTIES(BulletCollision PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletCollision PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletCollision LinearMath) +ENDIF (BUILD_SHARED_LIBS) + +#INSTALL of other files requires CMake 2.6 +IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + INSTALL(TARGETS BulletCollision DESTINATION lib) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.h") +ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + +IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletCollision PROPERTIES FRAMEWORK true) + + SET_TARGET_PROPERTIES(BulletCollision PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${BroadphaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadphaseCollision) + SET_PROPERTY(SOURCE ${CollisionDispatch_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionDispatch) + SET_PROPERTY(SOURCE ${CollisionShapes_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionShapes) + SET_PROPERTY(SOURCE ${Gimpact_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Gimpact) + SET_PROPERTY(SOURCE ${NarrowPhaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/NarrowPhaseCollision) + +ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp index f6c1e32ac7c..9a749a03793 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -19,9 +19,10 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btSphereShape.h" -SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle) +SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold) :m_sphere(sphere), -m_triangle(triangle) +m_triangle(triangle), +m_contactBreakingThreshold(contactBreakingThreshold) { } @@ -40,7 +41,7 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res //move sphere into triangle space btTransform sphereInTr = transformB.inverseTimes(transformA); - if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact)) + if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold)) { if (swapResults) { @@ -93,7 +94,7 @@ bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* ve } ///combined discrete/continuous sphere-triangle -bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact) +bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold) { const btVector3* vertices = &m_triangle->getVertexPtr(0); @@ -115,10 +116,7 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po normal *= btScalar(-1.); } - ///todo: move this gContactBreakingThreshold into a proper structure - extern btScalar gContactBreakingThreshold; - - btScalar contactMargin = gContactBreakingThreshold; + btScalar contactMargin = contactBreakingThreshold; bool isInsideContactPlane = distanceFromPlane < r + contactMargin; bool isInsideShellPlane = distanceFromPlane < r; @@ -140,8 +138,8 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po btVector3 nearestOnEdge; for (int i = 0; i < m_triangle->getNumEdges(); i++) { - btPoint3 pa; - btPoint3 pb; + btVector3 pa; + btVector3 pb; m_triangle->getEdge(i,pa,pb); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h index 26dabaa480e..981bd54e76c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -17,7 +17,7 @@ subject to the following restrictions: #define SPHERE_TRIANGLE_DETECTOR_H #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "LinearMath/btPoint3.h" + class btSphereShape; @@ -30,19 +30,19 @@ struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface { virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); - SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle); + SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold); virtual ~SphereTriangleDetector() {}; private: - bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact); + bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold); bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ); bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal); btSphereShape* m_sphere; btTriangleShape* m_triangle; - + btScalar m_contactBreakingThreshold; }; #endif //SPHERE_TRIANGLE_DETECTOR_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp new file mode 100644 index 00000000000..7e5da6c5872 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp @@ -0,0 +1,47 @@ +/* +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 "btActivatingCollisionAlgorithm.h" +#include "btCollisionDispatcher.h" +#include "btCollisionObject.h" + +btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci) +:btCollisionAlgorithm(ci) +//, +//m_colObj0(0), +//m_colObj1(0) +{ +} +btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1) +:btCollisionAlgorithm(ci) +//, +//m_colObj0(0), +//m_colObj1(0) +{ +// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1)) +// { +// m_colObj0 = colObj0; +// m_colObj1 = colObj1; +// +// m_colObj0->activate(); +// m_colObj1->activate(); +// } +} + +btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm() +{ +// m_colObj0->activate(); +// m_colObj1->activate(); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h new file mode 100644 index 00000000000..25fe088942d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h @@ -0,0 +1,36 @@ +/* +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. +*/ + +#ifndef __BT_ACTIVATING_COLLISION_ALGORITHM_H +#define __BT_ACTIVATING_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +///This class is not enabled yet (work-in-progress) to more aggressively activate objects. +class btActivatingCollisionAlgorithm : public btCollisionAlgorithm +{ +// btCollisionObject* m_colObj0; +// btCollisionObject* m_colObj1; + +public: + + btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci); + + btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1); + + virtual ~btActivatingCollisionAlgorithm(); + +}; +#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp index cd0c028012c..d3342c547b5 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp @@ -22,7 +22,7 @@ subject to the following restrictions: #define USE_PERSISTENT_CONTACTS 1 btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1) -: btCollisionAlgorithm(ci), +: btActivatingCollisionAlgorithm(ci,obj0,obj1), m_ownManifold(false), m_manifoldPtr(mf) { diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h index 35afaf175a1..e7d2cc25c22 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef BOX_BOX__COLLISION_ALGORITHM_H #define BOX_BOX__COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h" #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" @@ -24,14 +24,14 @@ subject to the following restrictions: class btPersistentManifold; ///box-box collision detection -class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm +class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm { bool m_ownManifold; btPersistentManifold* m_manifoldPtr; public: btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) {} + : btActivatingCollisionAlgorithm(ci) {} virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp index 45ebff5dc45..31353f1b2c4 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp @@ -207,7 +207,13 @@ void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) 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)); + if (btFabs(a+q) > SIMD_EPSILON) + { + a = 1.f/(btScalar(3.0)*(a+q)); + } else + { + a=1e30f; + } cx = a*(cx + q*(p[n*2-2]+p[0])); cy = a*(cy + q*(p[n*2-1]+p[1])); } @@ -226,9 +232,9 @@ void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) a = btScalar(j)*(2*M__PI/m) + A[i0]; if (a > 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 + + *iret = i0; // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0 + for (i=0; i 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..e6ff2130aad 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -52,12 +52,12 @@ btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisio for (int j=0;jgetCollisionAlgorithmCreateFunc(i,j); - assert(m_doubleDispatch[i][j]); + btAssert(m_doubleDispatch[i][j]); } } -}; +} void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) @@ -78,7 +78,13 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) btCollisionObject* body0 = (btCollisionObject*)b0; btCollisionObject* body1 = (btCollisionObject*)b1; - + + //test for Bullet 2.74: use a relative contact breaking threshold without clamping against 'gContactBreakingThreshold' + //btScalar contactBreakingThreshold = btMin(gContactBreakingThreshold,btMin(body0->getCollisionShape()->getContactBreakingThreshold(),body1->getCollisionShape()->getContactBreakingThreshold())); + btScalar contactBreakingThreshold = btMin(body0->getCollisionShape()->getContactBreakingThreshold(),body1->getCollisionShape()->getContactBreakingThreshold()); + + btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold()); + void* mem = 0; if (m_persistentManifoldPoolAllocator->getFreeCount()) @@ -89,7 +95,7 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) mem = btAlignedAlloc(sizeof(btPersistentManifold),16); } - btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0); + btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold); manifold->m_index1a = m_manifoldsPtr.size(); m_manifoldsPtr.push_back(manifold); @@ -144,7 +150,6 @@ btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* bo - bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) { //here you can do filtering @@ -158,8 +163,8 @@ bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionOb bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1) { - assert(body0); - assert(body1); + btAssert(body0); + btAssert(body1); bool needsCollision = true; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp index 846c9b9b989..285b8f174e4 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -19,6 +19,7 @@ subject to the following restrictions: btCollisionObject::btCollisionObject() : m_anisotropicFriction(1.f,1.f,1.f), m_hasAnisotropicFriction(false), + m_contactProcessingThreshold(0.f), m_broadphaseHandle(0), m_collisionShape(0), m_rootCollisionShape(0), diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h index 8442868cf89..0d5b7886443 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -29,8 +29,11 @@ struct btBroadphaseProxy; class btCollisionShape; #include "LinearMath/btMotionState.h" #include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" +typedef btAlignedObjectArray btCollisionObjectArray; + /// btCollisionObject can be used to manage collision detection objects. /// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy. @@ -49,8 +52,10 @@ protected: //without destroying the continuous interpolated motion (which uses this interpolation velocities) btVector3 m_interpolationLinearVelocity; btVector3 m_interpolationAngularVelocity; + btVector3 m_anisotropicFriction; - bool m_hasAnisotropicFriction; + bool m_hasAnisotropicFriction; + btScalar m_contactProcessingThreshold; btBroadphaseProxy* m_broadphaseHandle; btCollisionShape* m_collisionShape; @@ -74,7 +79,7 @@ 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. + ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc. ///do not assign your own m_internalType unless you write a new dynamics object class. int m_internalType; @@ -106,14 +111,19 @@ public: CF_STATIC_OBJECT= 1, CF_KINEMATIC_OBJECT= 2, CF_NO_CONTACT_RESPONSE = 4, - CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution) + CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution) + CF_CHARACTER_OBJECT = 16 }; enum CollisionObjectTypes { CO_COLLISION_OBJECT =1, CO_RIGID_BODY, - CO_SOFT_BODY + ///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter + ///It is useful for collision sensors, explosion objects, character controller etc. + CO_GHOST_OBJECT, + CO_SOFT_BODY, + CO_HF_FLUID }; SIMD_FORCE_INLINE bool mergesSimulationIslands() const @@ -136,6 +146,16 @@ public: return m_hasAnisotropicFriction; } + ///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default. + ///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges + void setContactProcessingThreshold( btScalar contactProcessingThreshold) + { + m_contactProcessingThreshold = contactProcessingThreshold; + } + btScalar getContactProcessingThreshold() const + { + return m_contactProcessingThreshold; + } SIMD_FORCE_INLINE bool isStaticObject() const { return (m_collisionFlags & CF_STATIC_OBJECT) != 0; @@ -193,7 +213,7 @@ public: m_collisionShape = collisionShape; } - int getActivationState() const { return m_activationState1;} + SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;} void setActivationState(int newState); @@ -210,7 +230,7 @@ public: void activate(bool forceActivation = false); - inline bool isActive() const + SIMD_FORCE_INLINE bool isActive() const { return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION)); } @@ -254,12 +274,12 @@ public: } - btBroadphaseProxy* getBroadphaseHandle() + SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle() { return m_broadphaseHandle; } - const btBroadphaseProxy* getBroadphaseHandle() const + SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const { return m_broadphaseHandle; } @@ -305,7 +325,7 @@ public: return m_interpolationAngularVelocity; } - const int getIslandTag() const + SIMD_FORCE_INLINE int getIslandTag() const { return m_islandTag1; } @@ -315,7 +335,7 @@ public: m_islandTag1 = tag; } - const int getCompanionId() const + SIMD_FORCE_INLINE int getCompanionId() const { return m_companionId; } @@ -325,7 +345,7 @@ public: m_companionId = id; } - const btScalar getHitFraction() const + SIMD_FORCE_INLINE btScalar getHitFraction() const { return m_hitFraction; } @@ -336,7 +356,7 @@ public: } - const int getCollisionFlags() const + SIMD_FORCE_INLINE int getCollisionFlags() const { return m_collisionFlags; } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index d8674a320a7..10e880e2523 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -32,6 +32,9 @@ subject to the following restrictions: #include "LinearMath/btQuickprof.h" #include "LinearMath/btStackAlloc.h" +//#define USE_BRUTEFORCE_RAYBROADPHASE 1 +//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest +//#define RECALCULATE_AABB_RAYCAST 1 //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" @@ -66,6 +69,7 @@ btCollisionWorld::~btCollisionWorld() // getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); getBroadphase()->destroyProxy(bp,m_dispatcher1); + collisionObject->setBroadphaseHandle(0); } } @@ -111,6 +115,41 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho +} + + + +void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj) +{ + btVector3 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::updateAabbs() @@ -125,38 +164,9 @@ void btCollisionWorld::updateAabbs() //only update aabb of active objects if (colObj->isActive()) { - 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"); - } - } + updateSingleAabb(colObj); } } - } @@ -226,6 +236,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra if (collisionShape->isConvex()) { +// BT_PROFILE("rayTestConvex"); btConvexCast::CastResult castResult; castResult.m_fraction = resultCallback.m_closestHitFraction; @@ -269,6 +280,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra } else { if (collisionShape->isConcave()) { +// BT_PROFILE("rayTestConcave"); if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) { ///optimized version for btBvhTriangleMeshShape @@ -286,7 +298,8 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): - btTriangleRaycastCallback(from,to), + //@BP Mod + btTriangleRaycastCallback(from,to, resultCallback->m_flags), m_resultCallback(resultCallback), m_collisionObject(collisionObject), m_triangleMesh(triangleMesh) @@ -317,7 +330,8 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal); } else { - btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; + //generic (slower) case + btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; btTransform worldTocollisionObject = colObjWorldTransform.inverse(); @@ -330,11 +344,12 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra { btCollisionWorld::RayResultCallback* m_resultCallback; btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; + btConcaveShape* m_triangleMesh; BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, - btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): - btTriangleRaycastCallback(from,to), + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh): + //@BP Mod + btTriangleRaycastCallback(from,to, resultCallback->m_flags), m_resultCallback(resultCallback), m_collisionObject(collisionObject), m_triangleMesh(triangleMesh) @@ -363,7 +378,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra }; - BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,concaveShape); rcb.m_hitFraction = resultCallback.m_closestHitFraction; btVector3 rayAabbMinLocal = rayFromLocal; @@ -371,10 +386,11 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btVector3 rayAabbMaxLocal = rayFromLocal; rayAabbMaxLocal.setMax(rayToLocal); - triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); + concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); } } else { - //todo: use AABB tree or other BVH acceleration structure! +// BT_PROFILE("rayTestCompound"); + ///@todo: use AABB tree or other BVH acceleration structure, see btDbvt if (collisionShape->isCompound()) { const btCompoundShape* compoundShape = static_cast(collisionShape); @@ -408,9 +424,10 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt { if (collisionShape->isConvex()) { + //BT_PROFILE("convexSweepConvex"); btConvexCast::CastResult castResult; castResult.m_allowedPenetration = allowedPenetration; - castResult.m_fraction = btScalar(1.);//?? + castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//?? btConvexShape* convexShape = (btConvexShape*) collisionShape; btVoronoiSimplexSolver simplexSolver; @@ -452,6 +469,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt { if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) { + //BT_PROFILE("convexSweepbtBvhTriangleMesh"); btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; btTransform worldTocollisionObject = colObjWorldTransform.inverse(); btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); @@ -508,7 +526,8 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal); } else { - btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + //BT_PROFILE("convexSweepConcave"); + btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; btTransform worldTocollisionObject = colObjWorldTransform.inverse(); btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); @@ -520,10 +539,10 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt { btCollisionWorld::ConvexResultCallback* m_resultCallback; btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; + btConcaveShape* m_triangleMesh; BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, - btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): + btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld): btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), m_resultCallback(resultCallback), m_collisionObject(collisionObject), @@ -556,7 +575,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt }; - BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform); + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform); tccb.m_hitFraction = resultCallback.m_closestHitFraction; btVector3 boxMinLocal, boxMaxLocal; castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); @@ -567,12 +586,13 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt rayAabbMaxLocal.setMax(convexToLocal); rayAabbMinLocal += boxMinLocal; rayAabbMaxLocal += boxMaxLocal; - triangleMesh->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); + concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); } } else { - //todo: use AABB tree or other BVH acceleration structure! + ///@todo : use AABB tree or other BVH acceleration structure! if (collisionShape->isCompound()) { + BT_PROFILE("convexSweepCompound"); const btCompoundShape* compoundShape = static_cast(collisionShape); int i=0; for (i=0;igetNumChildShapes();i++) @@ -596,51 +616,173 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt } } -void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const + +struct btSingleRayCallback : public btBroadphaseRayCallback { + btVector3 m_rayFromWorld; + btVector3 m_rayToWorld; + btTransform m_rayFromTrans; + btTransform m_rayToTrans; + btVector3 m_hitNormal; - btTransform rayFromTrans,rayToTrans; - rayFromTrans.setIdentity(); - rayFromTrans.setOrigin(rayFromWorld); - rayToTrans.setIdentity(); + const btCollisionWorld* m_world; + btCollisionWorld::RayResultCallback& m_resultCallback; - 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())) { - //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); - btVector3 collisionObjectAabbMin,collisionObjectAabbMax; - collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + btVector3 rayDir = (rayToWorld-rayFromWorld); - btScalar hitLambda = resultCallback.m_closestHitFraction; - btVector3 hitNormal; - if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) - { - rayTestSingle(rayFromTrans,rayToTrans, - collisionObject, - collisionObject->getCollisionShape(), - collisionObject->getWorldTransform(), - resultCallback); - } - } + rayDir.normalize (); + ///what about division by zero? --> just set rayDirection[i] to INF/1e30 + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); } + + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further ray tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; +#if 0 +#ifdef RECALCULATE_AABB + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); +#else + //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); + const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; + const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; +#endif +#endif + //btScalar hitLambda = m_resultCallback.m_closestHitFraction; + //culling already done by broadphase + //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) + { + m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback); + } + } + return true; + } +}; + +void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const +{ + BT_PROFILE("rayTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); +#else + for (int i=0;igetNumCollisionObjects();i++) + { + rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE + } -void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback) const + +struct btSingleSweepCallback : public btBroadphaseRayCallback { + + btTransform m_convexFromTrans; + btTransform m_convexToTrans; + btVector3 m_hitNormal; + const btCollisionWorld* m_world; + btCollisionWorld::ConvexResultCallback& m_resultCallback; + btScalar m_allowedCcdPenetration; + const btConvexShape* m_castShape; + + + btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration) + :m_convexFromTrans(convexFromTrans), + m_convexToTrans(convexToTrans), + m_world(world), + m_resultCallback(resultCallback), + m_allowedCcdPenetration(allowedPenetration), + m_castShape(castShape) + { + btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin()); + btVector3 rayDir = unnormalizedRayDir.normalized(); + ///what about division by zero? --> just set rayDirection[i] to INF/1e30 + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(unnormalizedRayDir); + + } + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further convex sweep tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback, + m_allowedCcdPenetration); + } + + return true; + } +}; + + + +void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const +{ + + BT_PROFILE("convexSweepTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical + + + btTransform convexFromTrans,convexToTrans; convexFromTrans = convexFromWorld; convexToTrans = convexToWorld; @@ -649,12 +791,21 @@ void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btT { btVector3 linVel, angVel; btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); + btVector3 zeroLinVel; + zeroLinVel.setValue(0,0,0); btTransform R; R.setIdentity (); R.setRotation (convexFromTrans.getRotation()); - castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); + castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); } +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + + btSingleSweepCallback convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration); + + m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax); + +#else /// go over all objects, and if the ray intersects their aabb + cast shape aabb, // do a ray-shape query using convexCaster (CCD) int i; @@ -676,9 +827,9 @@ void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btT collisionObject->getCollisionShape(), collisionObject->getWorldTransform(), resultCallback, - getDispatchInfo().m_allowedCcdPenetration); + allowedCcdPenetration); } } } - +#endif //USE_BRUTEFORCE_RAYBROADPHASE } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index 7557691a9a9..87f7137a55b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -1,6 +1,6 @@ /* Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ +Copyright (c) 2003-2006 Erwin Coumans http://bulletphysics.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. @@ -22,39 +22,39 @@ subject to the following restrictions: * * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ). * - * There is the Physics Forum for Feedback and bteral Collision Detection and Physics discussions. - * Please visit http://www.continuousphysics.com/Bullet/phpBB2/index.php + * There is the Physics Forum for feedback and general Collision Detection and Physics discussions. + * Please visit http://www.bulletphysics.com * * @section install_sec Installation * * @subsection step1 Step 1: Download - * You can download the Bullet Physics Library from our website: http://www.continuousphysics.com/Bullet/ + * You can download the Bullet Physics Library from the Google Code repository: http://code.google.com/p/bullet/downloads/list * @subsection step2 Step 2: Building * Bullet comes with autogenerated Project Files for Microsoft Visual Studio 6, 7, 7.1 and 8. * The main Workspace/Solution is located in Bullet/msvc/8/wksbullet.sln (replace 8 with your version). * - * Under other platforms, like Linux or Mac OS-X, Bullet can be build using either using cmake, http://www.cmake.org, or jam, http://www.perforce.com/jam/jam.html . cmake can autogenerate Xcode, KDevelop, MSVC and other build systems. just run cmake . in the root of Bullet. + * Under other platforms, like Linux or Mac OS-X, Bullet can be build using either using make, cmake, http://www.cmake.org , or jam, http://www.perforce.com/jam/jam.html . cmake can autogenerate Xcode, KDevelop, MSVC and other build systems. just run cmake . in the root of Bullet. + * So if you are not using MSVC or cmake, you can run ./autogen.sh ./configure to create both Makefile and Jamfile and then run make or jam. * Jam is a build system that can build the library, demos and also autogenerate the MSVC Project Files. - * So if you are not using MSVC, you can run configure and jam . - * If you don't have jam installed, you can make jam from the included jam-2.5 sources, or download jam from ftp://ftp.perforce.com/pub/jam/ + * If you don't have jam installed, you can make jam from the included jam-2.5 sources, or download jam from ftp://ftp.perforce.com/jam * * @subsection step3 Step 3: Testing demos - * Try to run and experiment with CcdPhysicsDemo executable as a starting point. + * Try to run and experiment with BasicDemo executable as a starting point. * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation. * The Dependencies can be seen in this documentation under Directories * - * @subsection step4 Step 4: Integrating in your application, Full Rigid Body Simulation - * Check out CcdPhysicsDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform. - * PLEASE NOTE THE CcdPhysicsEnvironment and CcdPhysicsController is obsolete and will be removed. It has been replaced by classes derived frmo btDynamicsWorld and btRididBody + * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation + * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform. + * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld. * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras) * Bullet Collision Detection can also be used without the Dynamics/Extras. - * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo. Also in Extras/test_BulletOde.cpp there is a sample Collision Detection integration with Open Dynamics Engine, ODE, http://www.ode.org + * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo. * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation. * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector. * * @section copyright Copyright - * Copyright (C) 2005-2007 Erwin Coumans, some contributions Copyright Gino van den Bergen, Christer Ericson, Simon Hobbs, Ricardo Padrela, F Richter(res), Stephane Redon - * Special thanks to all visitors of the Bullet Physics forum, and in particular above contributors, Dave Eberle, Dirk Gregorius, Erin Catto, Dave Eberle, Adam Moravanszky, + * Copyright (C) 2005-2008 Erwin Coumans, some contributions Copyright Gino van den Bergen, Christer Ericson, Simon Hobbs, Ricardo Padrela, F Richter(res), Stephane Redon + * Special thanks to all visitors of the Bullet Physics forum, and in particular above contributors, John McCutchan, Nathanael Presson, Dave Eberle, Dirk Gregorius, Erin Catto, Dave Eberle, Adam Moravanszky, * Pierre Terdiman, Kenny Erleben, Russell Smith, Oliver Strunk, Jan Paul van Waveren, Marten Svanfeldt. * */ @@ -71,7 +71,7 @@ class btBroadphaseInterface; #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" #include "btCollisionObject.h" -#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray +#include "btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" #include "LinearMath/btAlignedObjectArray.h" @@ -107,6 +107,11 @@ public: m_broadphasePairCache = pairCache; } + const btBroadphaseInterface* getBroadphase() const + { + return m_broadphasePairCache; + } + btBroadphaseInterface* getBroadphase() { return m_broadphasePairCache; @@ -128,8 +133,10 @@ public: return m_dispatcher1; } - virtual void updateAabbs(); + void updateSingleAabb(btCollisionObject* colObj); + virtual void updateAabbs(); + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) { m_debugDrawer = debugDrawer; @@ -179,6 +186,8 @@ public: btCollisionObject* m_collisionObject; short int m_collisionFilterGroup; short int m_collisionFilterMask; + //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback + unsigned int m_flags; virtual ~RayResultCallback() { @@ -192,7 +201,9 @@ public: :m_closestHitFraction(btScalar(1.)), m_collisionObject(0), m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), - m_collisionFilterMask(btBroadphaseProxy::AllFilter) + m_collisionFilterMask(btBroadphaseProxy::AllFilter), + //@BP Mod + m_flags(0) { } @@ -347,7 +358,7 @@ public: // 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 convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const; /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index 535b61992b0..1dea91a0b0b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -19,19 +19,32 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btDbvt.h" #include "LinearMath/btIDebugDraw.h" #include "LinearMath/btAabbUtil2.h" +#include "btManifoldResult.h" btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -:btCollisionAlgorithm(ci), +:btActivatingCollisionAlgorithm(ci,body0,body1), 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()); + btAssert (colObj->getCollisionShape()->isCompound()); btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + m_compoundShapeRevision = compoundShape->getUpdateRevision(); + + preallocateChildAlgorithms(body0,body1); +} + +void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1) +{ + btCollisionObject* colObj = m_isSwapped? body1 : body0; + btCollisionObject* otherObj = m_isSwapped? body0 : body1; + btAssert (colObj->getCollisionShape()->isCompound()); + + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + int numChildren = compoundShape->getNumChildShapes(); int i; @@ -46,14 +59,13 @@ m_sharedManifold(ci.m_manifold) btCollisionShape* tmpShape = colObj->getCollisionShape(); btCollisionShape* childShape = compoundShape->getChildShape(i); colObj->internalSetTemporaryCollisionShape( childShape ); - m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold); + m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold); colObj->internalSetTemporaryCollisionShape( tmpShape ); } } } - -btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() +void btCompoundCollisionAlgorithm::removeChildAlgorithms() { int numChildren = m_childCollisionAlgorithms.size(); int i; @@ -67,6 +79,11 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() } } +btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() +{ + removeChildAlgorithms(); +} + @@ -167,13 +184,50 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* otherObj = m_isSwapped? body0 : body1; - assert (colObj->getCollisionShape()->isCompound()); + + + btAssert (colObj->getCollisionShape()->isCompound()); btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + ///btCompoundShape might have changed: + ////make sure the internal child collision algorithm caches are still valid + if (compoundShape->getUpdateRevision() != m_compoundShapeRevision) + { + ///clear and update all + removeChildAlgorithms(); + + preallocateChildAlgorithms(body0,body1); + } + + 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 need to refresh all contact manifolds + ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep + ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm + { + int i; + btManifoldArray manifoldArray; + for (i=0;igetAllContactManifolds(manifoldArray); + for (int m=0;mgetNumContacts()) + { + resultOut->setPersistentManifold(manifoldArray[m]); + resultOut->refreshContactPoints(); + resultOut->setPersistentManifold(0);//??necessary? + } + } + manifoldArray.clear(); + } + } + } if (tree) { @@ -242,7 +296,7 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* otherObj = m_isSwapped? body0 : body1; - assert (colObj->getCollisionShape()->isCompound()); + btAssert (colObj->getCollisionShape()->isCompound()); btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); @@ -285,3 +339,4 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* } + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 624a3cf10f5..255e0af668c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COMPOUND_COLLISION_ALGORITHM_H #define COMPOUND_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" @@ -26,16 +26,23 @@ class btDispatcher; #include "btCollisionCreateFunc.h" #include "LinearMath/btAlignedObjectArray.h" class btDispatcher; +class btCollisionObject; /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes -class btCompoundCollisionAlgorithm : public btCollisionAlgorithm +class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm { btAlignedObjectArray m_childCollisionAlgorithms; bool m_isSwapped; class btPersistentManifold* m_sharedManifold; bool m_ownsManifold; + + int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated + void removeChildAlgorithms(); + + void preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1); + public: btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp index 6d28904cb03..cbc5530732b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -27,7 +27,7 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -: btCollisionAlgorithm(ci), +: btActivatingCollisionAlgorithm(ci,body0,body1), m_isSwapped(isSwapped), m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) { @@ -72,7 +72,7 @@ btConvexTriangleCallback::~btConvexTriangleCallback() void btConvexTriangleCallback::clearCache() { m_dispatcher->clearManifold(m_manifoldPtr); -}; +} @@ -93,7 +93,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i ///debug drawing of the overlapping triangles - if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0) + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe )) { btVector3 color(255,255,0); btTransform& tr = ob->getWorldTransform(); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h index 34b9a107be9..984a4c39e8e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H #define CONVEX_CONCAVE_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/CollisionShapes/btTriangleCallback.h" @@ -34,8 +34,8 @@ class btConvexTriangleCallback : public btTriangleCallback btVector3 m_aabbMin; btVector3 m_aabbMax ; - btManifoldResult* m_resultOut; + btManifoldResult* m_resultOut; btDispatcher* m_dispatcher; const btDispatcherInfo* m_dispatchInfoPtr; btScalar m_collisionMarginTriangle; @@ -70,7 +70,7 @@ int m_triangleCount; /// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes. -class btConvexConcaveCollisionAlgorithm : public btCollisionAlgorithm +class btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm { bool m_isSwapped; @@ -78,6 +78,7 @@ class btConvexConcaveCollisionAlgorithm : public btCollisionAlgorithm btConvexTriangleCallback m_btConvexTriangleCallback; + public: btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp index cb830f889be..274c5f5bdc6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -38,7 +38,7 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" @@ -51,6 +51,8 @@ subject to the following restrictions: btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) { + m_numPerturbationIterations = 0; + m_minimumPointsPerturbationThreshold = 3; m_simplexSolver = simplexSolver; m_pdSolver = pdSolver; } @@ -59,17 +61,22 @@ btConvexConvexAlgorithm::CreateFunc::~CreateFunc() { } -btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) -: btCollisionAlgorithm(ci), -m_gjkPairDetector(0,0,simplexSolver,pdSolver), +btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) +: btActivatingCollisionAlgorithm(ci,body0,body1), +m_simplexSolver(simplexSolver), +m_pdSolver(pdSolver), m_ownManifold (false), m_manifoldPtr(mf), -m_lowLevelOfDetail(false) +m_lowLevelOfDetail(false), +#ifdef USE_SEPDISTANCE_UTIL2 +,m_sepDistance((static_cast(body0->getCollisionShape()))->getAngularMotionDisc(), + (static_cast(body1->getCollisionShape()))->getAngularMotionDisc()), +#endif +m_numPerturbationIterations(numPerturbationIterations), +m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) { (void)body0; (void)body1; - - } @@ -90,8 +97,63 @@ void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel) } +struct btPerturbedContactResult : public btManifoldResult +{ + btManifoldResult* m_originalManifoldResult; + btTransform m_transformA; + btTransform m_transformB; + btTransform m_unPerturbedTransform; + bool m_perturbA; + btIDebugDraw* m_debugDrawer; + btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer) + :m_originalManifoldResult(originalResult), + m_transformA(transformA), + m_transformB(transformB), + m_perturbA(perturbA), + m_unPerturbedTransform(unPerturbedTransform), + m_debugDrawer(debugDrawer) + { + } + virtual ~ btPerturbedContactResult() + { + } + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth) + { + btVector3 endPt,startPt; + btScalar newDepth; + btVector3 newNormal; + + if (m_perturbA) + { + btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth; + endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg); + newDepth = (endPt - pointInWorld).dot(normalOnBInWorld); + startPt = endPt+normalOnBInWorld*newDepth; + } else + { + endPt = pointInWorld + normalOnBInWorld*orgDepth; + startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld); + newDepth = (endPt - startPt).dot(normalOnBInWorld); + + } + +//#define DEBUG_CONTACTS 1 +#ifdef DEBUG_CONTACTS + m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0)); + m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0)); + m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1)); +#endif //DEBUG_CONTACTS + + + m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth); + } + +}; + +extern btScalar gContactBreakingThreshold; // // Convex-Convex collision algorithm @@ -107,39 +169,125 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl } resultOut->setPersistentManifold(m_manifoldPtr); -#ifdef USE_BT_GJKEPA - btConvexShape* shape0(static_cast(body0->getCollisionShape())); - btConvexShape* shape1(static_cast(body1->getCollisionShape())); - const btScalar radialmargin(0/*shape0->getMargin()+shape1->getMargin()*/); - btGjkEpaSolver::sResults results; - if(btGjkEpaSolver::Collide( shape0,body0->getWorldTransform(), - shape1,body1->getWorldTransform(), - radialmargin,results)) - { - dispatchInfo.m_debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); - resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); - } -#else + //comment-out next line to test multi-contact generation + //resultOut->getPersistentManifold()->clearManifold(); + btConvexShape* min0 = static_cast(body0->getCollisionShape()); btConvexShape* min1 = static_cast(body1->getCollisionShape()); + +#ifdef USE_SEPDISTANCE_UTIL2 + m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform()); + if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f) +#endif //USE_SEPDISTANCE_UTIL2 + + { + btGjkPairDetector::ClosestPointInput input; + btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver); //TODO: if (dispatchInfo.m_useContinuous) - m_gjkPairDetector.setMinkowskiA(min0); - m_gjkPairDetector.setMinkowskiB(min1); - input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); - input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; - input.m_stackAlloc = dispatchInfo.m_stackAllocator; + gjkPairDetector.setMinkowskiA(min0); + gjkPairDetector.setMinkowskiB(min1); -// input.m_maximumDistanceSquared = btScalar(1e30); - +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + input.m_maximumDistanceSquared = 1e30f; + } else +#endif //USE_SEPDISTANCE_UTIL2 + { + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; + } + + input.m_stackAlloc = dispatchInfo.m_stackAllocator; input.m_transformA = body0->getWorldTransform(); input.m_transformB = body1->getWorldTransform(); + + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + btScalar sepDist = gjkPairDetector.getCachedSeparatingDistance()+dispatchInfo.m_convexConservativeDistanceThreshold; + + //now perturbe directions to get multiple contact points + btVector3 v0,v1; + btVector3 sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized(); + btPlaneSpace1(sepNormalWorldSpace,v0,v1); + //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects - m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points + if (resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold) + { + + int i; + + bool perturbeA = true; + const btScalar angleLimit = 0.125f * SIMD_PI; + btScalar perturbeAngle; + btScalar radiusA = min0->getAngularMotionDisc(); + btScalar radiusB = min1->getAngularMotionDisc(); + if (radiusA < radiusB) + { + perturbeAngle = gContactBreakingThreshold /radiusA; + perturbeA = true; + } else + { + perturbeAngle = gContactBreakingThreshold / radiusB; + perturbeA = false; + } + if ( perturbeAngle > angleLimit ) + perturbeAngle = angleLimit; + + btTransform unPerturbedTransform; + if (perturbeA) + { + unPerturbedTransform = input.m_transformA; + } else + { + unPerturbedTransform = input.m_transformB; + } + + for ( i=0;igetWorldTransform().getBasis()); + input.m_transformB = body1->getWorldTransform(); +#ifdef DEBUG_CONTACTS + dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0); +#endif //DEBUG_CONTACTS + } else + { + input.m_transformA = body0->getWorldTransform(); + input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis()); +#ifdef DEBUG_CONTACTS + dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0); #endif + } + + btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw); + gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw); + + + } + } + + + +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform()); + } +#endif //USE_SEPDISTANCE_UTIL2 + + + } if (m_ownManifold) { diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h index a0030e6793d..62dd33eb98d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -16,30 +16,50 @@ subject to the following restrictions: #ifndef CONVEX_CONVEX_ALGORITHM_H #define CONVEX_CONVEX_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btActivatingCollisionAlgorithm.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" +#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil class btConvexPenetrationDepthSolver; -///ConvexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations. -class btConvexConvexAlgorithm : public btCollisionAlgorithm -{ - btGjkPairDetector m_gjkPairDetector; -public: +///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise +///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions. +///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util +///for certain pairs that have a small size ratio +///#define USE_SEPDISTANCE_UTIL2 1 +///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects. +///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal. +///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888 +class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm +{ +#ifdef USE_SEPDISTANCE_UTIL2 + btConvexSeparatingDistanceUtil m_sepDistance; +#endif + btSimplexSolverInterface* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + bool m_ownManifold; btPersistentManifold* m_manifoldPtr; bool m_lowLevelOfDetail; + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + + ///cache separating vector to speedup collision detection + public: - btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); + virtual ~btConvexConvexAlgorithm(); @@ -65,9 +85,12 @@ public: struct CreateFunc :public btCollisionAlgorithmCreateFunc { + btConvexPenetrationDepthSolver* m_pdSolver; btSimplexSolverInterface* m_simplexSolver; - + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); virtual ~CreateFunc(); @@ -75,7 +98,7 @@ public: 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(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp index 391cf6c7bc4..a7b3b163d66 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.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. @@ -22,15 +22,17 @@ subject to the following restrictions: //#include -btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) +btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold) : btCollisionAlgorithm(ci), m_ownManifold(false), m_manifoldPtr(mf), -m_isSwapped(isSwapped) +m_isSwapped(isSwapped), +m_numPerturbationIterations(numPerturbationIterations), +m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) { 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); @@ -48,30 +50,28 @@ btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm() } } - - -void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) { - (void)dispatchInfo; - (void)resultOut; - if (!m_manifoldPtr) - return; - - btCollisionObject* convexObj = m_isSwapped? body1 : body0; + 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; + bool hasCollision = false; const btVector3& planeNormal = planeShape->getPlaneNormal(); const btScalar& planeConstant = planeShape->getPlaneConstant(); - btTransform planeInConvex; - planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform(); + + btTransform convexWorldTransform = convexObj->getWorldTransform(); btTransform convexInPlaneTrans; - convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform(); - + convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform; + //now perturbe the convex-world transform + convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot); + btTransform planeInConvex; + planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform(); + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + btVector3 vtxInPlane = convexInPlaneTrans(vtx); btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); @@ -87,6 +87,53 @@ void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0 btVector3 pOnB = vtxInPlaneWorld; resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); } +} + + +void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + 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(); + + //first perform a collision query with the non-perturbated collision objects + { + btQuaternion rotq(0,0,0,1); + collideSingleContact(rotq,body0,body1,dispatchInfo,resultOut); + } + + if (resultOut->getPersistentManifold()->getNumContacts()getAngularMotionDisc(); + perturbeAngle = gContactBreakingThreshold / radius; + if ( perturbeAngle > angleLimit ) + perturbeAngle = angleLimit; + + btQuaternion perturbeRot(v0,perturbeAngle); + for (int i=0;igetNumContacts()) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h index 7b258554171..368ca71dda0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h @@ -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. @@ -28,18 +28,22 @@ class btPersistentManifold; /// Other features are frame-coherency (persistent data) and collision response. class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm { - bool m_ownManifold; + bool m_ownManifold; btPersistentManifold* m_manifoldPtr; - bool m_isSwapped; - + bool m_isSwapped; + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + public: - btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold); virtual ~btConvexPlaneCollisionAlgorithm(); virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + void collideSingleContact (const btQuaternion& perturbeRot, 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) @@ -52,15 +56,24 @@ public: struct CreateFunc :public btCollisionAlgorithmCreateFunc { + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + CreateFunc() + : m_numPerturbationIterations(3), + m_minimumPointsPerturbationThreshold(3) + { + } + 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); + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); } else { - return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true); + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); } } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp index 1c317080544..3ae25f109c2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp @@ -100,11 +100,10 @@ btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefault int maxSize = sizeof(btConvexConvexAlgorithm); int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); int maxSize3 = sizeof(btCompoundCollisionAlgorithm); - int maxSize4 = sizeof(btEmptyAlgorithm); - + int sl = sizeof(btConvexSeparatingDistanceUtil); + sl = sizeof(btGjkPairDetector); int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2); collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); - collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4); if (constructionInfo.m_stackAlloc) { @@ -289,3 +288,10 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg //failed to find an algorithm return m_emptyCreateFunc; } + +void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold) +{ + btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc; + convexConvex->m_numPerturbationIterations = numPerturbationIterations; + convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h index df48ee95a18..6d8cab726bd 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -33,9 +33,9 @@ struct btDefaultCollisionConstructionInfo :m_stackAlloc(0), m_persistentManifoldPool(0), m_collisionAlgorithmPool(0), - m_defaultMaxPersistentManifoldPoolSize(65535), - m_defaultMaxCollisionAlgorithmPoolSize(65535), - m_defaultStackAllocatorSize(5*1024*1024) + m_defaultMaxPersistentManifoldPoolSize(4096), + m_defaultMaxCollisionAlgorithmPoolSize(4096), + m_defaultStackAllocatorSize(0) { } }; @@ -44,7 +44,7 @@ struct btDefaultCollisionConstructionInfo ///btCollisionConfiguration allows to configure Bullet collision detection ///stack allocator, pool memory allocators -///todo: describe the meaning +///@todo: describe the meaning class btDefaultCollisionConfiguration : public btCollisionConfiguration { @@ -111,6 +111,14 @@ public: virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + ///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm. + ///By default, this feature is disabled for best performance. + ///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature. + ///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled + ///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first. + ///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points. + ///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection. + void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.cpp new file mode 100644 index 00000000000..86141fa6899 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.cpp @@ -0,0 +1,171 @@ +/* +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 "btGhostObject.h" +#include "btCollisionWorld.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "LinearMath/btAabbUtil2.h" + +btGhostObject::btGhostObject() +{ + m_internalType = CO_GHOST_OBJECT; +} + +btGhostObject::~btGhostObject() +{ + ///btGhostObject should have been removed from the world, so no overlapping objects + btAssert(!m_overlappingObjects.size()); +} + + +void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + ///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index==m_overlappingObjects.size()) + { + //not found + m_overlappingObjects.push_back(otherObject); + } +} + +void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index~btHashedOverlappingPairCache(); + btAlignedFree( m_hashPairCache ); +} + +void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) +{ + btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle(); + btAssert(actualThisProxy); + + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index==m_overlappingObjects.size()) + { + m_overlappingObjects.push_back(otherObject); + m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy); + } +} + +void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle(); + btAssert(actualThisProxy); + + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (indexremoveOverlappingPair(actualThisProxy,otherProxy,dispatcher); + } +} + + +void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) 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)) + { + btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback, + allowedCcdPenetration); + } + } + } + +} + +void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const +{ + btTransform rayFromTrans; + rayFromTrans.setIdentity(); + rayFromTrans.setOrigin(rayFromWorld); + btTransform rayToTrans; + rayToTrans.setIdentity(); + rayToTrans.setOrigin(rayToWorld); + + + int i; + for (i=0;igetBroadphaseHandle())) + { + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback); + } + } +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.h new file mode 100644 index 00000000000..95b5750240c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btGhostObject.h @@ -0,0 +1,174 @@ +/* +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. +*/ + +#ifndef BT_GHOST_OBJECT_H +#define BT_GHOST_OBJECT_H + + +#include "btCollisionObject.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h" +#include "LinearMath/btAlignedAllocator.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "btCollisionWorld.h" + +class btConvexShape; + +class btDispatcher; + +///The btGhostObject can keep track of all objects that are overlapping +///By default, this overlap is based on the AABB +///This is useful for creating a character controller, collision sensors/triggers, explosions etc. +///We plan on adding rayTest and other queries for the btGhostObject +ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject +{ +protected: + + btAlignedObjectArray m_overlappingObjects; + +public: + + btGhostObject(); + + virtual ~btGhostObject(); + + void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const; + + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; + + ///this method is mainly for expert/internal use only. + virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0); + ///this method is mainly for expert/internal use only. + virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0); + + int getNumOverlappingObjects() const + { + return m_overlappingObjects.size(); + } + + btCollisionObject* getOverlappingObject(int index) + { + return m_overlappingObjects[index]; + } + + const btCollisionObject* getOverlappingObject(int index) const + { + return m_overlappingObjects[index]; + } + + btAlignedObjectArray& getOverlappingPairs() + { + return m_overlappingObjects; + } + + const btAlignedObjectArray getOverlappingPairs() const + { + return m_overlappingObjects; + } + + // + // internal cast + // + + static const btGhostObject* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_GHOST_OBJECT) + return (const btGhostObject*)colObj; + return 0; + } + static btGhostObject* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_GHOST_OBJECT) + return (btGhostObject*)colObj; + return 0; + } + +}; + +class btPairCachingGhostObject : public btGhostObject +{ + btHashedOverlappingPairCache* m_hashPairCache; + +public: + + btPairCachingGhostObject(); + + virtual ~btPairCachingGhostObject(); + + ///this method is mainly for expert/internal use only. + virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0); + + virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0); + + btHashedOverlappingPairCache* getOverlappingPairCache() + { + return m_hashPairCache; + } + +}; + + + +///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject. +class btGhostPairCallback : public btOverlappingPairCallback +{ + +public: + btGhostPairCallback() + { + } + + virtual ~btGhostPairCallback() + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject; + btGhostObject* ghost0 = btGhostObject::upcast(colObj0); + btGhostObject* ghost1 = btGhostObject::upcast(colObj1); + if (ghost0) + ghost0->addOverlappingObjectInternal(proxy1, proxy0); + if (ghost1) + ghost1->addOverlappingObjectInternal(proxy0, proxy1); + return 0; + } + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) + { + btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject; + btGhostObject* ghost0 = btGhostObject::upcast(colObj0); + btGhostObject* ghost1 = btGhostObject::upcast(colObj1); + if (ghost0) + ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0); + if (ghost1) + ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1); + return 0; + } + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) + { + btAssert(0); + //need to keep track of all ghost objects and call them here + //m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher); + } + + + +}; + +#endif \ No newline at end of file diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp index d5b12598be2..f8dfa5b101f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -55,7 +55,7 @@ btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* b void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) { - assert(m_manifoldPtr); + btAssert(m_manifoldPtr); //order in manifold needs to match if (depth > m_manifoldPtr->getContactBreakingThreshold()) @@ -92,8 +92,8 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b newPt.m_partId1 = m_partId1; newPt.m_index0 = m_index0; newPt.m_index1 = m_index1; - - ///todo, check this for any side effects + //printf("depth=%f\n",depth); + ///@todo, check this for any side effects if (insertIndex >= 0) { //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h index 5aac9a46f6a..964b6a04483 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -45,6 +45,8 @@ class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result int m_partId1; int m_index0; int m_index1; + + public: btManifoldResult() @@ -77,6 +79,7 @@ public: m_index1=index1; } + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); SIMD_FORCE_INLINE void refreshContactPoints() diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index 9f8e27a4407..0328d0f738f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -24,7 +24,8 @@ subject to the following restrictions: //#include #include "LinearMath/btQuickprof.h" -btSimulationIslandManager::btSimulationIslandManager() +btSimulationIslandManager::btSimulationIslandManager(): +m_splitIslands(true) { } @@ -43,10 +44,10 @@ void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btColl { { - btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); - + for (int i=0;igetPairCache()->getNumOverlappingPairs();i++) { + btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); const btBroadphasePair& collisionPair = pairPtr[i]; btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; @@ -143,11 +144,13 @@ class btPersistentManifoldSortPredicate }; -void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects) +void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld) { BT_PROFILE("islandUnionFindAndQuickSort"); + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); + m_islandmanifold.resize(0); //we are going to sort the unionfind array, and store the element id in the size @@ -183,7 +186,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio // printf("error in island management\n"); } - assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); if (colObj0->getIslandTag() == islandId) { if (colObj0->getActivationState()== ACTIVE_TAG) @@ -210,7 +213,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio // printf("error in island management\n"); } - assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); if (colObj0->getIslandTag() == islandId) { @@ -231,13 +234,14 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio // printf("error in island management\n"); } - assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); if (colObj0->getIslandTag() == islandId) { if ( colObj0->getActivationState() == ISLAND_SLEEPING) { colObj0->setActivationState( WANTS_DEACTIVATION); + colObj0->setDeactivationTime(0.f); } } } @@ -248,11 +252,11 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio int i; int maxNumManifolds = dispatcher->getNumManifolds(); -#define SPLIT_ISLANDS 1 -#ifdef SPLIT_ISLANDS +//#define SPLIT_ISLANDS 1 +//#ifdef SPLIT_ISLANDS -#endif //SPLIT_ISLANDS +//#endif //SPLIT_ISLANDS for (i=0;i(manifold->getBody0()); btCollisionObject* colObj1 = static_cast(manifold->getBody1()); - //todo: check sleeping conditions! + ///@todo: check sleeping conditions! if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) || ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING)) { @@ -276,24 +280,24 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio { colObj0->activate(); } -#ifdef SPLIT_ISLANDS - // //filtering for response - if (dispatcher->needsResponse(colObj0,colObj1)) - m_islandmanifold.push_back(manifold); -#endif //SPLIT_ISLANDS + if(m_splitIslands) + { + //filtering for response + if (dispatcher->needsResponse(colObj0,colObj1)) + m_islandmanifold.push_back(manifold); + } } } } -// -// todo: this is random access, it can be walked 'cache friendly'! -// -void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) +///@todo: this is random access, it can be walked 'cache friendly'! +void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback) { + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); - buildIslands(dispatcher,collisionObjects); + buildIslands(dispatcher,collisionWorld); int endIslandIndex=1; int startIslandIndex; @@ -301,84 +305,86 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, 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()); - - //now process all active islands (sets of manifolds for now) - - int startManifoldIndex = 0; - int endManifoldIndex = 1; - - //int islandId; - - - -// printf("Start Islands\n"); - - //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated - for ( startIslandIndex=0;startIslandIndexgetInternalManifoldPointer(); + int maxNumManifolds = dispatcher->getNumManifolds(); + 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()); - bool islandSleeping = false; - - for (endIslandIndex = startIslandIndex;(endIslandIndexisActive()) - islandSleeping = true; - } - + //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) + m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); - //find the accompanying contact manifold for this islandId - int numIslandManifolds = 0; - btPersistentManifold** startManifold = 0; + //now process all active islands (sets of manifolds for now) - if (startManifoldIndexisActive()) + islandSleeping = true; + } + + + //find the accompanying contact manifold for this islandId + int numIslandManifolds = 0; + btPersistentManifold** startManifold = 0; + + if (startManifoldIndexProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); + // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); + } + + if (numIslandManifolds) + { + startManifoldIndex = endManifoldIndex; + } - if (!islandSleeping) - { - callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); -// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); + m_islandBodies.resize(0); } - - if (numIslandManifolds) - { - startManifoldIndex = endManifoldIndex; - } - - m_islandBodies.resize(0); - } -#endif //SPLIT_ISLANDS - + } // else if(!splitIslands) } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h index 5f4d54cd803..d059f5d6b0d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -19,7 +19,7 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btUnionFind.h" #include "btCollisionCreateFunc.h" #include "LinearMath/btAlignedObjectArray.h" - +#include "btCollisionObject.h" class btCollisionObject; class btCollisionWorld; @@ -35,6 +35,7 @@ class btSimulationIslandManager btAlignedObjectArray m_islandmanifold; btAlignedObjectArray m_islandBodies; + bool m_splitIslands; public: btSimulationIslandManager(); @@ -61,9 +62,18 @@ public: virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0; }; - void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback); + void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback); - void buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects); + void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld); + + bool getSplitIslands() + { + return m_splitIslands; + } + void setSplitIslands(bool doSplitIslands) + { + m_splitIslands = doSplitIslands; + } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp index 1e4bbce451d..8df876928c1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp @@ -21,7 +21,7 @@ subject to the following restrictions: //#include btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) -: btCollisionAlgorithm(ci), +: btActivatingCollisionAlgorithm(ci,col0,col1), m_ownManifold(false), m_manifoldPtr(mf), m_isSwapped(isSwapped) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h index 158f0ffcc74..47111d1c4af 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef SPHERE_BOX_COLLISION_ALGORITHM_H #define SPHERE_BOX_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; @@ -26,7 +26,7 @@ class btPersistentManifold; /// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. /// Other features are frame-coherency (persistent data) and collision response. -class btSphereBoxCollisionAlgorithm : public btCollisionAlgorithm +class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm { bool m_ownManifold; btPersistentManifold* m_manifoldPtr; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp index c2b13f5903f..5c4e78fe518 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -19,7 +19,7 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCollisionObject.h" btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1) -: btCollisionAlgorithm(ci), +: btActivatingCollisionAlgorithm(ci,col0,col1), m_ownManifold(false), m_manifoldPtr(mf) { @@ -78,7 +78,7 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 } ///point on A (worldspace) - btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; + ///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; ///point on B (worldspace) btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h index afdc2ee7fa0..7d07512ca66 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H #define SPHERE_SPHERE_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" #include "btCollisionDispatcher.h" @@ -26,7 +26,7 @@ class btPersistentManifold; /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. /// Other features are frame-coherency (persistent data) and collision response. /// Also provides the most basic sample for custom/user btCollisionAlgorithm -class btSphereSphereCollisionAlgorithm : public btCollisionAlgorithm +class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm { bool m_ownManifold; btPersistentManifold* m_manifoldPtr; @@ -35,7 +35,7 @@ public: btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) {} + : btActivatingCollisionAlgorithm(ci) {} virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp index fdbd4abef27..2d5efcf56ba 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -22,7 +22,7 @@ subject to the following restrictions: btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped) -: btCollisionAlgorithm(ci), +: btActivatingCollisionAlgorithm(ci,col0,col1), m_ownManifold(false), m_manifoldPtr(mf), m_swapped(swapped) @@ -56,10 +56,10 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co /// report a contact. internally this will be kept persistent, and contact reduction is done resultOut->setPersistentManifold(m_manifoldPtr); - SphereTriangleDetector detector(sphere,triangle); + SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold()); btDiscreteCollisionDetectorInterface::ClosestPointInput input; - input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds + input.m_maximumDistanceSquared = btScalar(1e30);///@todo: tighter bounds input.m_transformA = sphereObj->getWorldTransform(); input.m_transformB = triObj->getWorldTransform(); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h index bbaf228c44c..606c3635ae9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H #define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; @@ -25,7 +25,7 @@ class btPersistentManifold; /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. /// Other features are frame-coherency (persistent data) and collision response. /// Also provides the most basic sample for custom/user btCollisionAlgorithm -class btSphereTriangleCollisionAlgorithm : public btCollisionAlgorithm +class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm { bool m_ownManifold; btPersistentManifold* m_manifoldPtr; @@ -35,7 +35,7 @@ public: btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped); btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) {} + : btActivatingCollisionAlgorithm(ci) {} virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp index bb01b60fa85..c561df06109 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -14,8 +14,6 @@ subject to the following restrictions: */ #include "btUnionFind.h" -#include - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h index 820c8bc858e..e105ecbff18 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h @@ -98,8 +98,8 @@ class btUnionFind int find(int x) { - //assert(x < m_N); - //assert(x >= 0); + //btAssert(x < m_N); + //btAssert(x >= 0); while (x != m_elements[x].m_id) { @@ -110,8 +110,8 @@ class btUnionFind m_elements[x].m_id = m_elements[m_elements[x].m_id].m_id; #endif // x = m_elements[x].m_id; - //assert(x < m_N); - //assert(x >= 0); + //btAssert(x < m_N); + //btAssert(x >= 0); } return x; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h index 4d4fbefea37..14502d485dc 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -19,7 +19,7 @@ subject to the following restrictions: #include "btPolyhedralConvexShape.h" #include "btCollisionMargin.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "LinearMath/btPoint3.h" +#include "LinearMath/btVector3.h" #include "LinearMath/btMinMax.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. @@ -45,8 +45,6 @@ public: } - virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;} - virtual btVector3 localGetSupportingVertex(const btVector3& vec) const { btVector3 halfExtents = getHalfExtentsWithoutMargin(); @@ -82,8 +80,10 @@ public: } - btBoxShape( const btVector3& boxHalfExtents) + btBoxShape( const btVector3& boxHalfExtents) + : btPolyhedralConvexShape() { + m_shapeType = BOX_SHAPE_PROXYTYPE; btVector3 margin(getMargin(),getMargin(),getMargin()); m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; }; @@ -117,7 +117,7 @@ public: virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const { //this plane might not be aligned... btVector4 plane ; @@ -161,36 +161,30 @@ public: switch (i) { case 0: - plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); - plane[3] = -halfExtents.x(); + plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x()); break; case 1: - plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); - plane[3] = -halfExtents.x(); + plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x()); break; case 2: - plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); - plane[3] = -halfExtents.y(); + plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y()); break; case 3: - plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); - plane[3] = -halfExtents.y(); + plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y()); break; case 4: - plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); - plane[3] = -halfExtents.z(); + plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z()); break; case 5: - plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); - plane[3] = -halfExtents.z(); + plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z()); break; default: - assert(0); + btAssert(0); } } - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const //virtual void getEdge(int i,Edge& edge) const { int edgeVert0 = 0; @@ -261,7 +255,7 @@ public: - virtual bool isInside(const btPoint3& pt,btScalar tolerance) const + virtual bool isInside(const btVector3& pt,btScalar tolerance) const { btVector3 halfExtents = getHalfExtentsWithoutMargin(); @@ -312,7 +306,7 @@ public: penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); break; default: - assert(0); + btAssert(0); } } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp index 819f6f7f97d..68ff5e2d7bb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp @@ -26,6 +26,7 @@ m_bvh(0), m_useQuantizedAabbCompression(useQuantizedAabbCompression), m_ownsBvh(false) { + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; //construct bvh from meshInterface #ifndef DISABLE_BVH @@ -57,6 +58,7 @@ m_bvh(0), m_useQuantizedAabbCompression(useQuantizedAabbCompression), m_ownsBvh(false) { + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; //construct bvh from meshInterface #ifndef DISABLE_BVH @@ -141,10 +143,19 @@ void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const 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()); + + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ()); + } } /* Perform ray vs. triangle collision here */ @@ -202,9 +213,18 @@ void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, co { int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; - btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); - m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ()); + } } /* Perform ray vs. triangle collision here */ @@ -279,12 +299,24 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co #ifdef DEBUG_TRIANGLE_MESH printf("%d ,",graphicsindex); #endif //DEBUG_TRIANGLE_MESH - btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); - m_triangle[j] = btVector3( - graphicsbase[0]*meshScaling.getX(), - graphicsbase[1]*meshScaling.getY(), - graphicsbase[2]*meshScaling.getZ()); + m_triangle[j] = btVector3( + btScalar(graphicsbase[0])*meshScaling.getX(), + btScalar(graphicsbase[1])*meshScaling.getY(), + btScalar(graphicsbase[2])*meshScaling.getZ()); + } #ifdef DEBUG_TRIANGLE_MESH printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z()); #endif //DEBUG_TRIANGLE_MESH diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h index 6e587340dc1..cb2c326574e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -37,7 +37,7 @@ public: BT_DECLARE_ALIGNED_ALLOCATOR(); - btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {}; + btBvhTriangleMeshShape() : btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;}; 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 @@ -50,10 +50,7 @@ public: 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); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp index 26ba276b900..60a96a542f9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -19,8 +19,9 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btCollisionMargin.h" #include "LinearMath/btQuaternion.h" -btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) +btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape () { + m_shapeType = CAPSULE_SHAPE_PROXYTYPE; m_upAxis = 1; m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h index d4b046d40c9..828c1b3a565 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -30,7 +30,7 @@ protected: protected: ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses. - btCapsuleShape() {}; + btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;}; public: btCapsuleShape(btScalar radius,btScalar height); @@ -43,15 +43,13 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - 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 center = t.getOrigin(); btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); aabbMin = center - extent; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp index 39e621aa946..d242cba1b72 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp @@ -16,6 +16,9 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btCollisionShape.h" +btScalar gContactThresholdFactor=btScalar(0.02); + + /* Make sure this dummy function never changes so that it can be used by probes that are checking whether the @@ -42,8 +45,13 @@ void btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) con center = (aabbMin+aabbMax)*btScalar(0.5); } +btScalar btCollisionShape::getContactBreakingThreshold() const +{ + return getAngularMotionDisc() * gContactThresholdFactor; +} btScalar btCollisionShape::getAngularMotionDisc() const { + ///@todo cache this value, to improve performance btVector3 center; btScalar disc; getBoundingSphere(center,disc); @@ -65,7 +73,7 @@ void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const b // add linear motion btVector3 linMotion = linvel*timeStep; - //todo: simd would have a vector max/min operation, instead of per-element access + ///@todo: simd would have a vector max/min operation, instead of per-element access if (linMotion.x() > btScalar(0.)) temporalAabbMaxx += linMotion.x(); else diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h index 3a352b90777..1f4b9bec647 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -19,20 +19,21 @@ subject to the following restrictions: #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 ///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects. class btCollisionShape { - +protected: + int m_shapeType; void* m_userPointer; public: - btCollisionShape() : m_userPointer(0) + btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0) { } + virtual ~btCollisionShape() { } @@ -45,6 +46,8 @@ public: ///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations. virtual btScalar getAngularMotionDisc() const; + virtual btScalar getContactBreakingThreshold() const; + ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) ///result is conservative @@ -76,7 +79,7 @@ public: return btBroadphaseProxy::isInfinite(getShapeType()); } - 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; @@ -87,13 +90,13 @@ public: #endif //__SPU__ - + int getShapeType() const { return m_shapeType; } virtual void setMargin(btScalar margin) = 0; virtual btScalar getMargin() const = 0; ///optional user data pointer - void setUserPointer(void* userPtr) + void setUserPointer(void* userPtr) { m_userPointer = userPtr; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index 997361a5069..9c2b04d18fa 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -17,16 +17,22 @@ subject to the following restrictions: #include "btCollisionShape.h" #include "BulletCollision/BroadphaseCollision/btDbvt.h" -btCompoundShape::btCompoundShape() -:m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), +btCompoundShape::btCompoundShape(bool enableDynamicAabbTree) +: m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)), m_collisionMargin(btScalar(0.)), m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), -m_dynamicAabbTree(0) +m_dynamicAabbTree(0), +m_updateRevision(1) { - void* mem = btAlignedAlloc(sizeof(btDbvt),16); - m_dynamicAabbTree = new(mem) btDbvt(); - btAssert(mem==m_dynamicAabbTree); + m_shapeType = COMPOUND_SHAPE_PROXYTYPE; + + if (enableDynamicAabbTree) + { + void* mem = btAlignedAlloc(sizeof(btDbvt),16); + m_dynamicAabbTree = new(mem) btDbvt(); + btAssert(mem==m_dynamicAabbTree); + } } @@ -41,6 +47,7 @@ btCompoundShape::~btCompoundShape() void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) { + m_updateRevision++; //m_childTransforms.push_back(localTransform); //m_childShapes.push_back(shape); btCompoundShapeChild child; @@ -49,6 +56,7 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio child.m_childShapeType = shape->getShapeType(); child.m_childMargin = shape->getMargin(); + //extend the local aabbMin/aabbMax btVector3 localAabbMin,localAabbMax; shape->getAabb(localTransform,localAabbMin,localAabbMax); @@ -72,10 +80,29 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio } m_children.push_back(child); + +} + +void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform) +{ + m_children[childIndex].m_transform = newChildTransform; + + if (m_dynamicAabbTree) + { + ///update the dynamic aabb tree + btVector3 localAabbMin,localAabbMax; + m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax); + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + int index = m_children.size()-1; + m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds); + } + + recalculateLocalAabb(); } void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) { + m_updateRevision++; btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); if (m_dynamicAabbTree) { @@ -86,8 +113,11 @@ void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) } + + void btCompoundShape::removeChildShape(btCollisionShape* shape) { + m_updateRevision++; // 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--) @@ -97,6 +127,8 @@ void btCompoundShape::removeChildShape(btCollisionShape* shape) m_children.swap(i,m_children.size()-1); m_children.pop_back(); //remove it from the m_dynamicAabbTree too + //@todo: this leads to problems due to caching in the btCompoundCollisionAlgorithm + //so effectively, removeChildShape is broken at the moment //m_dynamicAabbTree->remove(m_aabbProxies[i]); //m_aabbProxies.swap(i,m_children.size()-1); //m_aabbProxies.pop_back(); @@ -112,6 +144,7 @@ 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)); @@ -134,19 +167,27 @@ void btCompoundShape::recalculateLocalAabb() 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); + + //avoid an illegal AABB when there are no children + if (!m_children.size()) + { + localHalfExtents.setValue(0,0,0); + localCenter.setValue(0,0,0); + } + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); + btMatrix3x3 abs_b = trans.getBasis().absolute(); - btPoint3 center = trans(localCenter); + btVector3 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 btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const @@ -178,7 +219,9 @@ void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransf btScalar totalMass = 0; btVector3 center(0, 0, 0); - for (int k = 0; k < n; k++) + int k; + + for (k = 0; k < n; k++) { center += m_children[k].m_transform.getOrigin() * masses[k]; totalMass += masses[k]; @@ -187,7 +230,7 @@ void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransf principal.setOrigin(center); btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0); - for (int k = 0; k < n; k++) + for ( k = 0; k < n; k++) { btVector3 i; m_children[k].m_childShape->calculateLocalInertia(masses[k], i); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h index 3624749f768..434860c8633 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -46,23 +46,26 @@ SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompou c1.m_childMargin == c2.m_childMargin ); } -/// btCompoundShape allows to store multiple other btCollisionShapes +/// The btCompoundShape allows to store multiple other btCollisionShapes /// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape. +/// It has an (optional) dynamic aabb tree to accelerate early rejection tests. +/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25 +/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape) ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape { - //btAlignedObjectArray m_childTransforms; - //btAlignedObjectArray m_childShapes; btAlignedObjectArray m_children; btVector3 m_localAabbMin; btVector3 m_localAabbMax; - //btOptimizedBvh* m_aabbTree; btDbvt* m_dynamicAabbTree; + ///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated + int m_updateRevision; + public: BT_DECLARE_ALIGNED_ALLOCATOR(); - btCompoundShape(); + btCompoundShape(bool enableDynamicAabbTree = true); virtual ~btCompoundShape(); @@ -88,15 +91,18 @@ public: return m_children[index].m_childShape; } - btTransform getChildTransform(int index) + btTransform& getChildTransform(int index) { return m_children[index].m_transform; } - const btTransform getChildTransform(int index) const + const btTransform& getChildTransform(int index) const { return m_children[index].m_transform; } + ///set a new transform for a child, and update internal data structures (local aabb and dynamic tree) + void updateChildTransform(int childIndex, const btTransform& newChildTransform); + btCompoundShapeChild* getChildList() { @@ -121,8 +127,6 @@ public: virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} - virtual void setMargin(btScalar margin) { m_collisionMargin = margin; @@ -151,6 +155,10 @@ public: ///of the collision object by the principal transform. void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; + int getUpdateRevision() const + { + return m_updateRevision; + } private: btScalar m_collisionMargin; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h index f3f57206ab7..30065d55a12 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -20,6 +20,16 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "btTriangleCallback.h" +/// PHY_ScalarType enumerates possible scalar types. +/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use +typedef enum PHY_ScalarType { + PHY_FLOAT, + PHY_DOUBLE, + PHY_INTEGER, + PHY_SHORT, + PHY_FIXEDPOINT88, + PHY_UCHAR +} PHY_ScalarType; ///The btConcaveShape class provides an interface for non-moving (static) concave shapes. ///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape. diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp index 207b3024bc3..d887be61ada 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp @@ -14,14 +14,14 @@ subject to the following restrictions: */ #include "btConeShape.h" -#include "LinearMath/btPoint3.h" -btConeShape::btConeShape (btScalar radius,btScalar height): +btConeShape::btConeShape (btScalar radius,btScalar height): btConvexInternalShape (), m_radius (radius), m_height(height) { + m_shapeType = CONE_SHAPE_PROXYTYPE; setConeUpIndex(1); btVector3 halfExtents; m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height)); @@ -60,7 +60,7 @@ void btConeShape::setConeUpIndex(int upIndex) m_coneIndices[2] = 1; break; default: - assert(0); + btAssert(0); }; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h index 685369742e4..1869893f37a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h @@ -69,9 +69,6 @@ public: } - - virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; } - virtual const char* getName()const { return "Cone"; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp index 2596858bc3a..2b067367767 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp @@ -19,16 +19,17 @@ subject to the following restrictions: -btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) +btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexShape () { - m_points.resize(numPoints); + m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE; + m_unscaledPoints.resize(numPoints); unsigned char* pointsBaseAddress = (unsigned char*)points; for (int i=0;i maxDot) @@ -91,9 +92,9 @@ void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const supportVerticesOut[i][3] = btScalar(-1e30); } } - for (int i=0;i m_points; + btAlignedObjectArray m_unscaledPoints; public: BT_DECLARE_ALIGNED_ALLOCATOR(); @@ -33,23 +33,38 @@ public: ///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. ///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint. ///btConvexHullShape make an internal copy of the points. - btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btPoint3)); + btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3)); - void addPoint(const btPoint3& point); + void addPoint(const btVector3& point); - btPoint3* getPoints() + + btVector3* getUnscaledPoints() { - return &m_points[0]; + return &m_unscaledPoints[0]; } - const btPoint3* getPoints() const + const btVector3* getUnscaledPoints() const { - return &m_points[0]; + return &m_unscaledPoints[0]; } - int getNumPoints() const + ///getPoints is obsolete, please use getUnscaledPoints + const btVector3* getPoints() const { - return m_points.size(); + return getUnscaledPoints(); + } + + + + + SIMD_FORCE_INLINE btVector3 getScaledPoint(int i) const + { + return m_unscaledPoints[i] * m_localScaling; + } + + SIMD_FORCE_INLINE int getNumPoints() const + { + return m_unscaledPoints.size(); } virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; @@ -57,7 +72,6 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; } //debugging virtual const char* getName()const {return "Convex";} @@ -65,11 +79,11 @@ public: virtual int getNumVertices() const; virtual int getNumEdges() const; - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const; - virtual void getVertex(int i,btPoint3& vtx) const; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; + virtual void getVertex(int i,btVector3& vtx) const; virtual int getNumPlanes() const; - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const; - virtual bool isInside(const btPoint3& pt,btScalar tolerance) const; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; + virtual bool isInside(const btVector3& pt,btScalar tolerance) const; ///in case we receive negative scaling virtual void setLocalScaling(const btVector3& scaling); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp index fb81c8a5bde..bfb741310e1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp @@ -17,6 +17,7 @@ subject to the following restrictions: #include "btConvexInternalShape.h" + btConvexInternalShape::btConvexInternalShape() : m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), m_collisionMargin(CONVEX_DISTANCE_MARGIN) @@ -48,7 +49,8 @@ void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAa tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); minAabb[i] = tmp[i]-margin; } -}; +} + btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const @@ -70,6 +72,7 @@ btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)c return supVertex; #else + btAssert(0); 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 index 9388ccf31f2..bab720d7b6d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h @@ -19,23 +19,18 @@ class btConvexInternalShape : public btConvexShape btScalar m_padding; + btConvexInternalShape(); + 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 { diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp new file mode 100644 index 00000000000..4ab5d692945 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp @@ -0,0 +1,156 @@ +/* +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 "btConvexPointCloudShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" + +void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; + recalcLocalAabb(); +} + +#ifndef __SPU__ +btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); + btScalar newDot,maxDot = btScalar(-1e30); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + + for (int i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + return supVec; +} + +void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + btScalar newDot; + //use 'w' component of supportVerticesOut? + { + for (int i=0;i supportVerticesOut[j][3]) + { + //WARNING: don't swap next lines, the w component would get overwritten! + supportVerticesOut[j] = vtx; + supportVerticesOut[j][3] = newDot; + } + } + } + + + +} + + + +btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const +{ + 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; +} + + +#endif + + + + + + +//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection +//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo +int btConvexPointCloudShape::getNumVertices() const +{ + return m_numPoints; +} + +int btConvexPointCloudShape::getNumEdges() const +{ + return 0; +} + +void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const +{ + btAssert (0); +} + +void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const +{ + vtx = m_unscaledPoints[i]*m_localScaling; +} + +int btConvexPointCloudShape::getNumPlanes() const +{ + return 0; +} + +void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const +{ + + btAssert(0); +} + +//not yet +bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const +{ + btAssert(0); + return false; +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h new file mode 100644 index 00000000000..7e1c13b29c1 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h @@ -0,0 +1,96 @@ +/* +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_CONVEX_POINT_CLOUD_SHAPE_H +#define BT_CONVEX_POINT_CLOUD_SHAPE_H + +#include "btPolyhedralConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" + +///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices. +ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexShape +{ + btVector3* m_unscaledPoints; + int m_numPoints; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true) + { + m_localScaling = localScaling; + m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE; + m_unscaledPoints = points; + m_numPoints = numPoints; + + if (computeAabb) + recalcLocalAabb(); + } + + void setPoints (btVector3* points, int numPoints, bool computeAabb = true) + { + m_unscaledPoints = points; + m_numPoints = numPoints; + + if (computeAabb) + recalcLocalAabb(); + } + + SIMD_FORCE_INLINE btVector3* getUnscaledPoints() + { + return m_unscaledPoints; + } + + SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const + { + return m_unscaledPoints; + } + + SIMD_FORCE_INLINE int getNumPoints() const + { + return m_numPoints; + } + + SIMD_FORCE_INLINE btVector3 getScaledPoint( int index) const + { + return m_unscaledPoints[index] * m_localScaling; + } + +#ifndef __SPU__ + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; +#endif + + + //debugging + virtual const char* getName()const {return "ConvexPointCloud";} + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; + virtual void getVertex(int i,btVector3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; + virtual bool isInside(const btVector3& pt,btScalar tolerance) const; + + ///in case we receive negative scaling + virtual void setLocalScaling(const btVector3& scaling); +}; + + +#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp index 7afcccf8b03..7e67696f4c7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -14,5 +14,366 @@ subject to the following restrictions: */ #include "btConvexShape.h" +#include "btTriangleShape.h" +#include "btSphereShape.h" +#include "btCylinderShape.h" +#include "btCapsuleShape.h" +#include "btConvexHullShape.h" +#include "btConvexPointCloudShape.h" + +btConvexShape::btConvexShape () +{ +} + +btConvexShape::~btConvexShape() +{ + +} + +static btVector3 convexHullSupport (const btVector3& localDir, const btVector3* points, int numPoints, const btVector3& localScaling) +{ + btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); + btScalar newDot,maxDot = btScalar(-1e30); + + btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ()); + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + + for (int i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + return btVector3(supVec.getX(),supVec.getY(),supVec.getZ()); +} + +btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + return btVector3(0,0,0); + } + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + const btVector3& halfExtents = convexShape->getImplicitShapeDimensions(); + + return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()), + btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()), + btFsels(localDir.z(), halfExtents.z(), -halfExtents.z())); + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ()); + btVector3* vertices = &triangleShape->m_vertices1[0]; + btVector3 dots(dir.dot(vertices[0]), dir.dot(vertices[1]), dir.dot(vertices[2])); + btVector3 sup = vertices[dots.maxAxis()]; + return btVector3(sup.getX(),sup.getY(),sup.getZ()); + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShape* cylShape = (btCylinderShape*)this; + //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis) + + btVector3 halfExtents = cylShape->getImplicitShapeDimensions(); + btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ()); + int cylinderUpAxis = cylShape->getUpAxis(); + int XX(1),YY(0),ZZ(2); + + switch (cylinderUpAxis) + { + case 0: + { + XX = 1; + YY = 0; + ZZ = 2; + } + break; + case 1: + { + XX = 0; + YY = 1; + ZZ = 2; + } + break; + case 2: + { + XX = 0; + YY = 2; + ZZ = 1; + + } + break; + default: + btAssert(0); + break; + }; + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return btVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } else { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return btVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ()); + + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + btScalar halfHeight = capsuleShape->getHalfHeight(); + int capsuleUpAxis = capsuleShape->getUpAxis(); + + btScalar radius = capsuleShape->getRadius(); + btVector3 supVec(0,0,0); + + btScalar maxDot(btScalar(-1e30)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + btVector3 vtx; + btScalar newDot; + { + btVector3 pos(0,0,0); + pos[capsuleUpAxis] = halfHeight; + + //vtx = pos +vec*(radius); + vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV(); + newDot = vec.dot(vtx); + + + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + { + btVector3 pos(0,0,0); + pos[capsuleUpAxis] = -halfHeight; + + //vtx = pos +vec*(radius); + vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + return btVector3(supVec.getX(),supVec.getY(),supVec.getZ()); + } + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + { + btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this; + btVector3* points = convexPointCloudShape->getUnscaledPoints (); + int numPoints = convexPointCloudShape->getNumPoints (); + return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV()); + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btConvexHullShape* convexHullShape = (btConvexHullShape*)this; + btVector3* points = convexHullShape->getUnscaledPoints(); + int numPoints = convexHullShape->getNumPoints (); + return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV()); + } + default: +#ifndef __SPU__ + return this->localGetSupportingVertexWithoutMargin (localDir); +#else + btAssert (0); +#endif + } + + // should never reach here + btAssert (0); + return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f)); +} + +btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const +{ + btVector3 localDirNorm = localDir; + if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + localDirNorm.normalize (); + + return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm; +} + +/* TODO: This should be bumped up to btCollisionShape () */ +btScalar btConvexShape::getMarginNonVirtual () const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + btSphereShape* sphereShape = (btSphereShape*)this; + return sphereShape->getRadius (); + } + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + return convexShape->getMarginNV (); + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + return triangleShape->getMarginNV (); + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShape* cylShape = (btCylinderShape*)this; + return cylShape->getMarginNV(); + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + return capsuleShape->getMarginNV(); + } + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + /* fall through */ + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this; + return convexHullShape->getMarginNV(); + } + default: +#ifndef __SPU__ + return this->getMargin (); +#else + btAssert (0); +#endif + } + + // should never reach here + btAssert (0); + return btScalar(0.0f); +} + +void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + btSphereShape* sphereShape = (btSphereShape*)this; + btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX(); + btScalar margin = radius + sphereShape->getMarginNonVirtual(); + const btVector3& center = t.getOrigin(); + btVector3 extent(margin,margin,margin); + aabbMin = center - extent; + aabbMax = center + extent; + } + break; + case CYLINDER_SHAPE_PROXYTYPE: + /* fall through */ + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + btScalar margin=convexShape->getMarginNonVirtual(); + btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); + halfExtents += btVector3(margin,margin,margin); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 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; + break; + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + btScalar margin = triangleShape->getMarginNonVirtual(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()); + + btVector3 tmp = t(sv); + aabbMax[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis())); + aabbMin[i] = tmp[i]-margin; + } + } + break; + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius()); + int m_upAxis = capsuleShape->getUpAxis(); + halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight(); + halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual()); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 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; + } + break; + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this; + btScalar margin = convexHullShape->getMarginNonVirtual(); + convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin); + } + break; + default: +#ifndef __SPU__ + this->getAabb (t, aabbMin, aabbMax); +#else + btAssert (0); +#endif + break; + } + + // should never reach here + btAssert (0); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h index e4eb7f6dbf6..0cc7b349521 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -24,8 +24,6 @@ subject to the following restrictions: #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. @@ -38,20 +36,25 @@ public: BT_DECLARE_ALIGNED_ALLOCATOR(); - virtual ~btConvexShape() - { + btConvexShape (); - } + virtual ~btConvexShape(); + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const = 0; + + //////// + #ifndef __SPU__ + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const=0; + #endif //#ifndef __SPU__ + + btVector3 localGetSupportVertexWithoutMarginNonVirtual (const btVector3& vec) const; + btVector3 localGetSupportVertexNonVirtual (const btVector3& vec) const; + btScalar getMarginNonVirtual () const; + void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const; - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const =0; -#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__ - ///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; @@ -69,6 +72,9 @@ public: virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; + + + }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp index 02a293e82ba..4bd986bb7f7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -20,8 +20,9 @@ subject to the following restrictions: btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb) -:m_stridingMesh(meshInterface) +: btPolyhedralConvexShape(), m_stridingMesh(meshInterface) { + m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; if ( calcAabb ) recalcLocalAabb(); } @@ -107,7 +108,7 @@ void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargi } } - //todo: could do the batch inside the callback! + ///@todo: could do the batch inside the callback! for (int j=0;j 1 && "bad width"); + btAssert(heightStickLength > 1 && "bad length"); + btAssert(heightfieldData && "null heightfield data"); + // btAssert(heightScale) -- do we care? Trust caller here + btAssert(minHeight <= maxHeight && "bad min/max height"); + btAssert(upAxis >= 0 && upAxis < 3 && + "bad upAxis--should be in range [0,2]"); + btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT && + "Bad height data type enum"); + + // initialize member variables + m_shapeType = TERRAIN_SHAPE_PROXYTYPE; + m_heightStickWidth = heightStickWidth; + m_heightStickLength = heightStickLength; + m_minHeight = minHeight; + m_maxHeight = maxHeight; + m_width = (btScalar) (heightStickWidth - 1); + m_length = (btScalar) (heightStickLength - 1); + m_heightScale = heightScale; + m_heightfieldDataUnknown = heightfieldData; + m_heightDataType = hdt; + m_flipQuadEdges = flipQuadEdges; + m_useDiamondSubdivision = false; + m_upAxis = upAxis; + m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.)); + + // determine min/max axis-aligned bounding box (aabb) values switch (m_upAxis) { case 0: { - halfExtents.setValue( - btScalar(m_maxHeight), - btScalar(m_width), //?? don't know if this should change - btScalar(m_length)); + m_localAabbMin.setValue(m_minHeight, 0, 0); + m_localAabbMax.setValue(m_maxHeight, m_width, m_length); break; } case 1: { - halfExtents.setValue( - btScalar(m_width), - btScalar(m_maxHeight), - btScalar(m_length)); + m_localAabbMin.setValue(0, m_minHeight, 0); + m_localAabbMax.setValue(m_width, m_maxHeight, m_length); break; }; case 2: { - halfExtents.setValue( - btScalar(m_width), - btScalar(m_length), - btScalar(m_maxHeight) - ); + m_localAabbMin.setValue(0, 0, m_minHeight); + m_localAabbMax.setValue(m_width, m_length, m_maxHeight); break; } default: { //need to get valid m_upAxis - btAssert(0); + btAssert(0 && "Bad m_upAxis"); } } - halfExtents*= btScalar(0.5); - - m_localAabbMin = -halfExtents - clampValue; - m_localAabbMax = halfExtents + clampValue; - btVector3 aabbSize = m_localAabbMax - m_localAabbMin; - + // remember origin (defined as exact middle of aabb) + m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax); } + btHeightfieldTerrainShape::~btHeightfieldTerrainShape() { } @@ -92,57 +128,80 @@ btHeightfieldTerrainShape::~btHeightfieldTerrainShape() void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5); - halfExtents += btVector3(getMargin(),getMargin(),getMargin()); + + btVector3 localOrigin(0, 0, 0); + localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5); + localOrigin *= m_localScaling; btMatrix3x3 abs_b = t.getBasis().absolute(); - btPoint3 center = t.getOrigin(); + btVector3 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; - - } -btScalar btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const + +/// This returns the "raw" (user's initial) height, not the actual height. +/// The actual height needs to be adjusted to be relative to the center +/// of the heightfield's AABB. +btScalar +btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const { btScalar val = 0.f; - if (m_useFloatData) + switch (m_heightDataType) { - val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x]; - } else - { - //assume unsigned short int - unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x]; - val = heightFieldValue* (m_maxHeight/btScalar(65535)); + case PHY_FLOAT: + { + val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x]; + break; + } + + case PHY_UCHAR: + { + unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x]; + val = heightFieldValue * m_heightScale; + break; + } + + case PHY_SHORT: + { + short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x]; + val = hfValue * m_heightScale; + break; + } + + default: + { + btAssert(!"Bad m_heightDataType"); + } } + return val; } - +/// this returns the vertex in bullet-local coordinates void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const { - btAssert(x>=0); btAssert(y>=0); btAssert(xstartX) startX = quantizedAabbMin[1]; if (quantizedAabbMax[1]startX) startX = quantizedAabbMin[0]; if (quantizedAabbMax[0]startX) startX = quantizedAabbMin[0]; if (quantizedAabbMax[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; - } + + + /// protected initialization + /** + Handles the work of constructors so that public constructors can be + backwards-compatible without a lot of copy/paste. + */ + void initialize(int heightStickWidth, int heightStickLength, + void* heightfieldData, btScalar heightScale, + btScalar minHeight, btScalar maxHeight, int upAxis, + PHY_ScalarType heightDataType, bool flipQuadEdges); public: - btHeightfieldTerrainShape(int heightStickWidth,int heightStickHeight,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); + /// preferred constructor + /** + This constructor supports a range of heightfield + data types, and allows for a non-zero minimum height value. + heightScale is needed for any integer-based heightfield data types. + */ + btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength, + void* heightfieldData, btScalar heightScale, + btScalar minHeight, btScalar maxHeight, + int upAxis, PHY_ScalarType heightDataType, + bool flipQuadEdges); + + /// legacy constructor + /** + The legacy constructor assumes the heightfield has a minimum height + of zero. Only unsigned char or floats are supported. For legacy + compatibility reasons, heightScale is calculated as maxHeight / 65535 + (and is only used when useFloatData = false). + */ + btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); virtual ~btHeightfieldTerrainShape(); void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;} - virtual int getShapeType() const - { - return TERRAIN_SHAPE_PROXYTYPE; - } virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp index 8f893ac98aa..b107b0bea6e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp @@ -17,23 +17,25 @@ subject to the following restrictions: btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB) -:m_shapeA(shapeA), +: btConvexInternalShape (), +m_shapeA(shapeA), m_shapeB(shapeB) { + m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE; m_transA.setIdentity(); m_transB.setIdentity(); } btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(-vec*m_transA.getBasis())); - btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(vec*m_transB.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; } void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { - //todo: could make recursive use of batching. probably this shape is not used frequently. + ///@todo: could make recursive use of batching. probably this shape is not used frequently. for (int i=0;iprocessAllTriangles(&triBuf,aabbMin, aabbMax); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp index b962829041a..5f292532861 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp @@ -82,7 +82,8 @@ bool btTriangleIndexVertexArray::hasPremadeAabb() const return (m_hasAabb == 1); } -void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) + +void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const { m_aabbMin = aabbMin; m_aabbMax = aabbMax; @@ -95,3 +96,4 @@ void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* a *aabbMax = m_aabbMax; } + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h index e546675f802..eb79ff5e47d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h @@ -52,9 +52,9 @@ ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshIn 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; + mutable int m_hasAabb; // using int instead of bool to maintain alignment + mutable btVector3 m_aabbMin; + mutable btVector3 m_aabbMax; public: @@ -106,7 +106,7 @@ public: virtual void preallocateIndices(int numindices){(void) numindices;} virtual bool hasPremadeAabb() const; - virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ); + virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const; 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 index 492854ff646..abefa71250a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp @@ -1,3 +1,4 @@ + /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp index 29d26316316..5dcfa51c280 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp @@ -35,13 +35,13 @@ m_weldingThreshold(0.0) 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_triangleIndexBase = 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_triangleIndexBase = 0; m_indexedMeshes[0].m_indexType = PHY_SHORT; m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int); } @@ -49,12 +49,12 @@ m_weldingThreshold(0.0) 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_vertexBase = 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_vertexBase = 0; m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar); } @@ -74,17 +74,21 @@ void btTriangleMesh::addIndex(int index) } } -int btTriangleMesh::findOrAddVertex(const btVector3& vertex) + +int btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices) { //return index of new/existing vertex - //todo: could use acceleration structure for this + ///@todo: could use acceleration structure for this if (m_use4componentVertices) { - for (int i=0;i< m_4componentVertices.size();i++) - { - if ((m_4componentVertices[i]-vertex).length2() <= m_weldingThreshold) + if (removeDuplicateVertices) { - return i; + for (int i=0;i< m_4componentVertices.size();i++) + { + if ((m_4componentVertices[i]-vertex).length2() <= m_weldingThreshold) + { + return i; + } } } m_indexedMeshes[0].m_numVertices++; @@ -96,17 +100,20 @@ int btTriangleMesh::findOrAddVertex(const btVector3& vertex) } else { - for (int i=0;i< m_3componentVertices.size();i+=3) + if (removeDuplicateVertices) { - btVector3 vtx(m_3componentVertices[i],m_3componentVertices[i+1],m_3componentVertices[i+2]); - if ((vtx-vertex).length2() <= m_weldingThreshold) + for (int i=0;i< m_3componentVertices.size();i+=3) { - return i/3; + btVector3 vtx(m_3componentVertices[i],m_3componentVertices[i+1],m_3componentVertices[i+2]); + if ((vtx-vertex).length2() <= m_weldingThreshold) + { + return i/3; + } } - } - m_3componentVertices.push_back(vertex.getX()); - m_3componentVertices.push_back(vertex.getY()); - m_3componentVertices.push_back(vertex.getZ()); + } + m_3componentVertices.push_back((float)vertex.getX()); + m_3componentVertices.push_back((float)vertex.getY()); + m_3componentVertices.push_back((float)vertex.getZ()); m_indexedMeshes[0].m_numVertices++; m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; return (m_3componentVertices.size()/3)-1; @@ -114,13 +121,12 @@ int btTriangleMesh::findOrAddVertex(const btVector3& vertex) } -void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) +void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2,bool removeDuplicateVertices) { m_indexedMeshes[0].m_numTriangles++; - - addIndex(findOrAddVertex(vertex0)); - addIndex(findOrAddVertex(vertex1)); - addIndex(findOrAddVertex(vertex2)); + addIndex(findOrAddVertex(vertex0,removeDuplicateVertices)); + addIndex(findOrAddVertex(vertex1,removeDuplicateVertices)); + addIndex(findOrAddVertex(vertex2,removeDuplicateVertices)); } int btTriangleMesh::getNumTriangles() const diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h index 1f51b2f2c87..f06fbb7c22d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h @@ -25,7 +25,6 @@ subject to the following restrictions: ///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. -///It has a brute-force option to weld together closeby vertices. class btTriangleMesh : public btTriangleIndexVertexArray { btAlignedObjectArray m_4componentVertices; @@ -42,7 +41,7 @@ class btTriangleMesh : public btTriangleIndexVertexArray btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true); - int findOrAddVertex(const btVector3& vertex); + int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices); void addIndex(int index); bool getUse32bitIndices() const @@ -54,8 +53,9 @@ class btTriangleMesh : public btTriangleIndexVertexArray { return m_use4componentVertices; } - - void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2); + ///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes. + ///In general it is better to directly use btTriangleIndexVertexArray instead. + void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2, bool removeDuplicateVertices=false); int getNumTriangles() const; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp index 0a2c77096d1..1bd7e84a4e7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -22,8 +22,9 @@ subject to the following restrictions: btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) -: m_meshInterface(meshInterface) +: btConcaveShape (), m_meshInterface(meshInterface) { + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; if(meshInterface->hasPremadeAabb()) { meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax); @@ -52,7 +53,7 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt btMatrix3x3 abs_b = trans.getBasis().absolute(); - btPoint3 center = trans(localCenter); + btVector3 center = trans(localCenter); btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), abs_b[1].dot(localHalfExtents), diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h index c9eabafe290..53d65799001 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -40,7 +40,7 @@ public: virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - assert(0); + btAssert(0); return localGetSupportingVertex(vec); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h index ba7aa0c32a0..4bfb0b9e881 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -40,17 +40,13 @@ public: { vert = m_vertices1[index]; } - virtual int getShapeType() const - { - return TRIANGLE_SHAPE_PROXYTYPE; - } virtual int getNumEdges() const { return 3; } - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const { getVertex(i,pa); getVertex((i+1)%3,pb); @@ -83,15 +79,16 @@ public: - btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) + btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) : btPolyhedralConvexShape () { + m_shapeType = TRIANGLE_SHAPE_PROXYTYPE; m_vertices1[0] = p0; m_vertices1[1] = p1; m_vertices1[2] = p2; } - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i) const + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const { getPlaneEquation(i,planeNormal,planeSupport); } @@ -107,7 +104,7 @@ public: normal.normalize(); } - virtual void getPlaneEquation(int i, btVector3& planeNormal,btPoint3& planeSupport) const + virtual void getPlaneEquation(int i, btVector3& planeNormal,btVector3& planeSupport) const { (void)i; calcNormal(planeNormal); @@ -121,7 +118,7 @@ public: inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); } - virtual bool isInside(const btPoint3& pt,btScalar tolerance) const + virtual bool isInside(const btVector3& pt,btScalar tolerance) const { btVector3 normal; calcNormal(normal); @@ -135,7 +132,7 @@ public: int i; for (i=0;i<3;i++) { - btPoint3 pa,pb; + btVector3 pa,pb; getEdge(i,pa,pb); btVector3 edge = pb-pa; btVector3 edgeNormal = edge.cross(normal); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp index ef340286cb0..4c1c716d519 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp @@ -16,9 +16,10 @@ subject to the following restrictions: #include "btUniformScalingShape.h" btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor): -m_childConvexShape(convexChildShape), +btConvexShape (), m_childConvexShape(convexChildShape), m_uniformScalingFactor(uniformScalingFactor) { + m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE; } btUniformScalingShape::~btUniformScalingShape() diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h index 1e17fc8e198..945976ac036 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h @@ -61,7 +61,6 @@ class btUniformScalingShape : public btConvexShape return "UniformScalingShape"; } - virtual int getShapeType() const { return UNIFORM_SCALING_SHAPE_PROXYTYPE; } /////////////////////////// diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h b/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h index cf43f487e24..827a3c89587 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h @@ -26,9 +26,6 @@ subject to the following restrictions: #include "LinearMath/btTransform.h" -/*! \defgroup BOUND_AABB_OPERATIONS -*/ -//! @{ ///Swap numbers #define BT_SWAP_NUMBERS(a,b){ \ @@ -41,7 +38,7 @@ subject to the following restrictions: #define BT_MAX(a,b) (ab?b:a) -#define BT_GREATER(x, y) fabsf(x) > (y) +#define BT_GREATER(x, y) btFabs(x) > (y) #define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c)) #define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c)) @@ -181,7 +178,7 @@ public: { for(j=0;j<3;j++ ) { - m_AR[i][j] = 1e-6f + fabsf(m_R1to0[i][j]); + m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]); } } @@ -646,6 +643,5 @@ SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btT } -//! @} #endif // GIM_BOX_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h b/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h index 28c03b7e039..5de391a7561 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h @@ -27,9 +27,6 @@ subject to the following restrictions: #include "LinearMath/btTransform.h" #include "LinearMath/btGeometryUtil.h" -/*! \addtogroup GEOMETRIC_OPERATIONS -*/ -//! @{ SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point) { @@ -181,6 +178,5 @@ SIMD_FORCE_INLINE int bt_plane_clip_triangle( -//! @} #endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp index faba2d8a542..c3b697bdd1e 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp +++ b/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp @@ -103,12 +103,12 @@ void btContactArray::merge_contacts( push_back(contacts[keycontacts[0].m_value]); - BT_CONTACT * pcontact = &(*this)[0]; + GIM_CONTACT * pcontact = &(*this)[0]; for( i=1;i +class btContactArray:public btAlignedObjectArray { public: btContactArray() @@ -124,11 +120,11 @@ public: const btVector3 &point,const btVector3 & normal, btScalar depth, int feature1, int feature2) { - push_back( BT_CONTACT(point,normal,depth,feature1,feature2) ); + push_back( GIM_CONTACT(point,normal,depth,feature1,feature2) ); } SIMD_FORCE_INLINE void push_triangle_contacts( - const BT_TRIANGLE_CONTACT & tricontact, + const GIM_TRIANGLE_CONTACT & tricontact, int feature1,int feature2) { for(int i = 0;i>1); } - bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); - btAssert(!unbal); + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); return splitIndex; } -void btBvhTree::_build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) +void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) { int curIndex = m_num_nodes; m_num_nodes++; @@ -211,7 +210,7 @@ void btBvhTree::_build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIn //! stackless build tree void btBvhTree::build_tree( - BT_BVH_DATA_ARRAY & primitive_boxes) + GIM_BVH_DATA_ARRAY & primitive_boxes) { // initialize node count to 0 m_num_nodes = 0; @@ -236,7 +235,7 @@ void btGImpactBvh::refit() } else { - //const BT_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); + //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); //get left bound btAABB bound; bound.invalidate(); @@ -266,7 +265,7 @@ void btGImpactBvh::refit() void btGImpactBvh::buildSet() { //obtain primitive boxes - BT_BVH_DATA_ARRAY primitive_boxes; + GIM_BVH_DATA_ARRAY primitive_boxes; primitive_boxes.resize(m_primitive_manager->get_primitive_count()); for (int i = 0;i +class btPairSet: public btAlignedObjectArray { public: btPairSet() @@ -71,32 +65,32 @@ public: } inline void push_pair(int index1,int index2) { - push_back(BT_PAIR(index1,index2)); + push_back(GIM_PAIR(index1,index2)); } inline void push_pair_inv(int index1,int index2) { - push_back(BT_PAIR(index2,index1)); + push_back(GIM_PAIR(index2,index1)); } }; - -struct BT_BVH_DATA +///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box +struct GIM_BVH_DATA { btAABB m_bound; int m_data; }; //! Node Structure for trees -class BT_BVH_TREE_NODE +class GIM_BVH_TREE_NODE { public: btAABB m_bound; protected: int m_escapeIndexOrDataIndex; public: - BT_BVH_TREE_NODE() + GIM_BVH_TREE_NODE() { m_escapeIndexOrDataIndex = 0; } @@ -133,12 +127,12 @@ public: }; -class BT_BVH_DATA_ARRAY:public btAlignedObjectArray +class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray { }; -class BT_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray +class GIM_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray { }; @@ -150,15 +144,15 @@ class btBvhTree { protected: int m_num_nodes; - BT_BVH_TREE_NODE_ARRAY m_node_array; + GIM_BVH_TREE_NODE_ARRAY m_node_array; protected: int _sort_and_calc_splitting_index( - BT_BVH_DATA_ARRAY & primitive_boxes, + GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex, int splitAxis); - int _calc_splitting_axis(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); - void _build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); public: btBvhTree() { @@ -167,7 +161,7 @@ public: //! prototype functions for box tree management //!@{ - void build_tree(BT_BVH_DATA_ARRAY & primitive_boxes); + void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes); SIMD_FORCE_INLINE void clearNodes() { @@ -218,7 +212,7 @@ public: return m_node_array[nodeindex].getEscapeIndex(); } - SIMD_FORCE_INLINE const BT_BVH_TREE_NODE * get_node_pointer(int index = 0) const + SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const { return &m_node_array[index]; } @@ -382,12 +376,11 @@ public: } - SIMD_FORCE_INLINE const BT_BVH_TREE_NODE * get_node_pointer(int index = 0) const + SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const { return m_box_tree.get_node_pointer(index); } -//! @} static float getAverageTreeCollisionTime(); diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp index 28ad18fbde2..4d6fa88f62d 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp @@ -192,7 +192,7 @@ float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime() btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) -: btCollisionAlgorithm(ci) +: btActivatingCollisionAlgorithm(ci,body0,body1) { m_manifoldPtr = NULL; m_convex_algorithm = NULL; @@ -404,7 +404,7 @@ void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body btPrimitiveTriangle ptri0; btPrimitiveTriangle ptri1; - BT_TRIANGLE_CONTACT contact_data; + GIM_TRIANGLE_CONTACT contact_data; shape0->lockChildShapes(); shape1->lockChildShapes(); @@ -540,7 +540,7 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact( int i = pairset.size(); while(i--) { - BT_PAIR * pair = &pairset[i]; + GIM_PAIR * pair = &pairset[i]; m_triface0 = pair->m_index1; m_triface1 = pair->m_index2; btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0); @@ -584,14 +584,15 @@ void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0, if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) { btGImpactMeshShape * meshshape0 = static_cast(shape0); - m_part0 = meshshape0->getMeshPartCount(); + int& part = swapped ? m_part1 : m_part0; + part = meshshape0->getMeshPartCount(); - while(m_part0--) + while(part--) { gimpact_vs_shape(body0, body1, - meshshape0->getMeshPart(m_part0), + meshshape0->getMeshPart(part), shape1,swapped); } diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h index c745b7ed5d8..453472aa034 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h @@ -24,7 +24,7 @@ subject to the following restrictions: #ifndef BVH_CONCAVE_COLLISION_ALGORITHM_H #define BVH_CONCAVE_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" @@ -51,7 +51,7 @@ btCollisionDispatcher * dispatcher = static_cast(m_dyna btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); \endcode */ -class btGImpactCollisionAlgorithm : public btCollisionAlgorithm +class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm { protected: btCollisionAlgorithm * m_convex_algorithm; @@ -67,7 +67,7 @@ protected: //! Creates a new contact point SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1) { - m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); return m_manifoldPtr; } diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp index 0b1ef6acd83..ea1647a8129 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp @@ -67,7 +67,7 @@ float btGImpactQuantizedBvh::getAverageTreeCollisionTime() /////////////////////// btQuantizedBvhTree ///////////////////////////////// void btQuantizedBvhTree::calc_quantization( - BT_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin) + GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin) { //calc globa box btAABB global_bound; @@ -86,7 +86,7 @@ void btQuantizedBvhTree::calc_quantization( int btQuantizedBvhTree::_calc_splitting_axis( - BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) + GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) { int i; @@ -118,7 +118,7 @@ int btQuantizedBvhTree::_calc_splitting_axis( int btQuantizedBvhTree::_sort_and_calc_splitting_index( - BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, + GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex, int splitAxis) { int i; @@ -171,15 +171,14 @@ int btQuantizedBvhTree::_sort_and_calc_splitting_index( splitIndex = startIndex+ (numIndices>>1); } - bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); - btAssert(!unbal); + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); return splitIndex; } -void btQuantizedBvhTree::_build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) +void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) { int curIndex = m_num_nodes; m_num_nodes++; @@ -232,7 +231,7 @@ void btQuantizedBvhTree::_build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, in //! stackless build tree void btQuantizedBvhTree::build_tree( - BT_BVH_DATA_ARRAY & primitive_boxes) + GIM_BVH_DATA_ARRAY & primitive_boxes) { calc_quantization(primitive_boxes); // initialize node count to 0 @@ -258,7 +257,7 @@ void btGImpactQuantizedBvh::refit() } else { - //const BT_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); + //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); //get left bound btAABB bound; bound.invalidate(); @@ -288,7 +287,7 @@ void btGImpactQuantizedBvh::refit() void btGImpactQuantizedBvh::buildSet() { //obtain primitive boxes - BT_BVH_DATA_ARRAY primitive_boxes; + GIM_BVH_DATA_ARRAY primitive_boxes; primitive_boxes.resize(m_primitive_manager->get_primitive_count()); for (int i = 0;i +class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray { }; @@ -112,19 +106,19 @@ class btQuantizedBvhTree { protected: int m_num_nodes; - BT_QUANTIZED_BVH_NODE_ARRAY m_node_array; + GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array; btAABB m_global_bound; btVector3 m_bvhQuantization; protected: - void calc_quantization(BT_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) ); + void calc_quantization(GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) ); int _sort_and_calc_splitting_index( - BT_BVH_DATA_ARRAY & primitive_boxes, + GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex, int splitAxis); - int _calc_splitting_axis(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); - void _build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); public: btQuantizedBvhTree() { @@ -133,7 +127,7 @@ public: //! prototype functions for box tree management //!@{ - void build_tree(BT_BVH_DATA_ARRAY & primitive_boxes); + void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes); SIMD_FORCE_INLINE void quantizePoint( unsigned short * quantizedpoint, const btVector3 & point) const @@ -365,7 +359,6 @@ public: return m_box_tree.get_node_pointer(index); } -//! @} static float getAverageTreeCollisionTime(); diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h index 43f32bea5a1..05431cfce15 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h @@ -105,6 +105,7 @@ protected: public: btGImpactShapeInterface() { + m_shapeType=GIMPACT_SHAPE_PROXYTYPE; m_localAABB.invalidate(); m_needs_update = true; localScaling.setValue(1.f,1.f,1.f); @@ -880,6 +881,8 @@ Set of btGImpactMeshShapePart parts */ class btGImpactMeshShape : public btGImpactShapeInterface { + btStridingMeshInterface* m_meshInterface; + protected: btAlignedObjectArray m_mesh_parts; void buildMeshParts(btStridingMeshInterface * meshInterface) @@ -906,6 +909,7 @@ protected: public: btGImpactMeshShape(btStridingMeshInterface * meshInterface) { + m_meshInterface = meshInterface; buildMeshParts(meshInterface); } @@ -921,6 +925,15 @@ public: } + btStridingMeshInterface* getMeshInterface() + { + return m_meshInterface; + } + + const btStridingMeshInterface* getMeshInterface() const + { + return m_meshInterface; + } int getMeshPartCount() const { @@ -1032,12 +1045,12 @@ public: } //! call when reading child shapes - virtual void lockChildShapes() + virtual void lockChildShapes() const { btAssert(0); } - virtual void unlockChildShapes() + virtual void unlockChildShapes() const { btAssert(0); } diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp index 4b4b5e20dd3..956fa0430e3 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp @@ -251,16 +251,16 @@ bool btGenericPoolAllocator::freeMemory(void * pointer) #define BT_DEFAULT_POOL_ELEMENT_SIZE 8 // main allocator -class BT_STANDARD_ALLOCATOR: public btGenericPoolAllocator +class GIM_STANDARD_ALLOCATOR: public btGenericPoolAllocator { public: - BT_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE) + GIM_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE) { } }; // global allocator -BT_STANDARD_ALLOCATOR g_main_allocator; +GIM_STANDARD_ALLOCATOR g_main_allocator; void * btPoolAlloc(size_t size) diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.h b/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.h index 05b79a82516..e883bcd23d2 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.h @@ -155,14 +155,9 @@ public: -/*! \defgroup POOL_MEMORY_FUNCTIONS -standar managed Memory functions. Memory pools are used. -*/ -//! @{ void * btPoolAlloc(size_t size); void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize); void btPoolFree(void *ptr); -//! @} #endif diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h b/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h index f5800716a96..bc5a416ddb7 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h @@ -29,9 +29,6 @@ subject to the following restrictions: -/*! \defgroup GEOMETRIC_OPERATIONS -*/ -//! @{ #define PLANEDIREPSILON 0.0000001f @@ -210,7 +207,6 @@ SIMD_FORCE_INLINE void bt_segment_collision( -//! @} #endif // GIM_VECTOR_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h b/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h index e9e6ad3d805..7faada61c95 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h @@ -29,9 +29,6 @@ subject to the following restrictions: -/*! \defgroup GEOMETRIC_OPERATIONS -*/ -//! @{ @@ -86,7 +83,6 @@ SIMD_FORCE_INLINE btVector3 bt_unquantize( return vecOut; } -//! @} #endif // GIM_VECTOR_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp index 0267f7e67c7..78696277c34 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp +++ b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp @@ -25,7 +25,7 @@ subject to the following restrictions: -void BT_TRIANGLE_CONTACT::merge_points(const btVector4 & plane, +void GIM_TRIANGLE_CONTACT::merge_points(const btVector4 & plane, btScalar margin, const btVector3 * points, int point_count) { m_point_count = 0; @@ -123,7 +123,7 @@ int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * return clipped_count; } -bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, BT_TRIANGLE_CONTACT & contacts) +bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts) { btScalar margin = m_margin + other.m_margin; @@ -132,7 +132,7 @@ bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangl //create planes // plane v vs U points - BT_TRIANGLE_CONTACT contacts1; + GIM_TRIANGLE_CONTACT contacts1; contacts1.m_separating_normal = m_plane; @@ -152,7 +152,7 @@ bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangl //Clip tri1 by tri2 edges - BT_TRIANGLE_CONTACT contacts2; + GIM_TRIANGLE_CONTACT contacts2; contacts2.m_separating_normal = other.m_plane; clipped_count = other.clip_triangle(*this,clipped_points); diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h index bdaa323d564..bbd6b630c02 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h @@ -35,14 +35,14 @@ subject to the following restrictions: #define MAX_TRI_CLIPPING 16 //! Structure for collision -struct BT_TRIANGLE_CONTACT +struct GIM_TRIANGLE_CONTACT { btScalar m_penetration_depth; int m_point_count; btVector4 m_separating_normal; btVector3 m_points[MAX_TRI_CLIPPING]; - SIMD_FORCE_INLINE void copy_from(const BT_TRIANGLE_CONTACT& other) + SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other) { m_penetration_depth = other.m_penetration_depth; m_separating_normal = other.m_separating_normal; @@ -54,11 +54,11 @@ struct BT_TRIANGLE_CONTACT } } - BT_TRIANGLE_CONTACT() + GIM_TRIANGLE_CONTACT() { } - BT_TRIANGLE_CONTACT(const BT_TRIANGLE_CONTACT& other) + GIM_TRIANGLE_CONTACT(const GIM_TRIANGLE_CONTACT& other) { copy_from(other); } @@ -123,7 +123,7 @@ public: /*! \pre this triangle and other must have their triangles calculated */ - bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, BT_TRIANGLE_CONTACT & contacts); + bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts); }; diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h index 89fbb5ab0a5..c8161d252d5 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h @@ -34,11 +34,6 @@ email: projectileman@yahoo.com #include "gim_memory.h" -/*! \addtogroup CONTAINERS -\brief -Abstract class for template containers -*/ -//! @{ #define GIM_ARRAY_GROW_INCREMENT 2 #define GIM_ARRAY_GROW_FACTOR 2 @@ -321,11 +316,10 @@ public: { resizeData(m_size); } -//!@} + }; -//! @} diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h index d4cbce04b5e..666abf7917a 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h @@ -40,9 +40,6 @@ email: projectileman@yahoo.com -/*! \defgroup GEOMETRIC_OPERATIONS -*/ -//! @{ #define PLANEDIREPSILON 0.0000001f @@ -541,7 +538,6 @@ SIMD_FORCE_INLINE void SORT_3_INDICES( -//! @} #endif // GIM_VECTOR_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h index 7784aeff140..322004a8d5b 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h @@ -34,11 +34,6 @@ email: projectileman@yahoo.com #include "gim_array.h" -/*! \addtogroup CONTAINERS -\brief -Abstract class for template containers -*/ -//! @{ #define GUINT_BIT_COUNT 32 #define GUINT_EXPONENT 5 @@ -122,7 +117,6 @@ public: }; -//! @} diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h index c9bb83e3653..0add5e4b99f 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h @@ -35,9 +35,6 @@ email: projectileman@yahoo.com #include "gim_basic_geometry_operations.h" #include "LinearMath/btTransform.h" -/*! \defgroup BOUND_AABB_OPERATIONS -*/ -//! @{ //SIMD_FORCE_INLINE bool test_cross_edge_box( @@ -589,6 +586,5 @@ SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btT } -//! @} #endif // GIM_BOX_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp index 1ffc2bbad78..0c3d7ba8db0 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp @@ -110,8 +110,7 @@ GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index( splitIndex = startIndex+ (numIndices>>1); } - bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); - btAssert(!unbal); + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); return splitIndex; } @@ -180,3 +179,4 @@ void GIM_BOX_TREE::build_tree( _build_sub_tree(primitive_boxes, 0, primitive_boxes.size()); } + diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h index ece5936de6b..1058a0872a5 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h @@ -40,12 +40,6 @@ email: projectileman@yahoo.com #include "gim_tri_collision.h" -/*! \defgroup BOX_PRUNNING - - - -*/ -//! @{ //! Overlapping pair struct GIM_PAIR @@ -446,7 +440,6 @@ public: m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle); } -//! @} }; //! Class for Box Tree Sets diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h index 62151cb97b7..a91fd3aa422 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h @@ -33,9 +33,6 @@ email: projectileman@yahoo.com ----------------------------------------------------------------------------- */ -/*! \addtogroup GEOMETRIC_OPERATIONS -*/ -//! @{ //! This function calcs the distance from a 3D plane class DISTANCE_PLANE_3D_FUNC @@ -209,6 +206,5 @@ SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D( } -//! @} #endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_contact.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_contact.h index 62df51b782f..ad3e12298fe 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_contact.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_contact.h @@ -36,17 +36,6 @@ email: projectileman@yahoo.com #include "gim_radixsort.h" #include "gim_array.h" -/*! \defgroup CONTACTS -\brief -Functions for managing and sorting contacts resulting from a collision query. -
    -
  • Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST -
  • After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY -
  • Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts -
- -*/ -//! @{ /** Configuration var for applying interpolation of contact normals @@ -55,6 +44,10 @@ Configuration var for applying interpolation of contact normals #define CONTACT_DIFF_EPSILON 0.00001f /// Structure for collision results +///Functions for managing and sorting contacts resulting from a collision query. +///Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST +///After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY +///Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts class GIM_CONTACT { public: @@ -168,5 +161,4 @@ public: void merge_contacts_unique(const gim_contact_array & contacts); }; -//! @} #endif // GIM_CONTACT_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_geom_types.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_geom_types.h index cd3e53dcc0c..2fb1e3f9e45 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_geom_types.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_geom_types.h @@ -36,11 +36,7 @@ email: projectileman@yahoo.com #include "gim_math.h" -/*! \defgroup GEOMETRIC_TYPES -\brief -Basic types and constants for geometry -*/ -//! @{ + //! Short Integer vector 2D typedef GSHORT vec2s[2]; @@ -95,7 +91,6 @@ typedef GREAL mat4f[4][4]; typedef GREAL quatf[4]; //typedef struct _aabb3f aabb3f; -//! @} diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_hash_table.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_hash_table.h index fd980dff5fa..93c66f81823 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_hash_table.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_hash_table.h @@ -34,11 +34,6 @@ email: projectileman@yahoo.com #include "gim_radixsort.h" -/*! \addtogroup CONTAINERS -\brief -Abstract class for collision objects -*/ -//! @{ #define GIM_INVALID_HASH 0xffffffff //!< A very very high value #define GIM_DEFAULT_HASH_TABLE_SIZE 380 @@ -204,12 +199,7 @@ protected: //SuperBufferedArray< _node_type > m_nodes; bool m_sorted; - /*! \defgroup HASH_TABLE_STRUCTURES - \brief - Hash table data management. The hash table has the indices to the corresponding m_nodes array - */ - //! @{ - + ///Hash table data management. The hash table has the indices to the corresponding m_nodes array GUINT * m_hash_table;//!< GUINT m_table_size;//!< GUINT m_node_size;//!< @@ -459,13 +449,8 @@ protected: } - //! @} - - /*! \defgroup SORTED_ARRAY_STRUCTURES - \brief - Sorted array data management. The hash table has the indices to the corresponding m_nodes array - */ - //! @{ + + ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array inline bool _erase_sorted(GUINT index) { if(index>=(GUINT)m_nodes.size()) return false; @@ -575,8 +560,7 @@ protected: return GIM_INVALID_HASH; } - //! @} - + public: @@ -913,8 +897,6 @@ public: }; -//! @} - #endif // GIM_CONTAINERS_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h index adf1c1c2ddf..0247d4e61cc 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h @@ -40,11 +40,6 @@ email: projectileman@yahoo.com -/*! \defgroup VECTOR_OPERATIONS -T -Operations for vectors : vec2f,vec3f and vec4f -*/ -//! @{ //! Zero out a 2D vector #define VEC_ZERO_2(a) \ @@ -446,13 +441,8 @@ Takes two vectors a, b, blends them together with s <=1 */ -//! @} -/*! \defgroup MATRIX_OPERATIONS -Operations for matrices : mat2f, mat3f and mat4f -*/ -//! @{ /// initialize matrix #define IDENTIFY_MATRIX_3X3(m) \ @@ -1579,6 +1569,5 @@ and m is a mat4f
}\ -//! @} #endif // GIM_VECTOR_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_math.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_math.h index 25ad1e21c7f..8b9e6806ef7 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_math.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_math.h @@ -35,13 +35,6 @@ email: projectileman@yahoo.com #include "LinearMath/btScalar.h" -/*! \defgroup BASIC_TYPES -Basic types and constants -Conventions: -Types starting with G -Constants starting with G_ -*/ -//! @{ #define GREAL btScalar #define GREAL2 double @@ -52,15 +45,7 @@ Constants starting with G_ #define GINT64 long long #define GUINT64 unsigned long long -//! @} -/*! \defgroup BASIC_CONSTANTS -Basic constants -Conventions: -Types starting with G -Constants starting with G_ -*/ -//! @{ #define G_PI 3.14159265358979f #define G_HALF_PI 1.5707963f @@ -73,14 +58,9 @@ Constants starting with G_ #define G_REAL_INFINITY FLT_MAX #define G_SIGN_BITMASK 0x80000000 #define G_EPSILON SIMD_EPSILON -//! @} -/*! \defgroup SCALAR_TYPES -\brief -Precision type constants -*/ -//! @{ + enum GIM_SCALAR_TYPES { G_STYPE_REAL =0, @@ -92,12 +72,8 @@ enum GIM_SCALAR_TYPES G_STYPE_INT64, G_STYPE_UINT64 }; -//! @} -/*! \defgroup MATH_FUNCTIONS -mathematical functions -*/ -//! @{ + #define G_DEGTORAD(X) ((X)*3.1415926f/180.0f) #define G_RADTODEG(X) ((X)*180.0f/3.1415926f) @@ -131,7 +107,7 @@ mathematical functions ///returns a clamped number #define GIM_CLAMP(number,minval,maxval) (numbermaxval?maxval:number)) -#define GIM_GREATER(x, y) fabsf(x) > (y) +#define GIM_GREATER(x, y) btFabs(x) > (y) ///Swap numbers #define GIM_SWAP_NUMBERS(a,b){ \ @@ -176,6 +152,6 @@ inline GREAL gim_sqrt(GREAL f) return r; } -//! @} + #endif // GIM_MATH_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_memory.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_memory.h index 469a8280f7d..fa99eebb60e 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/gim_memory.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_memory.h @@ -36,9 +36,6 @@ email: projectileman@yahoo.com #include "gim_math.h" #include -//#define PREFETCH 1 -//! \defgroup PREFETCH -//! @{ #ifdef PREFETCH #include // for prefetch #define pfval 64 @@ -53,13 +50,9 @@ email: projectileman@yahoo.com //! Prefetch 128 #define pf2(_x,_i) #endif -//! @} -/*! \defgroup ARRAY_UTILITIES -\brief -Functions for manip packed arrays of numbers -*/ -//! @{ + +///Functions for manip packed arrays of numbers #define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\ {\ for (GUINT _i_=0;_i_*(Ls))(d)); + return(((m_shapes[0])->*(Ls))(d)); } - inline btVector3 Support1(const btVector3& d) const + inline btVector3 Support1(const btVector3& d) const { - return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d)); + return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d)); } - inline btVector3 Support(const btVector3& d) const + inline btVector3 Support(const btVector3& d) const { - return(Support0(d)-Support1(-d)); + return(Support0(d)-Support1(-d)); } - btVector3 Support(const btVector3& d,U index) const + btVector3 Support(const btVector3& d,U index) const { - if(index) - return(Support1(d)); + if(index) + return(Support1(d)); else - return(Support0(d)); + return(Support0(d)); } }; -typedef MinkowskiDiff tShape; + typedef MinkowskiDiff tShape; -// GJK -struct GJK -{ -/* Types */ -struct sSV + // GJK + struct GJK { - 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) + /* 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() { - 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; + m_ray = btVector3(0,0,0); + m_nfree = 0; + m_status = eStatus::Failed; + m_current = 0; + m_distance = 0; } - if(sqdist>=0) - {/* Valid */ - ns.rank = 0; - m_ray = btVector3(0,0,0); - m_current = next; - for(U i=0,ni=cs.rank;i0?-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) { - ns.c[ns.rank] = cs.c[i]; - ns.p[ns.rank++] = weights[i]; - m_ray += cs.c[i]->w*weights[i]; + if((w-lastw[i]).length2()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) + /* Check for termination */ + const btScalar omega=dot(m_ray,w)/rl; + alpha=btMax(omega,alpha); + if(((rl-alpha)-(GJK_ACCURARY*rl))<=0) + {/* Return old simplex */ + removevertice(m_simplices[m_current]); + break; + } + /* Reduce simplex */ + btScalar weights[4]; + U mask=0; + switch(cs.rank) { - appendvertice(*m_simplex, p); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - appendvertice(*m_simplex,-p); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); + case 2: sqdist=projectorigin( cs.c[0]->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; } - } - } - 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) + 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)c[0]->w-m_simplex->c[3]->w, + switch(m_simplex->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) + void removevertice(sSimplex& simplex) { - const U j=imd3[i]; - const btScalar s=vl*dot(d,cross(dl[i],dl[j])); - if(s>0) + 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 subd=projectorigin(*vt[i],*vt[j],d,subw,subm); - if((mindist<0)||(subd0?-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) { - mindist = subd; - m = static_cast((subm&1?1<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()) + { -// EPA -struct EPA -{ -/* Types */ -typedef GJK::sSV sSV; -struct sFace - { - btVector3 n; - btScalar d; - btScalar p; - sSV* c[3]; - sFace* f[3]; - sFace* l[2]; - U1 e[3]; - U1 pass; - }; -struct sList - { - sFace* root; - U count; - sList() : root(0),count(0) {} - }; -struct sHorizon - { - sFace* cf; - sFace* ff; - U nf; - sHorizon() : cf(0),ff(0),nf(0) {} - }; -struct eStatus { enum _ { - Valid, - Touching, - Degenerated, - NonConvex, - InvalidHull, - OutOfFaces, - OutOfVertices, - AccuraryReached, - FallBack, - Failed };}; -/* Fields */ -eStatus::_ m_status; -GJK::sSimplex m_result; -btVector3 m_normal; -btScalar m_depth; -sSV m_sv_store[EPA_MAX_VERTICES]; -sFace m_fc_store[EPA_MAX_FACES]; -U m_nextsv; -sList m_hull; -sList m_stock; -/* Methods */ - EPA() - { - Initialize(); - } - - - static inline void bind(sFace* fa,U ea,sFace* fb,U eb) - { - fa->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), + /* 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) + 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; } + } + 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); + } } - 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); } - } - /* 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) + sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) { - face->d = dot(a->w,face->n)/l; - face->n /= l; - if(forced||(face->d>=-EPA_PLANE_EPS)) + if(m_stock.root) { - 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); + 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); } - else + sFace* findbest() { - 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)) + 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]) { - remove(m_hull,f); - append(m_stock,f); - return(true); + 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); } - } - 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); -} + // + 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); + } } @@ -775,87 +775,87 @@ using namespace gjkepa2_impl; // int btGjkEpaSolver2::StackSizeRequirement() { -return(sizeof(GJK)+sizeof(EPA)); + 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) + 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) + 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) + 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; + 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); + 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); + 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) + 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) + 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) + 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]; + w0+=shape.Support(epa.m_result.c[i]->d,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); + 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; + break; case GJK::eStatus::Failed: - results.status=sResults::GJK_Failed; - break; + results.status=sResults::GJK_Failed; + break; } -return(false); + return(false); } // @@ -865,49 +865,49 @@ btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position, 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) + 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) + 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; + 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); + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + const btVector3 delta= results.witnesses[1]- + results.witnesses[0]; + const btScalar margin= shape0->getMarginNonVirtual()+ + shape1.getMarginNonVirtual(); + 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(gjk_status==GJK::eStatus::Inside) { - if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results)) + 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); + 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); + return(SIMD_INFINITY); } // @@ -918,10 +918,10 @@ bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0, const btVector3& guess, sResults& results) { -if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results)) - return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false)); + if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results)) + return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false)); else - return(true); + return(true); } /* Symbols cleanup */ diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp index c4f84ed4d75..05573c7cfce 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp @@ -17,13 +17,14 @@ 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, const btTransform& transformA, const btTransform& transformB, - btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, + btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB, class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc ) { @@ -33,20 +34,12 @@ 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..68dbc566518 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h @@ -28,7 +28,7 @@ class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver bool calcPenDepth( btSimplexSolverInterface& simplexSolver, const btConvexShape* pConvexA, const btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, - btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, + btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); private : diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp index 01fb1a4b068..0856332d1ca 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -18,11 +18,15 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" #include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" + + #if defined(DEBUG) || defined (_DEBUG) +//#define TEST_NON_VIRTUAL 1 #include //for debug printf #ifdef __SPU__ #include #define printf spu_printf +//#define DEBUG_SPU_COLLISION_DETECTION 1 #endif //__SPU__ #endif @@ -49,6 +53,8 @@ m_catchDegeneracies(1) void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) { + m_cachedSeparatingDistance = 0.f; + btScalar distance=btScalar(0.); btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.)); btVector3 pointOnA,pointOnB; @@ -58,16 +64,35 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& localTransA.getOrigin() -= positionOffset; localTransB.getOrigin() -= positionOffset; +#ifdef __SPU__ + btScalar marginA = m_minkowskiA->getMarginNonVirtual(); + btScalar marginB = m_minkowskiB->getMarginNonVirtual(); +#else btScalar marginA = m_minkowskiA->getMargin(); btScalar marginB = m_minkowskiB->getMargin(); +#ifdef TEST_NON_VIRTUAL + btScalar marginAv = m_minkowskiA->getMarginNonVirtual(); + btScalar marginBv = m_minkowskiB->getMarginNonVirtual(); + btAssert(marginA == marginAv); + btAssert(marginB == marginBv); +#endif //TEST_NON_VIRTUAL +#endif + + gNumGjkChecks++; +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("inside gjk\n"); +#endif //for CCD we don't use margins if (m_ignoreMargin) { marginA = btScalar(0.); marginB = btScalar(0.); +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("ignoring margin\n"); +#endif } m_curIter = 0; @@ -98,18 +123,35 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis(); btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis(); +#ifdef __SPU__ + btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); +#else btVector3 pInA = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); btVector3 qInB = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); - btPoint3 pWorld = localTransA(pInA); - btPoint3 qWorld = localTransB(qInB); - +#ifdef TEST_NON_VIRTUAL + btVector3 pInAv = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); + btVector3 qInBv = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); + btAssert((pInAv-pInA).length() < 0.0001); + btAssert((qInBv-qInB).length() < 0.0001); +#endif // +#endif //__SPU__ + + btVector3 pWorld = localTransA(pInA); + btVector3 qWorld = localTransB(qInB); + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("got local supporting vertices\n"); +#endif + btVector3 w = pWorld - qWorld; delta = m_cachedSeparatingAxis.dot(w); // potential exit, they don't overlap if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared)) { - checkPenetration = false; + checkSimplex=true; + //checkPenetration = false; break; } @@ -133,9 +175,15 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& checkSimplex = true; break; } + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("addVertex 1\n"); +#endif //add current vertex to simplex m_simplexSolver->addVertex(w, pWorld, qWorld); - +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("addVertex 2\n"); +#endif //calculate the closest point to the origin (update vector v) if (!m_simplexSolver->closest(m_cachedSeparatingAxis)) { @@ -167,7 +215,7 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject if (m_curIter++ > gGjkMaxIter) { - #if defined(DEBUG) || defined (_DEBUG) + #if defined(DEBUG) || defined (_DEBUG) || defined (DEBUG_SPU_COLLISION_DETECTION) printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter); printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n", @@ -290,10 +338,20 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& #endif //__CELLOS_LV2__ +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("output 1\n"); +#endif + m_cachedSeparatingAxis = normalInB; + m_cachedSeparatingDistance = distance; + output.addContactPoint( normalInB, pointOnB+positionOffset, distance); + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("output 2\n"); +#endif //printf("gjk add:%f",distance); } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h index 550fc4677e0..0ad4aab8a59 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h @@ -20,7 +20,6 @@ subject to the following restrictions: #define GJK_PAIR_DETECTOR_H #include "btDiscreteCollisionDetectorInterface.h" -#include "LinearMath/btPoint3.h" #include "BulletCollision/CollisionShapes/btCollisionMargin.h" class btConvexShape; @@ -38,6 +37,7 @@ class btGjkPairDetector : public btDiscreteCollisionDetectorInterface const btConvexShape* m_minkowskiA; const btConvexShape* m_minkowskiB; bool m_ignoreMargin; + btScalar m_cachedSeparatingDistance; public: @@ -68,6 +68,15 @@ public: m_cachedSeparatingAxis = seperatingAxis; } + const btVector3& getCachedSeparatingAxis() const + { + return m_cachedSeparatingAxis; + } + btScalar getCachedSeparatingDistance() const + { + return m_cachedSeparatingDistance; + } + void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver) { m_penetrationDepthSolver = penetrationDepthSolver; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h index e75fc1bee96..c7c9812985d 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h @@ -32,6 +32,8 @@ class btManifoldPoint :m_userPersistentData(0), m_appliedImpulse(0.f), m_lateralFrictionInitialized(false), + m_appliedImpulseLateral1(0.f), + m_appliedImpulseLateral2(0.f), m_lifeTime(0) { } @@ -110,6 +112,12 @@ class btManifoldPoint m_distance1 = dist; } + ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver + btScalar getAppliedImpulse() const + { + return m_appliedImpulse; + } + }; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp index 0e6fa2e6dfe..581b4258f03 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp @@ -19,9 +19,6 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" - - - #define NUM_UNITSPHERE_POINTS 42 static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = { @@ -73,7 +70,7 @@ btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver, const btConvexShape* convexA,const btConvexShape* convexB, const btTransform& transA,const btTransform& transB, - btVector3& v, btPoint3& pa, btPoint3& pb, + btVector3& v, btVector3& pa, btVector3& pb, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ) { @@ -117,7 +114,9 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s btVector3 seperatingAxisInA,seperatingAxisInB; btVector3 pInA,qInB,pWorld,qWorld,w; +#ifndef __SPU__ #define USE_BATCHED_SUPPORT 1 +#endif #ifdef USE_BATCHED_SUPPORT btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; @@ -200,6 +199,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s int numSampleDirections = NUM_UNITSPHERE_POINTS; +#ifndef __SPU__ { int numPDA = convexA->getNumPreferredPenetrationDirections(); if (numPDA) @@ -229,14 +229,15 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s } } } +#endif // __SPU__ for (int i=0;ilocalGetSupportingVertexWithoutMargin(seperatingAxisInA); - qInB = convexB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); + pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); pWorld = transA(pInA); qWorld = transB(qInB); w = qWorld - pWorld; @@ -254,13 +255,13 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s //add the margins - minA += minNorm*convexA->getMargin(); - minB -= minNorm*convexB->getMargin(); + minA += minNorm*convexA->getMarginNonVirtual(); + minB -= minNorm*convexB->getMarginNonVirtual(); //no penetration if (minProj < btScalar(0.)) return false; - minProj += (convexA->getMargin() + convexB->getMargin()); + minProj += (convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual()); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h index 27b42c2b47e..23cbd57ac7e 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h @@ -27,10 +27,9 @@ public: virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, const btConvexShape* convexA,const btConvexShape* convexB, const btTransform& transA,const btTransform& transB, - btVector3& v, btPoint3& pa, btPoint3& pb, + btVector3& v, btVector3& pa, btVector3& pb, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); - }; #endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp index 386885d2ac8..d4e29882d37 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp @@ -16,7 +16,7 @@ subject to the following restrictions: #include "btPersistentManifold.h" #include "LinearMath/btTransform.h" -#include + btScalar gContactBreakingThreshold = btScalar(0.02); ContactDestroyedCallback gContactDestroyedCallback = 0; @@ -66,7 +66,7 @@ void btPersistentManifold::clearUserCache(btManifoldPoint& pt) printf("error in clearUserCache\n"); } } - assert(occurance<=0); + btAssert(occurance<=0); #endif //DEBUG_PERSISTENCY if (pt.m_userPersistentData && gContactDestroyedCallback) @@ -164,7 +164,7 @@ int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) { - assert(validContactDistance(newPoint)); + btAssert(validContactDistance(newPoint)); int insertIndex = getNumContacts(); if (insertIndex == MANIFOLD_CACHE_SIZE) @@ -183,6 +183,9 @@ int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) } + if (insertIndex<0) + insertIndex=0; + btAssert(m_pointCache[insertIndex].m_userPersistentData==0); m_pointCache[insertIndex] = newPoint; return insertIndex; @@ -190,7 +193,7 @@ int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) btScalar btPersistentManifold::getContactBreakingThreshold() const { - return gContactBreakingThreshold; + return m_contactBreakingThreshold; } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h index c122eb865e8..0b3c734d1d7 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -24,7 +24,7 @@ subject to the following restrictions: struct btCollisionResult; -///contact breaking and merging threshold +///maximum contact breaking and merging threshold extern btScalar gContactBreakingThreshold; typedef bool (*ContactDestroyedCallback)(void* userPersistentData); @@ -54,6 +54,9 @@ ATTRIBUTE_ALIGNED16( class) btPersistentManifold void* m_body1; int m_cachedPoints; + btScalar m_contactBreakingThreshold; + btScalar m_contactProcessingThreshold; + /// sort cached points so most isolated points come first int sortCachedPoints(const btManifoldPoint& pt); @@ -68,10 +71,12 @@ public: btPersistentManifold(); - btPersistentManifold(void* body0,void* body1,int bla) - : m_body0(body0),m_body1(body1),m_cachedPoints(0) + btPersistentManifold(void* body0,void* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold) + : m_body0(body0),m_body1(body1),m_cachedPoints(0), + m_contactBreakingThreshold(contactBreakingThreshold), + m_contactProcessingThreshold(contactProcessingThreshold) { - (void)bla; + } SIMD_FORCE_INLINE void* getBody0() { return m_body0;} @@ -106,8 +111,13 @@ public: return m_pointCache[index]; } - /// todo: get this margin from the current physics / collision environment + ///@todo: get this margin from the current physics / collision environment btScalar getContactBreakingThreshold() const; + + btScalar getContactProcessingThreshold() const + { + return m_contactProcessingThreshold; + } int getCacheEntry(const btManifoldPoint& newPoint) const; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp index a70a3ae56c4..cdb1d22444d 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp @@ -23,10 +23,12 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "btRaycastCallback.h" -btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to) +btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags) : m_from(from), m_to(to), + //@BP Mod + m_flags(flags), m_hitFraction(btScalar(1.)) { @@ -55,6 +57,12 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, { return ; // same sign } + //@BP Mod - Backface filtering + if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a > btScalar(0.0))) + { + // Backface, skip check + return; + } const btScalar proj_length=dist_a-dist_b; const btScalar distance = (dist_a)/(proj_length); @@ -89,14 +97,18 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) { + //@BP Mod + // Triangle normal isn't normalized + triangleNormal.normalize(); - if ( dist_a > 0 ) + //@BP Mod - Allow for unflipped normal when raycasting against backfaces + if (((m_flags & kF_KeepUnflippedNormal) != 0) || (dist_a <= btScalar(0.0))) { - m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); + m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex); } else { - m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex); + m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); } } } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h index d2b4b80f8ba..3a1ab388c13 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h @@ -29,9 +29,20 @@ public: btVector3 m_from; btVector3 m_to; + //@BP Mod - allow backface filtering and unflipped normals + enum EFlags + { + kF_None = 0, + kF_FilterBackfaces = 1 << 0, + kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle + + kF_Terminator = 0xFFFFFFFF + }; + unsigned int m_flags; + btScalar m_hitFraction; - btTriangleRaycastCallback(const btVector3& from,const btVector3& to); + btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0); virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h index cf65f46505b..823b4e7158b 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h @@ -19,7 +19,6 @@ subject to the following restrictions: #define SIMPLEX_SOLVER_INTERFACE_H #include "LinearMath/btVector3.h" -#include "LinearMath/btPoint3.h" #define NO_VIRTUAL_INTERFACE 1 #ifdef NO_VIRTUAL_INTERFACE @@ -37,7 +36,7 @@ class btSimplexSolverInterface virtual void reset() = 0; - virtual void addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q) = 0; + virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0; virtual bool closest(btVector3& v) = 0; @@ -45,7 +44,7 @@ class btSimplexSolverInterface virtual bool fullSimplex() const = 0; - virtual int getSimplex(btPoint3 *pBuf, btPoint3 *qBuf, btVector3 *yBuf) const = 0; + virtual int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const = 0; virtual bool inSimplex(const btVector3& w) = 0; @@ -53,7 +52,7 @@ class btSimplexSolverInterface virtual bool emptySimplex() const = 0; - virtual void compute_points(btPoint3& p1, btPoint3& p2) = 0; + virtual void compute_points(btVector3& p1, btVector3& p2) = 0; virtual int numVertices() const =0; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp index cf8a3ab5eb1..a7ffeda8c62 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp @@ -25,8 +25,6 @@ subject to the following restrictions: #include "btVoronoiSimplexSolver.h" -#include -//#include #define VERTA 0 #define VERTB 1 @@ -37,7 +35,7 @@ subject to the following restrictions: void btVoronoiSimplexSolver::removeVertex(int index) { - assert(m_numVertices>0); + btAssert(m_numVertices>0); m_numVertices--; m_simplexVectorW[index] = m_simplexVectorW[m_numVertices]; m_simplexPointsP[index] = m_simplexPointsP[m_numVertices]; @@ -77,7 +75,7 @@ void btVoronoiSimplexSolver::reset() //add a vertex -void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q) +void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q) { m_lastW = w; m_needsUpdate = true; @@ -267,7 +265,7 @@ btScalar btVoronoiSimplexSolver::maxVertex() //return the current simplex -int btVoronoiSimplexSolver::getSimplex(btPoint3 *pBuf, btPoint3 *qBuf, btVector3 *yBuf) const +int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const { int i; for (i=0;i +//----------------------------------------------------------------------------- + +#define CONETWIST_USE_OBSOLETE_SOLVER false +#define CONETWIST_DEF_FIX_THRESH btScalar(.05f) + +//----------------------------------------------------------------------------- + btConeTwistConstraint::btConeTwistConstraint() -:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE) +:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE), +m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) { } @@ -31,69 +39,228 @@ btConeTwistConstraint::btConeTwistConstraint() btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame,const btTransform& rbBFrame) :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), - m_angularOnly(false) + m_angularOnly(false), + m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) { - m_swingSpan1 = btScalar(1e30); - m_swingSpan2 = btScalar(1e30); - m_twistSpan = btScalar(1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - - m_solveTwistLimit = false; - m_solveSwingLimit = false; - + init(); } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), - m_angularOnly(false) + m_angularOnly(false), + m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) { m_rbBFrame = m_rbAFrame; - - m_swingSpan1 = btScalar(1e30); - m_swingSpan2 = btScalar(1e30); - m_twistSpan = btScalar(1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; + init(); +} - m_solveTwistLimit = false; - m_solveSwingLimit = false; - -} -void btConeTwistConstraint::buildJacobian() +void btConeTwistConstraint::init() { - m_appliedImpulse = btScalar(0.); - - //set bias, sign, clear accumulator - m_swingCorrection = btScalar(0.); - m_twistLimitSign = btScalar(0.); + m_angularOnly = false; m_solveTwistLimit = false; m_solveSwingLimit = false; - m_accTwistLimitImpulse = btScalar(0.); - m_accSwingLimitImpulse = btScalar(0.); + m_bMotorEnabled = false; + m_maxMotorImpulse = btScalar(-1); - if (!m_angularOnly) + setLimit(btScalar(1e30), btScalar(1e30), btScalar(1e30)); + m_damping = btScalar(0.01); + m_fixThresh = CONETWIST_DEF_FIX_THRESH; +} + + +//----------------------------------------------------------------------------- + +void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) { - 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) + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + info->m_numConstraintRows = 3; + info->nub = 3; + calcAngleInfo2(); + if(m_solveSwingLimit) { - normal[0] = relPos.normalized(); + info->m_numConstraintRows++; + info->nub--; + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + if(m_solveTwistLimit) + { + info->m_numConstraintRows++; + info->nub--; + } + } +} // btConeTwistConstraint::getInfo1() + +//----------------------------------------------------------------------------- + +void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info) +{ + btAssert(!m_useSolveConstraintObsolete); + //retrieve matrices + btTransform body0_trans; + body0_trans = m_rbA.getCenterOfMassTransform(); + btTransform body1_trans; + body1_trans = m_rbB.getCenterOfMassTransform(); + // set jacobian + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip+1] = 1; + info->m_J1linearAxis[2*info->rowskip+2] = 1; + btVector3 a1 = body0_trans.getBasis() * m_rbAFrame.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + btVector3 a2 = body1_trans.getBasis() * m_rbBFrame.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + // set right hand side + btScalar k = info->fps * info->erp; + int j; + for (j=0; j<3; j++) + { + info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); + info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY; + info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY; + } + int row = 3; + int srow = row * info->rowskip; + btVector3 ax1; + // angular limits + if(m_solveSwingLimit) + { + btScalar *J1 = info->m_J1angularAxis; + btScalar *J2 = info->m_J2angularAxis; + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { + btTransform trA = m_rbA.getCenterOfMassTransform()*m_rbAFrame; + btVector3 p = trA.getBasis().getColumn(1); + btVector3 q = trA.getBasis().getColumn(2); + int srow1 = srow + info->rowskip; + J1[srow+0] = p[0]; + J1[srow+1] = p[1]; + J1[srow+2] = p[2]; + J1[srow1+0] = q[0]; + J1[srow1+1] = q[1]; + J1[srow1+2] = q[2]; + J2[srow+0] = -p[0]; + J2[srow+1] = -p[1]; + J2[srow+2] = -p[2]; + J2[srow1+0] = -q[0]; + J2[srow1+1] = -q[1]; + J2[srow1+2] = -q[2]; + btScalar fact = info->fps * m_relaxationFactor; + info->m_constraintError[srow] = fact * m_swingAxis.dot(p); + info->m_constraintError[srow1] = fact * m_swingAxis.dot(q); + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + info->m_lowerLimit[srow1] = -SIMD_INFINITY; + info->m_upperLimit[srow1] = SIMD_INFINITY; + srow = srow1 + info->rowskip; } else { - normal[0].setValue(btScalar(1.0),0,0); + ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + btScalar k = info->fps * m_biasFactor; + + info->m_constraintError[srow] = k * m_swingCorrection; + info->cfm[srow] = 0.0f; + // m_swingCorrection is always positive or 0 + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + srow += info->rowskip; } - - btPlaneSpace1(normal[0], normal[1], normal[2]); - - for (int i=0;i<3;i++) + } + if(m_solveTwistLimit) + { + ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor; + btScalar *J1 = info->m_J1angularAxis; + btScalar *J2 = info->m_J2angularAxis; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + btScalar k = info->fps * m_biasFactor; + info->m_constraintError[srow] = k * m_twistCorrection; + info->cfm[srow] = 0.0f; + if(m_twistSpan > 0.0f) { - new (&m_jac[i]) btJacobianEntry( + + if(m_twistCorrection > 0.0f) + { + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + srow += info->rowskip; + } +} + +//----------------------------------------------------------------------------- + +void btConeTwistConstraint::buildJacobian() +{ + if (m_useSolveConstraintObsolete) + { + m_appliedImpulse = btScalar(0.); + m_accTwistLimitImpulse = btScalar(0.); + m_accSwingLimitImpulse = btScalar(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++) + { + new (&m_jac[i]) btJacobianEntry( m_rbA.getCenterOfMassTransform().getBasis().transpose(), m_rbB.getCenterOfMassTransform().getBasis().transpose(), pivotAInW - m_rbA.getCenterOfMassPosition(), @@ -103,9 +270,243 @@ void btConeTwistConstraint::buildJacobian() m_rbA.getInvMass(), m_rbB.getInvInertiaDiagLocal(), m_rbB.getInvMass()); + } + } + + calcAngleInfo2(); + } +} + +//----------------------------------------------------------------------------- + +void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) +{ + if (m_useSolveConstraintObsolete) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + + btScalar tau = btScalar(0.3); + + //linear part + if (!m_angularOnly) + { + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1; + bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); + btVector3 vel2; + bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); + btVector3 vel = vel1 - vel2; + + for (int i=0;i<3;i++) + { + const btVector3& normal = m_jac[i].m_linearJointAxis; + btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + + 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; + m_appliedImpulse += impulse; + + btVector3 ftorqueAxis1 = rel_pos1.cross(normal); + btVector3 ftorqueAxis2 = rel_pos2.cross(normal); + bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); + bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); + + } + } + + // apply motor + if (m_bMotorEnabled) + { + // compute current and predicted transforms + btTransform trACur = m_rbA.getCenterOfMassTransform(); + btTransform trBCur = m_rbB.getCenterOfMassTransform(); + btVector3 omegaA; bodyA.getAngularVelocity(omegaA); + btVector3 omegaB; bodyB.getAngularVelocity(omegaB); + btTransform trAPred; trAPred.setIdentity(); + btVector3 zerovec(0,0,0); + btTransformUtil::integrateTransform( + trACur, zerovec, omegaA, timeStep, trAPred); + btTransform trBPred; trBPred.setIdentity(); + btTransformUtil::integrateTransform( + trBCur, zerovec, omegaB, timeStep, trBPred); + + // compute desired transforms in world + btTransform trPose(m_qTarget); + btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse(); + btTransform trADes = trBPred * trABDes; + btTransform trBDes = trAPred * trABDes.inverse(); + + // compute desired omegas in world + btVector3 omegaADes, omegaBDes; + + btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes); + btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes); + + // compute delta omegas + btVector3 dOmegaA = omegaADes - omegaA; + btVector3 dOmegaB = omegaBDes - omegaB; + + // compute weighted avg axis of dOmega (weighting based on inertias) + btVector3 axisA, axisB; + btScalar kAxisAInv = 0, kAxisBInv = 0; + + if (dOmegaA.length2() > SIMD_EPSILON) + { + axisA = dOmegaA.normalized(); + kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA); + } + + if (dOmegaB.length2() > SIMD_EPSILON) + { + axisB = dOmegaB.normalized(); + kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB); + } + + btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB; + + static bool bDoTorque = true; + if (bDoTorque && avgAxis.length2() > SIMD_EPSILON) + { + avgAxis.normalize(); + kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis); + kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis); + btScalar kInvCombined = kAxisAInv + kAxisBInv; + + btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) / + (kInvCombined * kInvCombined); + + if (m_maxMotorImpulse >= 0) + { + btScalar fMaxImpulse = m_maxMotorImpulse; + if (m_bNormalizedMotorStrength) + fMaxImpulse = fMaxImpulse/kAxisAInv; + + btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse; + btScalar newUnclampedMag = newUnclampedAccImpulse.length(); + if (newUnclampedMag > fMaxImpulse) + { + newUnclampedAccImpulse.normalize(); + newUnclampedAccImpulse *= fMaxImpulse; + impulse = newUnclampedAccImpulse - m_accMotorImpulse; + } + m_accMotorImpulse += impulse; + } + + btScalar impulseMag = impulse.length(); + btVector3 impulseAxis = impulse / impulseMag; + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); + + } + } + else // no motor: do a little damping + { + const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); + const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); + btVector3 relVel = angVelB - angVelA; + if (relVel.length2() > SIMD_EPSILON) + { + btVector3 relVelAxis = relVel.normalized(); + btScalar m_kDamping = btScalar(1.) / + (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) + + getRigidBodyB().computeAngularImpulseDenominator(relVelAxis)); + btVector3 impulse = m_damping * m_kDamping * relVel; + + btScalar impulseMag = impulse.length(); + btVector3 impulseAxis = impulse / impulseMag; + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); + } + } + + // joint limits + { + ///solve angular part + btVector3 angVelA; + bodyA.getAngularVelocity(angVelA); + btVector3 angVelB; + bodyB.getAngularVelocity(angVelB); + + // solve swing limit + if (m_solveSwingLimit) + { + btScalar amplitude = m_swingLimitRatio * m_swingCorrection*m_biasFactor/timeStep; + btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis); + if (relSwingVel > 0) + amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor; + btScalar impulseMag = amplitude * m_kSwing; + + // Clamp the accumulated impulse + btScalar temp = m_accSwingLimitImpulse; + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); + impulseMag = m_accSwingLimitImpulse - temp; + + btVector3 impulse = m_swingAxis * impulseMag; + + // don't let cone response affect twist + // (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit) + { + btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA; + btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple; + impulse = impulseNoTwistCouple; + } + + impulseMag = impulse.length(); + btVector3 noTwistSwingAxis = impulse / impulseMag; + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*noTwistSwingAxis, impulseMag); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*noTwistSwingAxis, -impulseMag); + } + + + // solve twist limit + if (m_solveTwistLimit) + { + btScalar amplitude = m_twistLimitRatio * m_twistCorrection*m_biasFactor/timeStep; + btScalar relTwistVel = (angVelB - angVelA).dot( m_twistAxis ); + if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important) + amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor; + btScalar impulseMag = amplitude * m_kTwist; + + // Clamp the accumulated impulse + btScalar temp = m_accTwistLimitImpulse; + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); + impulseMag = m_accTwistLimitImpulse - temp; + + btVector3 impulse = m_twistAxis * impulseMag; + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag); + } } } +} + +//----------------------------------------------------------------------------- + +void btConeTwistConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + +//----------------------------------------------------------------------------- + +void btConeTwistConstraint::calcAngleInfo() +{ + m_swingCorrection = btScalar(0.); + m_twistLimitSign = btScalar(0.); + m_solveTwistLimit = false; + m_solveSwingLimit = false; + btVector3 b1Axis1,b1Axis2,b1Axis3; btVector3 b2Axis1,b2Axis2; @@ -122,20 +523,17 @@ void btConeTwistConstraint::buildJacobian() 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; - } 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); @@ -152,17 +550,11 @@ void btConeTwistConstraint::buildJacobian() { m_swingCorrection = EllipseAngle-1.0f; m_solveSwingLimit = true; - // Calculate necessary axis & factors m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3)); m_swingAxis.normalize(); - btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; m_swingAxis *= swingAxisSign; - - m_kSwing = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_swingAxis) + - getRigidBodyB().computeAngularImpulseDenominator(m_swingAxis)); - } // Twist limits @@ -172,118 +564,426 @@ void btConeTwistConstraint::buildJacobian() btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1); btVector3 TwistRef = quatRotate(rotationArc,b2Axis2); btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) ); + m_twistAngle = twist; - btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); +// btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); + btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.); if (twist <= -m_twistSpan*lockedFreeFactor) { m_twistCorrection = -(twist + m_twistSpan); m_solveTwistLimit = true; - m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; m_twistAxis.normalize(); m_twistAxis *= -1.0f; + } + else if (twist > m_twistSpan*lockedFreeFactor) + { + m_twistCorrection = (twist - m_twistSpan); + m_solveTwistLimit = true; + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + } + } +} // btConeTwistConstraint::calcAngleInfo() - m_kTwist = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + - getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); - } else - if (twist > m_twistSpan*lockedFreeFactor) +static btVector3 vTwist(1,0,0); // twist axis in constraint's space + +//----------------------------------------------------------------------------- + +void btConeTwistConstraint::calcAngleInfo2() +{ + m_swingCorrection = btScalar(0.); + m_twistLimitSign = btScalar(0.); + m_solveTwistLimit = false; + m_solveSwingLimit = false; + + { + // compute rotation of A wrt B (in constraint space) + btQuaternion qA = getRigidBodyA().getCenterOfMassTransform().getRotation() * m_rbAFrame.getRotation(); + btQuaternion qB = getRigidBodyB().getCenterOfMassTransform().getRotation() * m_rbBFrame.getRotation(); + btQuaternion qAB = qB.inverse() * qA; + + // split rotation into cone and twist + // (all this is done from B's perspective. Maybe I should be averaging axes...) + btVector3 vConeNoTwist = quatRotate(qAB, vTwist); vConeNoTwist.normalize(); + btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist); qABCone.normalize(); + btQuaternion qABTwist = qABCone.inverse() * qAB; qABTwist.normalize(); + + if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh) + { + btScalar swingAngle, swingLimit = 0; btVector3 swingAxis; + computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit); + + if (swingAngle > swingLimit * m_limitSoftness) + { + m_solveSwingLimit = true; + + // compute limit ratio: 0->1, where + // 0 == beginning of soft limit + // 1 == hard/real limit + m_swingLimitRatio = 1.f; + if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON) + { + m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness)/ + (swingLimit - swingLimit * m_limitSoftness); + } + + // swing correction tries to get back to soft limit + m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness); + + // adjustment of swing axis (based on ellipse normal) + adjustSwingAxisToUseEllipseNormal(swingAxis); + + // Calculate necessary axis & factors + m_swingAxis = quatRotate(qB, -swingAxis); + + m_twistAxisA.setValue(0,0,0); + + m_kSwing = btScalar(1.) / + (getRigidBodyA().computeAngularImpulseDenominator(m_swingAxis) + + getRigidBodyB().computeAngularImpulseDenominator(m_swingAxis)); + } + } + else + { + // you haven't set any limits; + // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?) + // anyway, we have either hinge or fixed joint + btVector3 ivA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); + btVector3 jvA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); + btVector3 kvA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 ivB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(0); + btVector3 target; + btScalar x = ivB.dot(ivA); + btScalar y = ivB.dot(jvA); + btScalar z = ivB.dot(kvA); + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { // fixed. We'll need to add one more row to constraint + if((!btFuzzyZero(y)) || (!(btFuzzyZero(z)))) + { + m_solveSwingLimit = true; + m_swingAxis = -ivB.cross(ivA); + } + } + else + { + if(m_swingSpan1 < m_fixThresh) + { // hinge around Y axis + if(!(btFuzzyZero(y))) + { + m_solveSwingLimit = true; + if(m_swingSpan2 >= m_fixThresh) + { + y = btScalar(0.f); + btScalar span2 = btAtan2(z, x); + if(span2 > m_swingSpan2) + { + x = btCos(m_swingSpan2); + z = btSin(m_swingSpan2); + } + else if(span2 < -m_swingSpan2) + { + x = btCos(m_swingSpan2); + z = -btSin(m_swingSpan2); + } + } + } + } + else + { // hinge around Z axis + if(!btFuzzyZero(z)) + { + m_solveSwingLimit = true; + if(m_swingSpan1 >= m_fixThresh) + { + z = btScalar(0.f); + btScalar span1 = btAtan2(y, x); + if(span1 > m_swingSpan1) + { + x = btCos(m_swingSpan1); + y = btSin(m_swingSpan1); + } + else if(span1 < -m_swingSpan1) + { + x = btCos(m_swingSpan1); + y = -btSin(m_swingSpan1); + } + } + } + } + target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0]; + target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1]; + target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2]; + target.normalize(); + m_swingAxis = -ivB.cross(target); + m_swingCorrection = m_swingAxis.length(); + m_swingAxis.normalize(); + } + } + + if (m_twistSpan >= btScalar(0.f)) + { + btVector3 twistAxis; + computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis); + + if (m_twistAngle > m_twistSpan*m_limitSoftness) { - m_twistCorrection = (twist - m_twistSpan); m_solveTwistLimit = true; - m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; - m_twistAxis.normalize(); + m_twistLimitRatio = 1.f; + if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON) + { + m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness)/ + (m_twistSpan - m_twistSpan * m_limitSoftness); + } - m_kTwist = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + - getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); + // twist correction tries to get back to soft limit + m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness); + m_twistAxis = quatRotate(qB, -twistAxis); + + m_kTwist = btScalar(1.) / + (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + + getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); } - } -} -void btConeTwistConstraint::solveConstraint(btScalar timeStep) -{ - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - - btScalar tau = btScalar(0.3); - - //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; - btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - - 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; - 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()); + if (m_solveSwingLimit) + m_twistAxisA = quatRotate(qA, -twistAxis); } - } - - { - ///solve angular part - const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); - const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); - - // solve swing limit - if (m_solveSwingLimit) + else { - btScalar amplitude = ((angVelB - angVelA).dot( m_swingAxis )*m_relaxationFactor*m_relaxationFactor + m_swingCorrection*(btScalar(1.)/timeStep)*m_biasFactor); - btScalar impulseMag = amplitude * m_kSwing; - - // Clamp the accumulated impulse - btScalar temp = m_accSwingLimitImpulse; - m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); - impulseMag = m_accSwingLimitImpulse - temp; - - btVector3 impulse = m_swingAxis * impulseMag; - - m_rbA.applyTorqueImpulse(impulse); - m_rbB.applyTorqueImpulse(-impulse); - + m_twistAngle = btScalar(0.f); } + } +} // btConeTwistConstraint::calcAngleInfo2() - // solve twist limit - if (m_solveTwistLimit) + + +// given a cone rotation in constraint space, (pre: twist must already be removed) +// this method computes its corresponding swing angle and axis. +// more interestingly, it computes the cone/swing limit (angle) for this cone "pose". +void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, + btScalar& swingAngle, // out + btVector3& vSwingAxis, // out + btScalar& swingLimit) // out +{ + swingAngle = qCone.getAngle(); + if (swingAngle > SIMD_EPSILON) + { + vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z()); + vSwingAxis.normalize(); + if (fabs(vSwingAxis.x()) > SIMD_EPSILON) { - btScalar amplitude = ((angVelB - angVelA).dot( m_twistAxis )*m_relaxationFactor*m_relaxationFactor + m_twistCorrection*(btScalar(1.)/timeStep)*m_biasFactor ); - btScalar impulseMag = amplitude * m_kTwist; - - // Clamp the accumulated impulse - btScalar temp = m_accTwistLimitImpulse; - m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); - impulseMag = m_accTwistLimitImpulse - temp; - - btVector3 impulse = m_twistAxis * impulseMag; - - m_rbA.applyTorqueImpulse(impulse); - m_rbB.applyTorqueImpulse(-impulse); - + // non-zero twist?! this should never happen. + int wtf = 0; wtf = wtf; } - + + // Compute limit for given swing. tricky: + // Given a swing axis, we're looking for the intersection with the bounding cone ellipse. + // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.) + + // For starters, compute the direction from center to surface of ellipse. + // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis. + // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.) + btScalar xEllipse = vSwingAxis.y(); + btScalar yEllipse = -vSwingAxis.z(); + + // Now, we use the slope of the vector (using x/yEllipse) and find the length + // of the line that intersects the ellipse: + // x^2 y^2 + // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits) + // a^2 b^2 + // Do the math and it should be clear. + + swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1 + if (fabs(xEllipse) > SIMD_EPSILON) + { + btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); + btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); + norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); + btScalar swingLimit2 = (1 + surfaceSlope2) / norm; + swingLimit = sqrt(swingLimit2); + } + + // test! + /*swingLimit = m_swingSpan2; + if (fabs(vSwingAxis.z()) > SIMD_EPSILON) + { + btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2; + btScalar sinphi = m_swingSpan2 / sqrt(mag_2); + btScalar phi = asin(sinphi); + btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z())); + btScalar alpha = 3.14159f - theta - phi; + btScalar sinalpha = sin(alpha); + swingLimit = m_swingSpan1 * sinphi/sinalpha; + }*/ + } + else if (swingAngle < 0) + { + // this should never happen! + int wtf = 0; wtf = wtf; + } +} + +btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const +{ + // compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone) + btScalar xEllipse = btCos(fAngleInRadians); + btScalar yEllipse = btSin(fAngleInRadians); + + // Use the slope of the vector (using x/yEllipse) and find the length + // of the line that intersects the ellipse: + // x^2 y^2 + // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits) + // a^2 b^2 + // Do the math and it should be clear. + + float swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1) + if (fabs(xEllipse) > SIMD_EPSILON) + { + btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); + btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); + norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); + btScalar swingLimit2 = (1 + surfaceSlope2) / norm; + swingLimit = sqrt(swingLimit2); } + // convert into point in constraint space: + // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively + btVector3 vSwingAxis(0, xEllipse, -yEllipse); + btQuaternion qSwing(vSwingAxis, swingLimit); + btVector3 vPointInConstraintSpace(fLength,0,0); + return quatRotate(qSwing, vPointInConstraintSpace); } -void btConeTwistConstraint::updateRHS(btScalar timeStep) +// given a twist rotation in constraint space, (pre: cone must already be removed) +// this method computes its corresponding angle and axis. +void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist, + btScalar& twistAngle, // out + btVector3& vTwistAxis) // out { - (void)timeStep; + btQuaternion qMinTwist = qTwist; + twistAngle = qTwist.getAngle(); + if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate. + { + qMinTwist = operator-(qTwist); + twistAngle = qMinTwist.getAngle(); + } + if (twistAngle < 0) + { + // this should never happen + int wtf = 0; wtf = wtf; + } + + vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z()); + if (twistAngle > SIMD_EPSILON) + vTwistAxis.normalize(); } + + +void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const +{ + // the swing axis is computed as the "twist-free" cone rotation, + // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2). + // so, if we're outside the limits, the closest way back inside the cone isn't + // along the vector back to the center. better (and more stable) to use the ellipse normal. + + // convert swing axis to direction from center to surface of ellipse + // (ie. rotate 2D vector by PI/2) + btScalar y = -vSwingAxis.z(); + btScalar z = vSwingAxis.y(); + + // do the math... + if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0. + { + // compute gradient/normal of ellipse surface at current "point" + btScalar grad = y/z; + grad *= m_swingSpan2 / m_swingSpan1; + + // adjust y/z to represent normal at point (instead of vector to point) + if (y > 0) + y = fabs(grad * z); + else + y = -fabs(grad * z); + + // convert ellipse direction back to swing axis + vSwingAxis.setZ(-y); + vSwingAxis.setY( z); + vSwingAxis.normalize(); + } +} + + + +void btConeTwistConstraint::setMotorTarget(const btQuaternion &q) +{ + btTransform trACur = m_rbA.getCenterOfMassTransform(); + btTransform trBCur = m_rbB.getCenterOfMassTransform(); + btTransform trABCur = trBCur.inverse() * trACur; + btQuaternion qABCur = trABCur.getRotation(); + btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame); + btQuaternion qConstraintCur = trConstraintCur.getRotation(); + + btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation(); + setMotorTargetInConstraintSpace(qConstraint); +} + + +void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &q) +{ + m_qTarget = q; + + // clamp motor target to within limits + { + btScalar softness = 1.f;//m_limitSoftness; + + // split into twist and cone + btVector3 vTwisted = quatRotate(m_qTarget, vTwist); + btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted); qTargetCone.normalize(); + btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; qTargetTwist.normalize(); + + // clamp cone + if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f)) + { + btScalar swingAngle, swingLimit; btVector3 swingAxis; + computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit); + + if (fabs(swingAngle) > SIMD_EPSILON) + { + if (swingAngle > swingLimit*softness) + swingAngle = swingLimit*softness; + else if (swingAngle < -swingLimit*softness) + swingAngle = -swingLimit*softness; + qTargetCone = btQuaternion(swingAxis, swingAngle); + } + } + + // clamp twist + if (m_twistSpan >= btScalar(0.05f)) + { + btScalar twistAngle; btVector3 twistAxis; + computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis); + + if (fabs(twistAngle) > SIMD_EPSILON) + { + // eddy todo: limitSoftness used here??? + if (twistAngle > m_twistSpan*softness) + twistAngle = m_twistSpan*softness; + else if (twistAngle < -m_twistSpan*softness) + twistAngle = -m_twistSpan*softness; + qTargetTwist = btQuaternion(twistAxis, twistAngle); + } + } + + m_qTarget = qTargetCone * qTargetTwist; + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index f121919c8f9..84ea9e04095 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -20,7 +20,7 @@ Written by: Marcus Hennix #ifndef CONETWISTCONSTRAINT_H #define CONETWISTCONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" @@ -42,10 +42,14 @@ public: btScalar m_biasFactor; btScalar m_relaxationFactor; + btScalar m_damping; + btScalar m_swingSpan1; btScalar m_swingSpan2; btScalar m_twistSpan; + btScalar m_fixThresh; + btVector3 m_swingAxis; btVector3 m_twistAxis; @@ -56,6 +60,8 @@ public: btScalar m_swingCorrection; btScalar m_twistCorrection; + btScalar m_twistAngle; + btScalar m_accSwingLimitImpulse; btScalar m_accTwistLimitImpulse; @@ -63,6 +69,19 @@ public: bool m_solveTwistLimit; bool m_solveSwingLimit; + bool m_useSolveConstraintObsolete; + + // not yet used... + btScalar m_swingLimitRatio; + btScalar m_twistLimitRatio; + btVector3 m_twistAxisA; + + // motor + bool m_bMotorEnabled; + bool m_bNormalizedMotorStrength; + btQuaternion m_qTarget; + btScalar m_maxMotorImpulse; + btVector3 m_accMotorImpulse; public: @@ -74,7 +93,12 @@ public: virtual void buildJacobian(); - virtual void solveConstraint(btScalar timeStep); + virtual void getInfo1 (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); void updateRHS(btScalar timeStep); @@ -92,7 +116,32 @@ public: m_angularOnly = angularOnly; } - void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 0.8f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + void setLimit(int limitIndex,btScalar limitValue) + { + switch (limitIndex) + { + case 3: + { + m_twistSpan = limitValue; + break; + } + case 4: + { + m_swingSpan2 = limitValue; + break; + } + case 5: + { + m_swingSpan1 = limitValue; + break; + } + default: + { + } + }; + } + + void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) { m_swingSpan1 = _swingSpan1; m_swingSpan2 = _swingSpan2; @@ -121,6 +170,60 @@ public: return m_twistLimitSign; } + void calcAngleInfo(); + void calcAngleInfo2(); + + inline btScalar getSwingSpan1() + { + return m_swingSpan1; + } + inline btScalar getSwingSpan2() + { + return m_swingSpan2; + } + inline btScalar getTwistSpan() + { + return m_twistSpan; + } + inline btScalar getTwistAngle() + { + return m_twistAngle; + } + bool isPastSwingLimit() { return m_solveSwingLimit; } + + + void setDamping(btScalar damping) { m_damping = damping; } + + void enableMotor(bool b) { m_bMotorEnabled = b; } + void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; } + void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; } + + btScalar getFixThresh() { return m_fixThresh; } + void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; } + + // setMotorTarget: + // q: the desired rotation of bodyA wrt bodyB. + // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability) + // note: don't forget to enableMotor() + void setMotorTarget(const btQuaternion &q); + + // same as above, but q is the desired rotation of frameA wrt frameB in constraint space + void setMotorTargetInConstraintSpace(const btQuaternion &q); + + btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const; + + + +protected: + void init(); + + void computeConeLimitInfo(const btQuaternion& qCone, // in + btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs + + void computeTwistLimitInfo(const btQuaternion& qTwist, // in + btScalar& twistAngle, btVector3& vTwistAxis); // all outs + + void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const; }; #endif //CONETWISTCONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp index 4d7cd05feb7..012c321fd6d 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -22,7 +22,7 @@ subject to the following restrictions: #include "LinearMath/btMinMax.h" #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" -#define ASSERT2 assert +#define ASSERT2 btAssert #define USE_INTERNAL_APPLY_IMPULSE 1 @@ -52,7 +52,7 @@ void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, btVector3 vel = vel1 - vel2; - btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), + btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), body2.getCenterOfMassTransform().getBasis().transpose(), rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(), body2.getInvInertiaDiagLocal(),body2.getInvMass()); @@ -114,7 +114,7 @@ btScalar resolveSingleCollision( btScalar Kcor = Kerp *Kfps; btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - assert(cpd); + btAssert(cpd); btScalar distance = cpd->m_penetration; btScalar positionalError = Kcor *-distance; btScalar velocityError = cpd->m_restitution - rel_vel;// * damping; @@ -166,7 +166,7 @@ btScalar resolveSingleFriction( btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - assert(cpd); + btAssert(cpd); btScalar combinedFriction = cpd->m_friction; @@ -255,7 +255,7 @@ btScalar resolveSingleFrictionOriginal( btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - assert(cpd); + btAssert(cpd); btScalar combinedFriction = cpd->m_friction; @@ -337,7 +337,7 @@ btScalar resolveSingleCollisionCombined( btScalar Kcor = Kerp *Kfps; btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - assert(cpd); + btAssert(cpd); btScalar distance = cpd->m_penetration; btScalar positionalError = Kcor *-distance; btScalar velocityError = cpd->m_restitution - rel_vel;// * damping; @@ -425,5 +425,5 @@ btScalar resolveSingleFrictionEmpty( return btScalar(0.); -}; +} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h index 826e79f78bd..e8871f3860b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef CONTACT_CONSTRAINT_H #define CONTACT_CONSTRAINT_H -//todo: make into a proper class working with the iterative constraint solver +///@todo: make into a proper class working with the iterative constraint solver class btRigidBody; #include "LinearMath/btVector3.h" diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index 916d4581f79..e99430c00de 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -21,7 +21,13 @@ enum btSolverMode SOLVER_RANDMIZE_ORDER = 1, SOLVER_FRICTION_SEPARATE = 2, SOLVER_USE_WARMSTARTING = 4, - SOLVER_CACHE_FRIENDLY = 8 + SOLVER_USE_FRICTION_WARMSTARTING = 8, + SOLVER_USE_2_FRICTION_DIRECTIONS = 16, + SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32, + SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64, + SOLVER_CACHE_FRIENDLY = 128, + SOLVER_SIMD = 256, //enabled for Windows, the solver innerloop is branchless SIMD, 40% faster than FPU/scalar version + SOLVER_CUDA = 512 //will be open sourced during Game Developers Conference 2009. Much faster. }; struct btContactSolverInfoData @@ -38,12 +44,14 @@ struct btContactSolverInfoData btScalar m_sor; btScalar m_erp;//used as Baumgarte factor btScalar m_erp2;//used in Split Impulse + btScalar m_globalCfm;//constraint force mixing int m_splitImpulse; btScalar m_splitImpulsePenetrationThreshold; btScalar m_linearSlop; btScalar m_warmstartingFactor; int m_solverMode; + int m_restingContactRestitutionThreshold; }; @@ -63,12 +71,14 @@ struct btContactSolverInfo : public btContactSolverInfoData m_numIterations = 10; m_erp = btScalar(0.2); m_erp2 = btScalar(0.1); - m_sor = btScalar(1.3); + m_globalCfm = btScalar(0.); + m_sor = btScalar(1.); 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; + m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD ;//SOLVER_RANDMIZE_ORDER + m_restingContactRestitutionThreshold = 2;//resting contact lifetime threshold to disable restitution } }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp index 077b326d13a..6cbfe61f700 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -19,18 +19,40 @@ email: projectileman@yahoo.com http://gimpact.sf.net */ - #include "btGeneric6DofConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #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 D6_USE_OBSOLETE_METHOD false +//----------------------------------------------------------------------------- + +btGeneric6DofConstraint::btGeneric6DofConstraint() +:btTypedConstraint(D6_CONSTRAINT_TYPE), +m_useLinearReferenceFrameA(true), +m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) +{ +} + +//----------------------------------------------------------------------------- + +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), +m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) +{ + +} +//----------------------------------------------------------------------------- + + #define GENERIC_D6_DISABLE_WARMSTARTING 1 +//----------------------------------------------------------------------------- + btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) { @@ -39,51 +61,48 @@ btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) 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) { -// // 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)) + btScalar fi = btGetMatrixElem(mat,2); + if (fi < btScalar(1.0f)) + { + if (fi > btScalar(-1.0f)) { - 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; - } + 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. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); - xyz[1] = SIMD_HALF_PI; - xyz[2] = 0.0; - + // 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; + } return false; } - - //////////////////////////// btRotationalLimitMotor //////////////////////////////////// - int btRotationalLimitMotor::testLimitValue(btScalar test_value) { if(m_loLimit>m_hiLimit) @@ -107,212 +126,239 @@ int btRotationalLimitMotor::testLimitValue(btScalar test_value) m_currentLimit = 0;//Free from violation return 0; - + } +//----------------------------------------------------------------------------- btScalar btRotationalLimitMotor::solveAngularLimits( - btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, - btRigidBody * body0, btRigidBody * body1) + btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, + btRigidBody * body0, btSolverBody& bodyA, btRigidBody * body1, btSolverBody& bodyB) { - if (needApplyTorques()==false) return 0.0f; + if (needApplyTorques()==false) return 0.0f; - btScalar target_velocity = m_targetVelocity; - btScalar maxMotorForce = m_maxMotorForce; + 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; - } + if (m_currentLimit!=0) + { + target_velocity = -m_ERP*m_currentLimitError/(timeStep); + maxMotorForce = m_maxLimitForce; + } - maxMotorForce *= timeStep; + maxMotorForce *= timeStep; - // current velocity difference - btVector3 vel_diff = body0->getAngularVelocity(); - if (body1) - { - vel_diff -= body1->getAngularVelocity(); - } + // current velocity difference + + btVector3 angVelA; + bodyA.getAngularVelocity(angVelA); + btVector3 angVelB; + bodyB.getAngularVelocity(angVelB); + + btVector3 vel_diff; + vel_diff = angVelA-angVelB; - btScalar rel_vel = axis.dot(vel_diff); + btScalar rel_vel = axis.dot(vel_diff); // correction velocity - btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); + 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 - } + 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; + btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; // clip correction impulse - btScalar clippedMotorImpulse; + btScalar clippedMotorImpulse; - //todo: should clip against accumulated impulse - if (unclippedMotorImpulse>0.0f) - { - clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; - } - else - { - clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; - } + ///@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 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; + btScalar oldaccumImpulse = m_accumulatedImpulse; + btScalar sum = oldaccumImpulse + clippedMotorImpulse; + m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; + clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; + + btVector3 motorImp = clippedMotorImpulse * axis; + + //body0->applyTorqueImpulse(motorImp); + //body1->applyTorqueImpulse(-motorImp); + + bodyA.applyImpulse(btVector3(0,0,0), body0->getInvInertiaTensorWorld()*axis,clippedMotorImpulse); + bodyB.applyImpulse(btVector3(0,0,0), body1->getInvInertiaTensorWorld()*axis,-clippedMotorImpulse); - - btVector3 motorImp = clippedMotorImpulse * axis; - - - body0->applyTorqueImpulse(motorImp); - if (body1) body1->applyTorqueImpulse(-motorImp); - - return clippedMotorImpulse; + return clippedMotorImpulse; } //////////////////////////// End btRotationalLimitMotor //////////////////////////////////// + + + //////////////////////////// btTranslationalLimitMotor //////////////////////////////////// + + +int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value) +{ + btScalar loLimit = m_lowerLimit[limitIndex]; + btScalar hiLimit = m_upperLimit[limitIndex]; + if(loLimit > hiLimit) + { + m_currentLimit[limitIndex] = 0;//Free from violation + m_currentLimitError[limitIndex] = btScalar(0.f); + return 0; + } + + if (test_value < loLimit) + { + m_currentLimit[limitIndex] = 2;//low limit violation + m_currentLimitError[limitIndex] = test_value - loLimit; + return 2; + } + else if (test_value> hiLimit) + { + m_currentLimit[limitIndex] = 1;//High limit violation + m_currentLimitError[limitIndex] = test_value - hiLimit; + return 1; + }; + + m_currentLimit[limitIndex] = 0;//Free from violation + m_currentLimitError[limitIndex] = btScalar(0.f); + return 0; +} // btTranslationalLimitMotor::testLimitValue() + +//----------------------------------------------------------------------------- + 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) + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,btSolverBody& bodyA,const btVector3 &pointInA, + btRigidBody& body2,btSolverBody& bodyB,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(); + ///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; + btVector3 vel1; + bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); + btVector3 vel2; + bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); + btVector3 vel = vel1 - vel2; - btScalar rel_vel = axis_normal_on_a.dot(vel); + btScalar rel_vel = axis_normal_on_a.dot(vel); -/// apply displacement correction + /// 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); + //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]; + 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.); + //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; - } - } - } - } + } + 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 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; + 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; + btVector3 impulse_vector = axis_normal_on_a * normalImpulse; + //body1.applyImpulse( impulse_vector, rel_pos1); + //body2.applyImpulse(-impulse_vector, rel_pos2); + + btVector3 ftorqueAxis1 = rel_pos1.cross(axis_normal_on_a); + btVector3 ftorqueAxis2 = rel_pos2.cross(axis_normal_on_a); + bodyA.applyImpulse(axis_normal_on_a*body1.getInvMass(), body1.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse); + bodyB.applyImpulse(axis_normal_on_a*body2.getInvMass(), body2.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse); + + + + + 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. - + // 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); @@ -320,34 +366,29 @@ void btGeneric6DofConstraint::calculateAngleInfo() 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); -// } + m_calculatedAxis[0].normalize(); + m_calculatedAxis[1].normalize(); + m_calculatedAxis[2].normalize(); } +//----------------------------------------------------------------------------- + void btGeneric6DofConstraint::calculateTransforms() { - m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; - m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; - - calculateAngleInfo(); + m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; + m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; + calculateLinearInfo(); + calculateAngleInfo(); } +//----------------------------------------------------------------------------- void btGeneric6DofConstraint::buildLinearJacobian( - btJacobianEntry & jacLinear,const btVector3 & normalWorld, - const btVector3 & pivotAInW,const btVector3 & pivotBInW) + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW) { - new (&jacLinear) btJacobianEntry( + new (&jacLinear) btJacobianEntry( m_rbA.getCenterOfMassTransform().getBasis().transpose(), m_rbB.getCenterOfMassTransform().getBasis().transpose(), pivotAInW - m_rbA.getCenterOfMassPosition(), @@ -357,13 +398,14 @@ void btGeneric6DofConstraint::buildLinearJacobian( m_rbA.getInvMass(), m_rbB.getInvInertiaDiagLocal(), m_rbB.getInvMass()); - } +//----------------------------------------------------------------------------- + void btGeneric6DofConstraint::buildAngularJacobian( - btJacobianEntry & jacAngular,const btVector3 & jointAxisW) + btJacobianEntry & jacAngular,const btVector3 & jointAxisW) { - new (&jacAngular) btJacobianEntry(jointAxisW, + new (&jacAngular) btJacobianEntry(jointAxisW, m_rbA.getCenterOfMassTransform().getBasis().transpose(), m_rbB.getCenterOfMassTransform().getBasis().transpose(), m_rbA.getInvInertiaDiagLocal(), @@ -371,142 +413,260 @@ void btGeneric6DofConstraint::buildAngularJacobian( } +//----------------------------------------------------------------------------- + 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(); + btScalar angle = m_calculatedAxisAngleDiff[axis_index]; + //test limits + m_angularLimits[axis_index].testLimitValue(angle); + return m_angularLimits[axis_index].needApplyTorques(); } +//----------------------------------------------------------------------------- + void btGeneric6DofConstraint::buildJacobian() { + if (m_useSolveConstraintObsolete) + { - // 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(); + // 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; + // 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(); + // 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); + 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); + 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); - } - } + } + } + // 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) +void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info) { - 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); - } - } + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } else + { + //prepare constraint + calculateTransforms(); + info->m_numConstraintRows = 0; + info->nub = 6; + int i; + //test linear limits + for(i = 0; i < 3; i++) + { + if(m_linearLimits.needApplyForce(i)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + //test angular limits + for (i=0;i<3 ;i++ ) + { + if(testAngularLimitMotor(i)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + } } +//----------------------------------------------------------------------------- + +void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info) +{ + btAssert(!m_useSolveConstraintObsolete); + int row = setLinearLimits(info); + setAngularLimits(info, row); +} + +//----------------------------------------------------------------------------- + +int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info) +{ + btGeneric6DofConstraint * d6constraint = this; + int row = 0; + //solve linear limits + btRotationalLimitMotor limot; + for (int i=0;i<3 ;i++ ) + { + if(m_linearLimits.needApplyForce(i)) + { // re-use rotational motor code + limot.m_bounce = btScalar(0.f); + limot.m_currentLimit = m_linearLimits.m_currentLimit[i]; + limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; + limot.m_damping = m_linearLimits.m_damping; + limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; + limot.m_ERP = m_linearLimits.m_restitution; + limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; + limot.m_limitSoftness = m_linearLimits.m_limitSoftness; + limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; + limot.m_maxLimitForce = btScalar(0.f); + limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; + limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; + btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i); + row += get_limit_motor_info2(&limot, &m_rbA, &m_rbB, info, row, axis, 0); + } + } + return row; +} + +//----------------------------------------------------------------------------- + +int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset) +{ + btGeneric6DofConstraint * d6constraint = this; + int row = row_offset; + //solve angular limits + for (int i=0;i<3 ;i++ ) + { + if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques()) + { + btVector3 axis = d6constraint->getAxis(i); + row += get_limit_motor_info2( + d6constraint->getRotationalLimitMotor(i), + &m_rbA, + &m_rbB, + info,row,axis,1); + } + } + + return row; +} + +//----------------------------------------------------------------------------- + +void btGeneric6DofConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) +{ + if (m_useSolveConstraintObsolete) + { + + + 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,bodyA,pointInA, + m_rbB,bodyB,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,bodyA,&m_rbB,bodyB); + } + } + } +} + +//----------------------------------------------------------------------------- + void btGeneric6DofConstraint::updateRHS(btScalar timeStep) { - (void)timeStep; + (void)timeStep; } +//----------------------------------------------------------------------------- + btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const { - return m_calculatedAxis[axis_index]; + return m_calculatedAxis[axis_index]; } +//----------------------------------------------------------------------------- + btScalar btGeneric6DofConstraint::getAngle(int axis_index) const { - return m_calculatedAxisAngleDiff[axis_index]; + return m_calculatedAxisAngleDiff[axis_index]; } +//----------------------------------------------------------------------------- + void btGeneric6DofConstraint::calcAnchorPos(void) { btScalar imA = m_rbA.getInvMass(); @@ -526,3 +686,144 @@ void btGeneric6DofConstraint::calcAnchorPos(void) return; } // btGeneric6DofConstraint::calcAnchorPos() +//----------------------------------------------------------------------------- + +void btGeneric6DofConstraint::calculateLinearInfo() +{ + m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin(); + m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff; + for(int i = 0; i < 3; i++) + { + m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]); + } +} // btGeneric6DofConstraint::calculateLinearInfo() + +//----------------------------------------------------------------------------- + +int btGeneric6DofConstraint::get_limit_motor_info2( + btRotationalLimitMotor * limot, + btRigidBody * body0, btRigidBody * body1, + btConstraintInfo2 *info, int row, btVector3& ax1, int rotational) +{ + int srow = row * info->rowskip; + int powered = limot->m_enableMotor; + int limit = limot->m_currentLimit; + if (powered || limit) + { // if the joint is powered, or has joint limits, add in the extra row + btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; + btScalar *J2 = rotational ? info->m_J2angularAxis : 0; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + if(rotational) + { + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + } + if((!rotational) && limit) + { + btVector3 ltd; // Linear Torque Decoupling vector + btVector3 c = m_calculatedTransformB.getOrigin() - body0->getCenterOfMassPosition(); + ltd = c.cross(ax1); + info->m_J1angularAxis[srow+0] = ltd[0]; + info->m_J1angularAxis[srow+1] = ltd[1]; + info->m_J1angularAxis[srow+2] = ltd[2]; + + c = m_calculatedTransformB.getOrigin() - body1->getCenterOfMassPosition(); + ltd = -c.cross(ax1); + info->m_J2angularAxis[srow+0] = ltd[0]; + info->m_J2angularAxis[srow+1] = ltd[1]; + info->m_J2angularAxis[srow+2] = ltd[2]; + } + // if we're limited low and high simultaneously, the joint motor is + // ineffective + if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0; + info->m_constraintError[srow] = btScalar(0.f); + if (powered) + { + info->cfm[srow] = 0.0f; + if(!limit) + { + info->m_constraintError[srow] += limot->m_targetVelocity; + info->m_lowerLimit[srow] = -limot->m_maxMotorForce; + info->m_upperLimit[srow] = limot->m_maxMotorForce; + } + } + if(limit) + { + btScalar k = info->fps * limot->m_ERP; + if(!rotational) + { + info->m_constraintError[srow] += k * limot->m_currentLimitError; + } + else + { + info->m_constraintError[srow] += -k * limot->m_currentLimitError; + } + info->cfm[srow] = 0.0f; + if (limot->m_loLimit == limot->m_hiLimit) + { // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + if (limit == 1) + { + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // deal with bounce + if (limot->m_bounce > 0) + { + // calculate joint velocity + btScalar vel; + if (rotational) + { + vel = body0->getAngularVelocity().dot(ax1); + if (body1) + vel -= body1->getAngularVelocity().dot(ax1); + } + else + { + vel = body0->getLinearVelocity().dot(ax1); + if (body1) + vel -= body1->getLinearVelocity().dot(ax1); + } + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if (limit == 1) + { + if (vel < 0) + { + btScalar newc = -limot->m_bounce* vel; + if (newc > info->m_constraintError[srow]) + info->m_constraintError[srow] = newc; + } + } + else + { + if (vel > 0) + { + btScalar newc = -limot->m_bounce * vel; + if (newc < info->m_constraintError[srow]) + info->m_constraintError[srow] = newc; + } + } + } + } + } + return 1; + } + else return 0; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h index f0718d2d4a0..0ae161d5bdf 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -30,6 +30,8 @@ http://gimpact.sf.net class btRigidBody; + + //! Rotation Limit structure for generic joints class btRotationalLimitMotor { @@ -92,7 +94,7 @@ public: //! Is limited bool isLimited() { - if(m_loLimit>=m_hiLimit) return false; + if(m_loLimit > m_hiLimit) return false; return true; } @@ -110,8 +112,7 @@ public: int testLimitValue(btScalar test_value); //! apply the correction impulses for two bodies - btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); - + btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btSolverBody& bodyA,btRigidBody * body1,btSolverBody& bodyB); }; @@ -129,6 +130,11 @@ public: btScalar m_damping;//!< Damping for linear limit btScalar m_restitution;//! Bounce parameter for linear limit //!@} + bool m_enableMotor[3]; + btVector3 m_targetVelocity;//!< target motor velocity + btVector3 m_maxMotorForce;//!< max force on motor + btVector3 m_currentLimitError;//! How much is violated this limit + int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit btTranslationalLimitMotor() { @@ -139,6 +145,12 @@ public: m_limitSoftness = 0.7f; m_damping = btScalar(1.0f); m_restitution = btScalar(0.5f); + for(int i=0; i < 3; i++) + { + m_enableMotor[i] = false; + m_targetVelocity[i] = btScalar(0.f); + m_maxMotorForce[i] = btScalar(0.f); + } } btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) @@ -150,6 +162,12 @@ public: m_limitSoftness = other.m_limitSoftness ; m_damping = other.m_damping; m_restitution = other.m_restitution; + for(int i=0; i < 3; i++) + { + m_enableMotor[i] = other.m_enableMotor[i]; + m_targetVelocity[i] = other.m_targetVelocity[i]; + m_maxMotorForce[i] = other.m_maxMotorForce[i]; + } } //! Test limit @@ -163,13 +181,19 @@ public: { return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); } + inline bool needApplyForce(int limitIndex) + { + if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false; + return true; + } + int testLimitValue(int limitIndex, btScalar test_value); btScalar solveLinearAxis( btScalar timeStep, btScalar jacDiagABInv, - btRigidBody& body1,const btVector3 &pointInA, - btRigidBody& body2,const btVector3 &pointInB, + btRigidBody& body1,btSolverBody& bodyA,const btVector3 &pointInA, + btRigidBody& body2,btSolverBody& bodyB,const btVector3 &pointInB, int limit_index, const btVector3 & axis_normal_on_a, const btVector3 & anchorPos); @@ -247,6 +271,7 @@ protected: btTransform m_calculatedTransformB; btVector3 m_calculatedAxisAngleDiff; btVector3 m_calculatedAxis[3]; + btVector3 m_calculatedLinearDiff; btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes @@ -262,6 +287,9 @@ protected: } + int setAngularLimits(btConstraintInfo2 *info, int row_offset); + + int setLinearLimits(btConstraintInfo2 *info); void buildLinearJacobian( btJacobianEntry & jacLinear,const btVector3 & normalWorld, @@ -269,6 +297,8 @@ protected: void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); + // tests linear limits + void calculateLinearInfo(); //! calcs the euler angles between the two bodies. void calculateAngleInfo(); @@ -276,6 +306,10 @@ protected: public: + + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; + btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); btGeneric6DofConstraint(); @@ -330,7 +364,11 @@ public: //! performs Jacobian calculation, and also calculates angle differences and axis virtual void buildJacobian(); - virtual void solveConstraint(btScalar timeStep); + virtual void getInfo1 (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); void updateRHS(btScalar timeStep); @@ -432,6 +470,11 @@ public: virtual void calcAnchorPos(void); // overridable + int get_limit_motor_info2( btRotationalLimitMotor * limot, + btRigidBody * body0, btRigidBody * body1, + btConstraintInfo2 *info, int row, btVector3& ax1, int rotational); + + }; #endif //GENERIC_6DOF_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index a0523a8c76b..b6b34305804 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -19,19 +19,33 @@ subject to the following restrictions: #include "LinearMath/btTransformUtil.h" #include "LinearMath/btMinMax.h" #include +#include "btSolverBody.h" + +//----------------------------------------------------------------------------- + +#define HINGE_USE_OBSOLETE_SOLVER false + +//----------------------------------------------------------------------------- btHingeConstraint::btHingeConstraint() : btTypedConstraint (HINGE_CONSTRAINT_TYPE), -m_enableAngularMotor(false) +m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useReferenceFrameA(false) { + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); } +//----------------------------------------------------------------------------- + btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, - btVector3& axisInA,btVector3& axisInB) + btVector3& axisInA,btVector3& axisInB, bool useReferenceFrameA) :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), m_angularOnly(false), - m_enableAngularMotor(false) + m_enableAngularMotor(false), + m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), + m_useReferenceFrameA(useReferenceFrameA) { m_rbAFrame.getOrigin() = pivotInA; @@ -60,9 +74,9 @@ btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const bt 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() ); + 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); @@ -71,32 +85,28 @@ btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const bt m_relaxationFactor = 1.0f; m_limitSoftness = 0.9f; m_solveLimit = false; - + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); } +//----------------------------------------------------------------------------- -btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false) +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA, bool useReferenceFrameA) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useReferenceFrameA(useReferenceFrameA) { // 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); + btVector3 rbAxisA1, rbAxisA2; + btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2); 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; + btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA; btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); @@ -115,19 +125,19 @@ btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA, m_relaxationFactor = 1.0f; m_limitSoftness = 0.9f; m_solveLimit = false; + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); } +//----------------------------------------------------------------------------- + btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, - const btTransform& rbAFrame, const btTransform& rbBFrame) + const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), m_angularOnly(false), -m_enableAngularMotor(false) +m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useReferenceFrameA(useReferenceFrameA) { - // 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); @@ -135,22 +145,20 @@ m_enableAngularMotor(false) m_relaxationFactor = 1.0f; m_limitSoftness = 0.9f; m_solveLimit = false; + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); } +//----------------------------------------------------------------------------- - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame) +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA) :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), m_angularOnly(false), -m_enableAngularMotor(false) +m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useReferenceFrameA(useReferenceFrameA) { ///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 @@ -160,33 +168,38 @@ m_enableAngularMotor(false) m_relaxationFactor = 1.0f; m_limitSoftness = 0.9f; m_solveLimit = false; + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); } +//----------------------------------------------------------------------------- + void btHingeConstraint::buildJacobian() { - m_appliedImpulse = btScalar(0.); - - if (!m_angularOnly) + if (m_useSolveConstraintObsolete) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - btVector3 relPos = pivotBInW - pivotAInW; + m_appliedImpulse = btScalar(0.); - btVector3 normal[3]; - if (relPos.length2() > SIMD_EPSILON) + if (!m_angularOnly) { - normal[0] = relPos.normalized(); - } - else - { - normal[0].setValue(btScalar(1.0),0,0); - } + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; - btPlaneSpace1(normal[0], normal[1], normal[2]); + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } - for (int i=0;i<3;i++) - { - new (&m_jac[i]) btJacobianEntry( + btPlaneSpace1(normal[0], normal[1], normal[2]); + + for (int i=0;i<3;i++) + { + new (&m_jac[i]) btJacobianEntry( m_rbA.getCenterOfMassTransform().getBasis().transpose(), m_rbB.getCenterOfMassTransform().getBasis().transpose(), pivotAInW - m_rbA.getCenterOfMassPosition(), @@ -196,214 +209,458 @@ void btHingeConstraint::buildJacobian() m_rbA.getInvMass(), m_rbB.getInvInertiaDiagLocal(), m_rbB.getInvMass()); + } } - } - //calculate two perpendicular jointAxis, orthogonal to hingeAxis - //these two jointAxis require equal angular velocities for both bodies + //calculate two perpendicular jointAxis, orthogonal to hingeAxis + //these two jointAxis require equal angular velocities for both bodies - //this is unused for now, it's a todo - btVector3 jointAxis0local; - btVector3 jointAxis1local; - - btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); - - 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_rbAFrame.getBasis().getColumn(2); + //this is unused for now, it's a todo + btVector3 jointAxis0local; + btVector3 jointAxis1local; - new (&m_jacAng[0]) btJacobianEntry(jointAxis0, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); + btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); - new (&m_jacAng[1]) btJacobianEntry(jointAxis1, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); + 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_rbAFrame.getBasis().getColumn(2); + + new (&m_jacAng[0]) btJacobianEntry(jointAxis0, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); - new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); + new (&m_jacAng[1]) btJacobianEntry(jointAxis1, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); - // Compute limit information - btScalar hingeAngle = getHingeAngle(); + // clear accumulator + m_accLimitImpulse = btScalar(0.); - //set bias, sign, clear accumulator - m_correction = btScalar(0.); - m_limitSign = btScalar(0.); - m_solveLimit = false; - m_accLimitImpulse = btScalar(0.); + // test angular limit + testLimit(); + + //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)); -// 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) +//----------------------------------------------------------------------------- + +void btHingeConstraint::getInfo1(btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular + info->nub = 1; + //prepare constraint + testLimit(); + if(getSolveLimit() || getEnableAngularMotor()) + { + info->m_numConstraintRows++; // limit 3rd anguar as well + info->nub--; + } + } +} // btHingeConstraint::getInfo1 () + +//----------------------------------------------------------------------------- + +void btHingeConstraint::getInfo2 (btConstraintInfo2* info) +{ + btAssert(!m_useSolveConstraintObsolete); + int i, s = info->rowskip; + // transforms in world space + btTransform trA = m_rbA.getCenterOfMassTransform()*m_rbAFrame; + btTransform trB = m_rbB.getCenterOfMassTransform()*m_rbBFrame; + // pivot point + btVector3 pivotAInW = trA.getOrigin(); + btVector3 pivotBInW = trB.getOrigin(); + // linear (all fixed) + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[s + 1] = 1; + info->m_J1linearAxis[2 * s + 2] = 1; + btVector3 a1 = pivotAInW - m_rbA.getCenterOfMassTransform().getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + s); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * s); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + btVector3 a2 = pivotBInW - m_rbB.getCenterOfMassTransform().getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + s); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * s); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + // linear RHS + btScalar k = info->fps * info->erp; + for(i = 0; i < 3; i++) + { + info->m_constraintError[i * s] = k * (pivotBInW[i] - pivotAInW[i]); + } + // make rotations around X and Y equal + // the hinge axis should be the only unconstrained + // rotational axis, the angular velocity of the two bodies perpendicular to + // the hinge axis should be equal. thus the constraint equations are + // p*w1 - p*w2 = 0 + // q*w1 - q*w2 = 0 + // where p and q are unit vectors normal to the hinge axis, and w1 and w2 + // are the angular velocity vectors of the two bodies. + // get hinge axis (Z) + btVector3 ax1 = trA.getBasis().getColumn(2); + // get 2 orthos to hinge axis (X, Y) + btVector3 p = trA.getBasis().getColumn(0); + btVector3 q = trA.getBasis().getColumn(1); + // set the two hinge angular rows + int s3 = 3 * info->rowskip; + int s4 = 4 * info->rowskip; + + info->m_J1angularAxis[s3 + 0] = p[0]; + info->m_J1angularAxis[s3 + 1] = p[1]; + info->m_J1angularAxis[s3 + 2] = p[2]; + info->m_J1angularAxis[s4 + 0] = q[0]; + info->m_J1angularAxis[s4 + 1] = q[1]; + info->m_J1angularAxis[s4 + 2] = q[2]; + + info->m_J2angularAxis[s3 + 0] = -p[0]; + info->m_J2angularAxis[s3 + 1] = -p[1]; + info->m_J2angularAxis[s3 + 2] = -p[2]; + info->m_J2angularAxis[s4 + 0] = -q[0]; + info->m_J2angularAxis[s4 + 1] = -q[1]; + info->m_J2angularAxis[s4 + 2] = -q[2]; + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the hinge back into alignment. + // if ax1,ax2 are the unit length hinge axes as computed from body1 and + // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if `theta' is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. + btVector3 ax2 = trB.getBasis().getColumn(2); + btVector3 u = ax1.cross(ax2); + info->m_constraintError[s3] = k * u.dot(p); + info->m_constraintError[s4] = k * u.dot(q); + // check angular limits + int nrow = 4; // last filled row + int srow; + btScalar limit_err = btScalar(0.0); + int limit = 0; + if(getSolveLimit()) + { + limit_err = m_correction * m_referenceSign; + limit = (limit_err > btScalar(0.0)) ? 1 : 2; + } + // if the hinge has joint limits or motor, add in the extra row + int powered = 0; + if(getEnableAngularMotor()) + { + powered = 1; + } + if(limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1angularAxis[srow+0] = ax1[0]; + info->m_J1angularAxis[srow+1] = ax1[1]; + info->m_J1angularAxis[srow+2] = ax1[2]; + + info->m_J2angularAxis[srow+0] = -ax1[0]; + info->m_J2angularAxis[srow+1] = -ax1[1]; + info->m_J2angularAxis[srow+2] = -ax1[2]; + + btScalar lostop = getLowerLimit(); + btScalar histop = getUpperLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + info->m_constraintError[srow] = btScalar(0.0f); + if(powered) + { + info->cfm[srow] = btScalar(0.0); + btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * info->erp); + info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign; + info->m_lowerLimit[srow] = - m_maxMotorImpulse; + info->m_upperLimit[srow] = m_maxMotorImpulse; + } + if(limit) + { + k = info->fps * info->erp; + info->m_constraintError[srow] += k * limit_err; + info->cfm[srow] = btScalar(0.0); + if(lostop == histop) + { + // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { // high limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) + btScalar bounce = m_relaxationFactor; + if(bounce > btScalar(0.0)) + { + btScalar vel = m_rbA.getAngularVelocity().dot(ax1); + vel -= m_rbB.getAngularVelocity().dot(ax1); + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if(newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } + info->m_constraintError[srow] *= m_biasFactor; + } // if(limit) + } // if angular limit or powered +} + +//----------------------------------------------------------------------------- + +void btHingeConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - - btScalar tau = btScalar(0.3); - - //linear part - if (!m_angularOnly) + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + if (m_useSolveConstraintObsolete) { - 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; + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - for (int i=0;i<3;i++) - { - const btVector3& normal = m_jac[i].m_linearJointAxis; - btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + btScalar tau = btScalar(0.3); - 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; - 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()); - } - } - - - { - ///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); - - const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); - const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); - - btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); - btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); - - btVector3 angAorthog = angVelA - angVelAroundHingeAxisA; - btVector3 angBorthog = angVelB - angVelAroundHingeAxisB; - btVector3 velrelOrthog = angAorthog-angBorthog; + //linear part + if (!m_angularOnly) { - //solve orthogonal angular velocity correction - btScalar relaxation = btScalar(1.); - btScalar len = velrelOrthog.length(); - if (len > btScalar(0.00001)) - { - btVector3 normal = velrelOrthog.normalized(); - btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) + - getRigidBodyB().computeAngularImpulseDenominator(normal); - // scale for mass and relaxation - //todo: expose this 0.9 factor to developer - velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; - } + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - //solve angular positional correction - btVector3 angularError = -axisA.cross(axisB) *(btScalar(1.)/timeStep); - btScalar len2 = angularError.length(); - if (len2>btScalar(0.00001)) - { - btVector3 normal2 = angularError.normalized(); - btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) + - getRigidBodyB().computeAngularImpulseDenominator(normal2); - angularError *= (btScalar(1.)/denom2) * relaxation; - } + btVector3 vel1,vel2; + bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); + bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); + btVector3 vel = vel1 - vel2; - m_rbA.applyTorqueImpulse(-velrelOrthog+angularError); - m_rbB.applyTorqueImpulse(velrelOrthog-angularError); + for (int i=0;i<3;i++) + { + const btVector3& normal = m_jac[i].m_linearJointAxis; + btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - // 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); + 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; + m_appliedImpulse += impulse; + btVector3 impulse_vector = normal * impulse; + btVector3 ftorqueAxis1 = rel_pos1.cross(normal); + btVector3 ftorqueAxis2 = rel_pos2.cross(normal); + bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); + bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); } } - //apply motor - if (m_enableAngularMotor) + { - //todo: add limits too - btVector3 angularLimit(0,0,0); + ///solve angular part - btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; - btScalar projRelVel = velrel.dot(axisA); + // 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); - btScalar desiredMotorVel = m_motorTargetVelocity; - btScalar motor_relvel = desiredMotorVel - projRelVel; + btVector3 angVelA; + bodyA.getAngularVelocity(angVelA); + btVector3 angVelB; + bodyB.getAngularVelocity(angVelB); - 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; - btVector3 motorImp = clippedMotorImpulse * axisA; + btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); + btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); - m_rbA.applyTorqueImpulse(motorImp+angularLimit); - m_rbB.applyTorqueImpulse(-motorImp-angularLimit); + btVector3 angAorthog = angVelA - angVelAroundHingeAxisA; + btVector3 angBorthog = angVelB - angVelAroundHingeAxisB; + btVector3 velrelOrthog = angAorthog-angBorthog; + { + + + //solve orthogonal angular velocity correction + btScalar relaxation = btScalar(1.); + btScalar len = velrelOrthog.length(); + if (len > btScalar(0.00001)) + { + btVector3 normal = velrelOrthog.normalized(); + btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) + + getRigidBodyB().computeAngularImpulseDenominator(normal); + // scale for mass and relaxation + //velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*velrelOrthog,-(btScalar(1.)/denom)); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*velrelOrthog,(btScalar(1.)/denom)); + + } + + //solve angular positional correction + btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/timeStep); + btScalar len2 = angularError.length(); + if (len2>btScalar(0.00001)) + { + btVector3 normal2 = angularError.normalized(); + btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) + + getRigidBodyB().computeAngularImpulseDenominator(normal2); + //angularError *= (btScalar(1.)/denom2) * relaxation; + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*angularError,(btScalar(1.)/denom2)); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*angularError,-(btScalar(1.)/denom2)); + + } + + + + + + // 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; + + + + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,impulseMag * m_limitSign); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-(impulseMag * m_limitSign)); + + } + } + + //apply motor + if (m_enableAngularMotor) + { + //todo: add limits too + btVector3 angularLimit(0,0,0); + + btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; + btScalar projRelVel = velrel.dot(axisA); + + btScalar desiredMotorVel = m_motorTargetVelocity; + btScalar motor_relvel = desiredMotorVel - projRelVel; + + 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; + btVector3 motorImp = clippedMotorImpulse * axisA; + bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,clippedMotorImpulse); + bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-clippedMotorImpulse); + + } } } } +//----------------------------------------------------------------------------- + void btHingeConstraint::updateRHS(btScalar timeStep) { (void)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) ); + btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); + return m_referenceSign * angle; } +//----------------------------------------------------------------------------- + +void btHingeConstraint::testLimit() +{ + // Compute limit information + m_hingeAngle = getHingeAngle(); + m_correction = btScalar(0.); + m_limitSign = btScalar(0.); + m_solveLimit = false; + if (m_lowerLimit <= m_upperLimit) + { + if (m_hingeAngle <= m_lowerLimit) + { + m_correction = (m_lowerLimit - m_hingeAngle); + m_limitSign = 1.0f; + m_solveLimit = true; + } + else if (m_hingeAngle >= m_upperLimit) + { + m_correction = m_upperLimit - m_hingeAngle; + m_limitSign = -1.0f; + m_solveLimit = true; + } + } + return; +} // btHingeConstraint::testLimit() + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 4fa9972f6d8..0af655f4409 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -53,27 +53,35 @@ public: btScalar m_correction; btScalar m_accLimitImpulse; + btScalar m_hingeAngle; + btScalar m_referenceSign; bool m_angularOnly; bool m_enableAngularMotor; bool m_solveLimit; + bool m_useSolveConstraintObsolete; + bool m_useReferenceFrameA; 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, bool useReferenceFrameA = false); - btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA); + btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA, bool useReferenceFrameA = false); - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame); + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false); - btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame); + btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false); btHingeConstraint(); virtual void buildJacobian(); - virtual void solveConstraint(btScalar timeStep); + virtual void getInfo1 (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); void updateRHS(btScalar timeStep); @@ -86,6 +94,16 @@ public: return m_rbB; } + btRigidBody& getRigidBodyA() + { + return m_rbA; + } + + btRigidBody& getRigidBodyB() + { + return m_rbB; + } + void setAngularOnly(bool angularOnly) { m_angularOnly = angularOnly; @@ -122,6 +140,8 @@ public: btScalar getHingeAngle(); + void testLimit(); + const btTransform& getAFrame() { return m_rbAFrame; }; const btTransform& getBFrame() { return m_rbBFrame; }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp index 2b69ad90438..1da749517e8 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -21,33 +21,38 @@ subject to the following restrictions: btPoint2PointConstraint::btPoint2PointConstraint() -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE), +m_useSolveConstraintObsolete(false) { } 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(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), +m_useSolveConstraintObsolete(false) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), +m_useSolveConstraintObsolete(false) { } void btPoint2PointConstraint::buildJacobian() { - m_appliedImpulse = btScalar(0.); - - btVector3 normal(0,0,0); - - for (int i=0;i<3;i++) + ///we need it for both methods { - normal[i] = 1; - new (&m_jac[i]) btJacobianEntry( + m_appliedImpulse = btScalar(0.); + + btVector3 normal(0,0,0); + + 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(), @@ -58,64 +63,162 @@ void btPoint2PointConstraint::buildJacobian() m_rbB.getInvInertiaDiagLocal(), m_rbB.getInvMass()); normal[i] = 0; + } } } -void btPoint2PointConstraint::solveConstraint(btScalar timeStep) + +void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } else + { + info->m_numConstraintRows = 3; + info->nub = 3; + } +} +void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info) +{ + btAssert(!m_useSolveConstraintObsolete); - btVector3 normal(0,0,0); - + //retrieve matrices + btTransform body0_trans; + body0_trans = m_rbA.getCenterOfMassTransform(); + btTransform body1_trans; + body1_trans = m_rbB.getCenterOfMassTransform(); -// btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); -// btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); + // anchor points in global coordinates with respect to body PORs. + + // set jacobian + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip+1] = 1; + info->m_J1linearAxis[2*info->rowskip+2] = 1; - for (int i=0;i<3;i++) - { - 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(); - //this jacobian entry could be re-used for all iterations - - 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); - - /* - //velocity error (first order error) - btScalar rel_vel = m_jac[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, - m_rbB.getLinearVelocity(),angvelB); + btVector3 a1 = body0_trans.getBasis()*getPivotInA(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + + /*info->m_J2linearAxis[0] = -1; + info->m_J2linearAxis[s+1] = -1; + info->m_J2linearAxis[2*s+2] = -1; */ - //positional error (zeroth order error) - 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; + btVector3 a2 = body1_trans.getBasis()*getPivotInB(); + + { + btVector3 a2n = -a2; + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + - btScalar impulseClamp = m_setting.m_impulseClamp; - if (impulseClamp > 0) + + // set right hand side + btScalar k = info->fps * info->erp; + int j; + + for (j=0; j<3; j++) + { + info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); + //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]); + } + + btScalar impulseClamp = m_setting.m_impulseClamp;// + for (j=0; j<3; j++) + { + if (m_setting.m_impulseClamp > 0) { - if (impulse < -impulseClamp) - impulse = -impulseClamp; - if (impulse > impulseClamp) - impulse = impulseClamp; + info->m_lowerLimit[j*info->rowskip] = -impulseClamp; + info->m_upperLimit[j*info->rowskip] = impulseClamp; } + } + +} - 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()); + +void btPoint2PointConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) +{ + if (m_useSolveConstraintObsolete) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; + + + btVector3 normal(0,0,0); - normal[i] = 0; + + // btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); + // btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); + + for (int i=0;i<3;i++) + { + 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(); + //this jacobian entry could be re-used for all iterations + + btVector3 vel1,vel2; + bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); + bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); + btVector3 vel = vel1 - vel2; + + btScalar rel_vel; + rel_vel = normal.dot(vel); + + /* + //velocity error (first order error) + btScalar rel_vel = m_jac[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, + m_rbB.getLinearVelocity(),angvelB); + */ + + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + + btScalar deltaImpulse = depth*m_setting.m_tau/timeStep * jacDiagABInv - m_setting.m_damping * rel_vel * jacDiagABInv; + + btScalar impulseClamp = m_setting.m_impulseClamp; + + const btScalar sum = btScalar(m_appliedImpulse) + deltaImpulse; + if (sum < -impulseClamp) + { + deltaImpulse = -impulseClamp-m_appliedImpulse; + m_appliedImpulse = -impulseClamp; + } + else if (sum > impulseClamp) + { + deltaImpulse = impulseClamp-m_appliedImpulse; + m_appliedImpulse = impulseClamp; + } + else + { + m_appliedImpulse = sum; + } + + + btVector3 impulse_vector = normal * deltaImpulse; + + btVector3 ftorqueAxis1 = rel_pos1.cross(normal); + btVector3 ftorqueAxis2 = rel_pos2.cross(normal); + bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,deltaImpulse); + bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-deltaImpulse); + + + normal[i] = 0; + } } } diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index c9d5968530c..e2b865cd484 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -50,6 +50,9 @@ public: public: + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; + btConstraintSetting m_setting; btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB); @@ -60,8 +63,12 @@ public: virtual void buildJacobian(); + virtual void getInfo1 (btConstraintInfo1* info); - virtual void solveConstraint(btScalar timeStep); + virtual void getInfo2 (btConstraintInfo2* info); + + + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); void updateRHS(btScalar timeStep); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 41e336c9d17..6928bdb966b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -15,7 +15,6 @@ subject to the following restrictions: //#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" @@ -32,31 +31,156 @@ subject to the following restrictions: #include "LinearMath/btQuickprof.h" #include "btSolverBody.h" #include "btSolverConstraint.h" - - #include "LinearMath/btAlignedObjectArray.h" +#include //for memset - -int totalCpd = 0; - -int gTotalContactPoints = 0; - -struct btOrderIndex +btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() +:m_btSeed2(0) { - int m_manifoldIndex; - int m_pointIndex; -}; +} +btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() +{ +} + +#ifdef USE_SIMD +#include +#define vec_splat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) +static inline __m128 _vmathVfDot3( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps( vec0, vec1); + return _mm_add_ps( vec_splat( result, 0 ), _mm_add_ps( vec_splat( result, 1 ), vec_splat( result, 2 ) ) ); +} +#endif//USE_SIMD + +// Project Gauss Seidel or the equivalent Sequential Impulse +void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ +#ifdef USE_SIMD + __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(_vmathVfDot3(c.m_contactNormal.mVec128,body1.m_deltaLinearVelocity.mVec128), _vmathVfDot3(c.m_relpos1CrossNormal.mVec128,body1.m_deltaAngularVelocity.mVec128)); + __m128 deltaVel2Dotn = _mm_sub_ps(_vmathVfDot3(c.m_relpos2CrossNormal.mVec128,body2.m_deltaAngularVelocity.mVec128),_vmathVfDot3((c.m_contactNormal).mVec128,body2.m_deltaLinearVelocity.mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); + btSimdScalar resultLowerLess,resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + __m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) ); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,_mm_set1_ps(body1.m_invMass)); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,_mm_set1_ps(body2.m_invMass)); + __m128 impulseMagnitude = deltaImpulse; + body1.m_deltaLinearVelocity.mVec128 = _mm_add_ps(body1.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); + body1.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body1.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); + body2.m_deltaLinearVelocity.mVec128 = _mm_sub_ps(body2.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); + body2.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body2.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); +#else + resolveSingleConstraintRowGeneric(body1,body2,c); +#endif +} + +// Project Gauss Seidel or the equivalent Sequential Impulse + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.m_deltaLinearVelocity) + c.m_relpos1CrossNormal.dot(body1.m_deltaAngularVelocity); + const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.m_deltaLinearVelocity) + c.m_relpos2CrossNormal.dot(body2.m_deltaAngularVelocity); + + const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn; + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else if (sum > c.m_upperLimit) + { + deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_upperLimit; + } + else + { + c.m_appliedImpulse = sum; + } + if (body1.m_invMass) + body1.applyImpulse(c.m_contactNormal*body1.m_invMass,c.m_angularComponentA,deltaImpulse); + if (body2.m_invMass) + body2.applyImpulse(-c.m_contactNormal*body2.m_invMass,c.m_angularComponentB,deltaImpulse); +} + + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ +#ifdef USE_SIMD + __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(_vmathVfDot3(c.m_contactNormal.mVec128,body1.m_deltaLinearVelocity.mVec128), _vmathVfDot3(c.m_relpos1CrossNormal.mVec128,body1.m_deltaAngularVelocity.mVec128)); + __m128 deltaVel2Dotn = _mm_sub_ps(_vmathVfDot3(c.m_relpos2CrossNormal.mVec128,body2.m_deltaAngularVelocity.mVec128),_vmathVfDot3((c.m_contactNormal).mVec128,body2.m_deltaLinearVelocity.mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); + btSimdScalar resultLowerLess,resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,_mm_set1_ps(body1.m_invMass)); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,_mm_set1_ps(body2.m_invMass)); + __m128 impulseMagnitude = deltaImpulse; + body1.m_deltaLinearVelocity.mVec128 = _mm_add_ps(body1.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); + body1.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body1.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); + body2.m_deltaLinearVelocity.mVec128 = _mm_sub_ps(body2.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); + body2.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body2.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); +#else + resolveSingleConstraintRowLowerLimit(body1,body2,c); +#endif +} + +// Project Gauss Seidel or the equivalent Sequential Impulse + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.m_deltaLinearVelocity) + c.m_relpos1CrossNormal.dot(body1.m_deltaAngularVelocity); + const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.m_deltaLinearVelocity) + c.m_relpos2CrossNormal.dot(body2.m_deltaAngularVelocity); + + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else + { + c.m_appliedImpulse = sum; + } + if (body1.m_invMass) + body1.applyImpulse(c.m_contactNormal*body1.m_invMass,c.m_angularComponentA,deltaImpulse); + if (body2.m_invMass) + body2.applyImpulse(-c.m_contactNormal*body2.m_invMass,c.m_angularComponentB,deltaImpulse); +} -#define SEQUENTIAL_IMPULSE_MAX_SOLVER_POINTS 16384 -static btOrderIndex gOrder[SEQUENTIAL_IMPULSE_MAX_SOLVER_POINTS]; unsigned long btSequentialImpulseConstraintSolver::btRand2() { - m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff; - return m_btSeed2; + m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff; + return m_btSeed2; } @@ -64,437 +188,63 @@ unsigned long btSequentialImpulseConstraintSolver::btRand2() //See ODE: adam's all-int straightforward(?) dRandInt (0..n-1) int btSequentialImpulseConstraintSolver::btRandInt2 (int n) { - // seems good; xor-fold and modulus - const unsigned long un = static_cast(n); - unsigned long r = btRand2(); + // seems good; xor-fold and modulus + const unsigned long un = static_cast(n); + unsigned long r = btRand2(); - // note: probably more aggressive than it needs to be -- might be - // able to get away without one or two of the innermost branches. - if (un <= 0x00010000UL) { - r ^= (r >> 16); - if (un <= 0x00000100UL) { - r ^= (r >> 8); - if (un <= 0x00000010UL) { - r ^= (r >> 4); - if (un <= 0x00000004UL) { - r ^= (r >> 2); - if (un <= 0x00000002UL) { - r ^= (r >> 1); - } - } - } - } - } - - return (int) (r % un); -} - - - - -bool MyContactDestroyedCallback(void* userPersistentData); -bool MyContactDestroyedCallback(void* userPersistentData) -{ - assert (userPersistentData); - btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData; - btAlignedFree(cpd); - totalCpd--; - //printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData); - return true; -} - - - -btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() -:m_btSeed2(0) -{ - gContactDestroyedCallback = &MyContactDestroyedCallback; - - //initialize default friction/contact funcs - int i,j; - for (i=0;i> 16); + if (un <= 0x00000100UL) { + r ^= (r >> 8); + if (un <= 0x00000010UL) { + r ^= (r >> 4); + if (un <= 0x00000004UL) { + r ^= (r >> 2); + if (un <= 0x00000002UL) { + r ^= (r >> 1); + } + } + } } + } + + return (int) (r % un); } -btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() -{ -} -void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject); -void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject) +void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject) { - btRigidBody* rb = btRigidBody::upcast(collisionObject); + btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0; + + solverBody->m_deltaLinearVelocity.setValue(0.f,0.f,0.f); + solverBody->m_deltaAngularVelocity.setValue(0.f,0.f,0.f); + 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 btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution) { btScalar rest = restitution * -rel_vel; return rest; } -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( - btSolverBody& body1, - btSolverBody& body2, - 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; - - { - - - // 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) - + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); - btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) - + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); - - 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 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_appliedImpulse; - btScalar sum = oldNormalImpulse + normalImpulse; - contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - - normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; - - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, - contactConstraint.m_angularComponentA,normalImpulse); - - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, - contactConstraint.m_angularComponentB,-normalImpulse); - } - - return normalImpulse; -} - -//#define NO_FRICTION_TANGENTIALS 1 -#ifndef NO_FRICTION_TANGENTIALS - -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, - const btContactSolverInfo& solverInfo, - btScalar appliedNormalImpulse) -{ - (void)solverInfo; - - - const btScalar combinedFriction = contactConstraint.m_friction; - - const btScalar limit = appliedNormalImpulse * combinedFriction; - - if (appliedNormalImpulse>btScalar(0.)) - //friction - { - - btScalar j1; - { - - btScalar rel_vel; - const btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) - + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); - const btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) - + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); - rel_vel = vel1Dotn-vel2Dotn; - - // 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; - } - 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); - - } - return 0.f; -} - - -#else - -//velocity + friction -//response between two dynamic objects with friction -btScalar resolveSingleFrictionCacheFriendly( - btSolverBody& body1, - btSolverBody& body2, - btSolverConstraint& contactConstraint, - const btContactSolverInfo& solverInfo) -{ - - btVector3 vel1; - btVector3 vel2; - btScalar normalImpulse(0.f); - - { - const btVector3& normal = contactConstraint.m_contactNormal; - if (contactConstraint.m_penetration < 0.f) - return 0.f; - - - body1.getVelocityInLocalPoint(contactConstraint.m_relpos1CrossNormal,vel1); - body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = normal.dot(vel); - - btVector3 lat_vel = vel - normal * rel_vel; - btScalar lat_rel_vel = lat_vel.length2(); - - btScalar combinedFriction = contactConstraint.m_friction; - const btVector3& rel_pos1 = contactConstraint.m_rel_posA; - const btVector3& rel_pos2 = contactConstraint.m_rel_posB; - - - if (lat_rel_vel > SIMD_EPSILON*SIMD_EPSILON) - { - lat_rel_vel = btSqrt(lat_rel_vel); - - lat_vel /= lat_rel_vel; - btVector3 temp1 = body1.m_invInertiaWorld * rel_pos1.cross(lat_vel); - 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; - - btSetMin(friction_impulse, normal_impulse); - btSetMin(friction_impulse, -normal_impulse); - body1.internalApplyImpulse(lat_vel * -friction_impulse, rel_pos1); - body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); - } - } - - return normalImpulse; -} - -#endif //NO_FRICTION_TANGENTIALS - - - - - -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; - - -} - void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection); void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection) @@ -513,6 +263,368 @@ void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirec +btSolverConstraint& 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_tmpSolverContactFrictionConstraintPool.expand(); + memset(&solverConstraint,0xff,sizeof(btSolverConstraint)); + solverConstraint.m_contactNormal = normalAxis; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_frictionIndex = frictionIndex; + + solverConstraint.m_friction = cp.m_combinedFriction; + solverConstraint.m_originalContactPoint = 0; + + solverConstraint.m_appliedImpulse = 0.f; + // solverConstraint.m_appliedPushImpulse = 0.f; + + { + btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0); + } + { + btVector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : 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; + +#ifdef _USE_JACOBIAN + solverConstraint.m_jac = btJacobianEntry ( + rel_pos1,rel_pos2,solverConstraint.m_contactNormal, + body0->getInvInertiaDiagLocal(), + body0->getInvMass(), + body1->getInvInertiaDiagLocal(), + body1->getInvMass()); +#endif //_USE_JACOBIAN + + + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?body0->getLinearVelocity():btVector3(0,0,0)) + + solverConstraint.m_relpos1CrossNormal.dot(body0?body0->getAngularVelocity():btVector3(0,0,0)); + btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?body1->getLinearVelocity():btVector3(0,0,0)) + + solverConstraint.m_relpos2CrossNormal.dot(body1?body1->getAngularVelocity():btVector3(0,0,0)); + + rel_vel = vel1Dotn+vel2Dotn; + + btScalar positionalError = 0.f; + + btSimdScalar velocityError = - rel_vel; + btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv); + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_cfm = 0.f; + solverConstraint.m_lowerLimit = 0; + solverConstraint.m_upperLimit = 1e10f; + } + + return solverConstraint; +} + +int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body) +{ + int solverBodyIdA = -1; + + if (body.getCompanionId() >= 0) + { + //body has already been converted + solverBodyIdA = body.getCompanionId(); + } else + { + btRigidBody* rb = btRigidBody::upcast(&body); + if (rb && rb->getInvMass()) + { + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,&body); + body.setCompanionId(solverBodyIdA); + } else + { + return 0;//assume first one is a fixed solver body + } + } + return solverBodyIdA; +} +#include + + + +void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal) +{ + btCollisionObject* colObj0=0,*colObj1=0; + + colObj0 = (btCollisionObject*)manifold->getBody0(); + colObj1 = (btCollisionObject*)manifold->getBody1(); + + int solverBodyIdA=-1; + int solverBodyIdB=-1; + + if (manifold->getNumContacts()) + { + solverBodyIdA = getOrInitSolverBody(*colObj0); + solverBodyIdB = getOrInitSolverBody(*colObj1); + } + + btVector3 rel_pos1; + btVector3 rel_pos2; + btScalar relaxation; + + for (int j=0;jgetNumContacts();j++) + { + + btManifoldPoint& cp = manifold->getContactPoint(j); + + if (cp.getDistance() <= manifold->getContactProcessingThreshold()) + { + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); + rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); + + + relaxation = 1.f; + btScalar rel_vel; + btVector3 vel; + + int frictionIndex = m_tmpSolverContactConstraintPool.size(); + + { + btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expand(); + btRigidBody* rb0 = btRigidBody::upcast(colObj0); + btRigidBody* rb1 = btRigidBody::upcast(colObj1); + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + + solverConstraint.m_originalContactPoint = &cp; + + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); + { +#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; + } + + solverConstraint.m_contactNormal = cp.m_normalWorldOnB; + solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB); + 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); + + vel = vel1 - vel2; + + rel_vel = cp.m_normalWorldOnB.dot(vel); + + btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop; + + + solverConstraint.m_friction = cp.m_combinedFriction; + + btScalar restitution = 0.f; + + if (cp.m_lifeTime>infoGlobal.m_restingContactRestitutionThreshold) + { + restitution = 0.f; + } else + { + restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (restitution <= btScalar(0.)) + { + restitution = 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].applyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass(),-solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse); + } else + { + solverConstraint.m_appliedImpulse = 0.f; + } + + // solverConstraint.m_appliedPushImpulse = 0.f; + + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0?rb0->getLinearVelocity():btVector3(0,0,0)) + + solverConstraint.m_relpos1CrossNormal.dot(rb0?rb0->getAngularVelocity():btVector3(0,0,0)); + btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1?rb1->getLinearVelocity():btVector3(0,0,0)) + + solverConstraint.m_relpos2CrossNormal.dot(rb1?rb1->getAngularVelocity():btVector3(0,0,0)); + + rel_vel = vel1Dotn+vel2Dotn; + + btScalar positionalError = 0.f; + positionalError = -penetration * infoGlobal.m_erp/infoGlobal.m_timeStep; + btScalar velocityError = restitution - rel_vel;// * damping; + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_cfm = 0.f; + solverConstraint.m_lowerLimit = 0; + solverConstraint.m_upperLimit = 1e10f; + } + + + /////setup the friction constraints + + + + if (1) + { + solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size(); + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized) + { + cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); + if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON) + { + cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel); + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); + cp.m_lateralFrictionDir2.normalize();//?? + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } + cp.m_lateralFrictionInitialized = true; + } else + { + //re-calculate friction direction every frame, todo: check if this is really needed + btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1); + + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2); + 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); + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } + + if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) + { + { + btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[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].applyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass(),-frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse); + } else + { + frictionConstraint1.m_appliedImpulse = 0.f; + } + } + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[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].applyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-frictionConstraint2.m_appliedImpulse); + } else + { + frictionConstraint2.m_appliedImpulse = 0.f; + } + } + } else + { + btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex]; + frictionConstraint1.m_appliedImpulse = 0.f; + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; + frictionConstraint2.m_appliedImpulse = 0.f; + } + } + } + } + + + } + } +} + btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** /*bodies */,int /*numBodies */,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) { @@ -523,331 +635,11 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol if (!(numConstraints + numManifolds)) { -// printf("empty\n"); + // 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(); - - manifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); - - } - - END_PROFILE("refreshManifolds"); -#endif //FORCE_REFESH_CONTACT_MANIFOLDS - - - - - - //int sizeofSB = sizeof(btSolverBody); - //int sizeofSC = sizeof(btSolverConstraint); - - - //if (1) - { - //if m_stackAlloc, try to pack bodies/constraints to speed up solving -// btBlock* sablock; -// sablock = stackAlloc->beginBlock(); - - // int memsize = 16; -// unsigned char* stackMemory = stackAlloc->allocate(memsize); - - - //todo: use stack allocator for this temp memory -// int minReservation = numManifolds*2; - - //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 = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb); - rb->setCompanionId(solverBodyId); - } - } - } -*/ - - //m_tmpSolverConstraintPool.reserve(minReservation); - //m_tmpSolverFrictionConstraintPool.reserve(minReservation); - - { - int i; - - for (i=0;igetBody0(); - colObj1 = (btCollisionObject*)manifold->getBody1(); - - int solverBodyIdA=-1; - int solverBodyIdB=-1; - - if (manifold->getNumContacts()) - { - - - - if (colObj0->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); - } - } else - { - //create a static body - solverBodyIdA = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,colObj0); - } - - if (colObj1->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); - } - } else - { - //create a static body - 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); - - 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(); - - - relaxation = 1.f; - btScalar rel_vel; - btVector3 vel; - - int frictionIndex = m_tmpSolverConstraintPool.size(); - - { - 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); - { -#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; - } - - solverConstraint.m_contactNormal = cp.m_normalWorldOnB; - solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB); - 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); - - 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_friction = cp.m_combinedFriction; - solverConstraint.m_restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); - if (solverConstraint.m_restitution <= btScalar(0.)) - { - solverConstraint.m_restitution = 0.f; - }; - - - btScalar penVel = -solverConstraint.m_penetration/infoGlobal.m_timeStep; - - - - if (solverConstraint.m_restitution > penVel) - { - solverConstraint.m_penetration = btScalar(0.); - } - - - - ///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; - - //scale anisotropic friction - - applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1); - applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1); - - 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(); - applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2); - applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2); - - 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); - applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2); - applyAnisotropicFriction(colObj1,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; - } - } - } - - - } - } - } - } - } - - btContactSolverInfo info = infoGlobal; + if (1) { int j; for (j=0;jbuildJacobian(); } } - - - int numConstraintPool = m_tmpSolverConstraintPool.size(); - int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); + btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&fixedBody,0); - ///todo: use stack allocator for such temporarily memory, same for solver bodies/constraints + //btRigidBody* rb0=0,*rb1=0; + + //if (1) + { + { + + int totalNumRows = 0; + int i; + //calculate the total number of contraint rows + for (i=0;igetInfo1(&info1); + totalNumRows += info1.m_numConstraintRows; + } + m_tmpSolverNonContactConstraintPool.resize(totalNumRows); + + btTypedConstraint::btConstraintInfo1 info1; + info1.m_numConstraintRows = 0; + + + ///setup the btSolverConstraints + int currentRow = 0; + + for (i=0;igetInfo1(&info1); + if (info1.m_numConstraintRows) + { + btAssert(currentRowgetRigidBodyA(); + btRigidBody& rbB = constraint->getRigidBodyB(); + + int solverBodyIdA = getOrInitSolverBody(rbA); + int solverBodyIdB = getOrInitSolverBody(rbB); + + btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB]; + + int j; + for ( j=0;jm_deltaLinearVelocity.setValue(0.f,0.f,0.f); + bodyAPtr->m_deltaAngularVelocity.setValue(0.f,0.f,0.f); + bodyBPtr->m_deltaLinearVelocity.setValue(0.f,0.f,0.f); + bodyBPtr->m_deltaAngularVelocity.setValue(0.f,0.f,0.f); + + + + btTypedConstraint::btConstraintInfo2 info2; + info2.fps = 1.f/infoGlobal.m_timeStep; + info2.erp = infoGlobal.m_erp; + info2.m_J1linearAxis = currentConstraintRow->m_contactNormal; + info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; + info2.m_J2linearAxis = 0; + info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; + info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this + ///the size of btSolverConstraint needs be a multiple of btScalar + btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); + info2.m_constraintError = ¤tConstraintRow->m_rhs; + info2.cfm = ¤tConstraintRow->m_cfm; + info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit; + info2.m_upperLimit = ¤tConstraintRow->m_upperLimit; + constraints[i]->getInfo2(&info2); + + ///finalize the constraint setup + for ( j=0;jgetRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); + } + { + const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; + solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); + } + + { + btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass(); + btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; + btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal? + btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; + + btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal); + sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); + sum += iMJlB.dot(solverConstraint.m_contactNormal); + sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); + + solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; + } + + + ///fix rhs + ///todo: add force/torque accelerators + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()); + btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()); + + rel_vel = vel1Dotn+vel2Dotn; + + btScalar restitution = 0.f; + btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 + btScalar velocityError = restitution - rel_vel;// * damping; + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_appliedImpulse = 0.f; + + } + } + } + } + } + + { + int i; + btPersistentManifold* manifold = 0; + btCollisionObject* colObj0=0,*colObj1=0; + + + for (i=0;igetRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) + ///solve all joint constraints, using SIMD, if available + for (j=0;jgetRigidBodyA().getCompanionId()].writebackVelocity(); - } - if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) - { - m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); + btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j]; + resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint); } - constraint->solveConstraint(infoGlobal.m_timeStep); - - if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) + for (j=0;jgetRigidBodyA().getCompanionId()].readVelocity(); - } - if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) - { - m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); + int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA()); + int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB()); + btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; + btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; + constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep); } - } - - { - int numPoolConstraints = m_tmpSolverConstraintPool.size(); + ///solve all contact constraints using SIMD, if available + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); for (j=0;jbtScalar(0)) { - const btSolverConstraint& solveManifold = m_tmpSolverConstraintPool[m_orderTmpConstraintPool[j]]; + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], - m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal); + resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + } + } + } else + { + + ///solve all joint constraints + for (j=0;jgetRigidBodyA()); + int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB()); + btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; + btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; + + constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep); + } + + ///solve all contact constraints + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + for (j=0;jbtScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + + resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); } } } + + } - } - return 0.f; } -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) + +/// btSequentialImpulseConstraintSolver Sequentially applies impulses +btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* /*dispatcher*/) { + + + + BT_PROFILE("solveGroup"); + //we only implement SOLVER_CACHE_FRIENDLY now + //you need to provide at least some bodies + btAssert(bodies); + btAssert(numBodies); + int i; solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc); solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc); - int numPoolConstraints = m_tmpSolverConstraintPool.size(); + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); int j; + for (j=0;jm_appliedImpulse = solveManifold.m_appliedImpulse; - pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; - pt->m_appliedImpulseLateral2 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; + if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING) + { + pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; + pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; + } //do a callback here? - } if (infoGlobal.m_splitImpulse) @@ -1030,418 +997,26 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio } else { for ( i=0;igetNumContacts();p++) - { - gOrder[totalPoints].m_manifoldIndex = j; - gOrder[totalPoints].m_pointIndex = p; - totalPoints++; - } - } - } - - { - int j; - for (j=0;jbuildJacobian(); - } - } - - - //should traverse the contacts random order... - int iteration; - - { - for ( iteration = 0;iterationsolveConstraint(info.m_timeStep); - } - - for (j=0;jgetBody0(), - (btRigidBody*)manifold->getBody1() - ,manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); - } - - for (j=0;jgetBody0(), - (btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); - } - - } - } - - - - - return btScalar(0.); -} - - - - - - - -void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer) -{ - - (void)debugDrawer; - - btRigidBody* body0 = (btRigidBody*)manifoldPtr->getBody0(); - btRigidBody* body1 = (btRigidBody*)manifoldPtr->getBody1(); - - - //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; - - - for (int i=0;igetContactPoint(i); - if (cp.getDistance() <= btScalar(0.)) - { - const btVector3& pos1 = cp.getPositionWorldOnA(); - const btVector3& pos2 = cp.getPositionWorldOnB(); - - btVector3 rel_pos1 = pos1 - body0->getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body1->getCenterOfMassPosition(); - - - //this jacobian entry is re-used for all iterations - btJacobianEntry jac(body0->getCenterOfMassTransform().getBasis().transpose(), - body1->getCenterOfMassTransform().getBasis().transpose(), - rel_pos1,rel_pos2,cp.m_normalWorldOnB,body0->getInvInertiaDiagLocal(),body0->getInvMass(), - body1->getInvInertiaDiagLocal(),body1->getInvMass()); - - - btScalar jacDiagAB = jac.getDiagonal(); - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; - if (cpd) - { - //might be invalid - cpd->m_persistentLifeTime++; - if (cpd->m_persistentLifeTime != cp.getLifeTime()) - { - //printf("Invalid: cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd->m_persistentLifeTime,cp.getLifeTime()); - new (cpd) btConstraintPersistentData; - cpd->m_persistentLifeTime = cp.getLifeTime(); - - } else - { - //printf("Persistent: cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd->m_persistentLifeTime,cp.getLifeTime()); - - } - } else - { - - //todo: should this be in a pool? - void* mem = btAlignedAlloc(sizeof(btConstraintPersistentData),16); - cpd = new (mem)btConstraintPersistentData; - assert(cpd); - - totalCpd ++; - //printf("totalCpd = %i Created Ptr %x\n",totalCpd,cpd); - cp.m_userPersistentData = cpd; - cpd->m_persistentLifeTime = cp.getLifeTime(); - //printf("CREATED: %x . cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd,cpd->m_persistentLifeTime,cp.getLifeTime()); - - } - assert(cpd); - - cpd->m_jacDiagABInv = btScalar(1.) / jacDiagAB; - - //Dependent on Rigidbody A and B types, fetch the contact/friction response func - //perhaps do a similar thing for friction/restutution combiner funcs... - - cpd->m_frictionSolverFunc = m_frictionDispatch[body0->m_frictionSolverType][body1->m_frictionSolverType]; - cpd->m_contactSolverFunc = m_contactDispatch[body0->m_contactSolverType][body1->m_contactSolverType]; - - btVector3 vel1 = body0->getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body1->getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = cp.m_normalWorldOnB.dot(vel); - - btScalar combinedRestitution = cp.m_combinedRestitution; - - cpd->m_penetration = cp.getDistance();///btScalar(info.m_numIterations); - cpd->m_friction = cp.m_combinedFriction; - cpd->m_restitution = restitutionCurve(rel_vel, combinedRestitution); - if (cpd->m_restitution <= btScalar(0.)) - { - cpd->m_restitution = btScalar(0.0); - - }; - - //restitution and penetration work in same direction so - //rel_vel - - btScalar penVel = -cpd->m_penetration/info.m_timeStep; - - if (cpd->m_restitution > penVel) - { - cpd->m_penetration = btScalar(0.); - } - - - btScalar relaxation = info.m_damping; - if (info.m_solverMode & SOLVER_USE_WARMSTARTING) - { - cpd->m_appliedImpulse *= relaxation; - } else - { - cpd->m_appliedImpulse =btScalar(0.); - } - - //for friction - cpd->m_prevAppliedImpulse = cpd->m_appliedImpulse; - - //re-calculate friction direction every frame, todo: check if this is really needed - btPlaneSpace1(cp.m_normalWorldOnB,cpd->m_frictionWorldTangential0,cpd->m_frictionWorldTangential1); - - -#define NO_FRICTION_WARMSTART 1 - - #ifdef NO_FRICTION_WARMSTART - cpd->m_accumulatedTangentImpulse0 = btScalar(0.); - cpd->m_accumulatedTangentImpulse1 = btScalar(0.); - #endif //NO_FRICTION_WARMSTART - btScalar denom0 = body0->computeImpulseDenominator(pos1,cpd->m_frictionWorldTangential0); - btScalar denom1 = body1->computeImpulseDenominator(pos2,cpd->m_frictionWorldTangential0); - btScalar denom = relaxation/(denom0+denom1); - cpd->m_jacDiagABInvTangent0 = denom; - - - denom0 = body0->computeImpulseDenominator(pos1,cpd->m_frictionWorldTangential1); - denom1 = body1->computeImpulseDenominator(pos2,cpd->m_frictionWorldTangential1); - denom = relaxation/(denom0+denom1); - cpd->m_jacDiagABInvTangent1 = denom; - - btVector3 totalImpulse = - #ifndef NO_FRICTION_WARMSTART - cpd->m_frictionWorldTangential0*cpd->m_accumulatedTangentImpulse0+ - cpd->m_frictionWorldTangential1*cpd->m_accumulatedTangentImpulse1+ - #endif //NO_FRICTION_WARMSTART - cp.m_normalWorldOnB*cpd->m_appliedImpulse; - - - - /// - { - btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); - cpd->m_angularComponentA = body0->getInvInertiaTensorWorld()*torqueAxis0; - btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); - cpd->m_angularComponentB = body1->getInvInertiaTensorWorld()*torqueAxis1; - } - { - btVector3 ftorqueAxis0 = rel_pos1.cross(cpd->m_frictionWorldTangential0); - cpd->m_frictionAngularComponent0A = body0->getInvInertiaTensorWorld()*ftorqueAxis0; - } - { - btVector3 ftorqueAxis1 = rel_pos1.cross(cpd->m_frictionWorldTangential1); - cpd->m_frictionAngularComponent1A = body0->getInvInertiaTensorWorld()*ftorqueAxis1; - } - { - btVector3 ftorqueAxis0 = rel_pos2.cross(cpd->m_frictionWorldTangential0); - cpd->m_frictionAngularComponent0B = body1->getInvInertiaTensorWorld()*ftorqueAxis0; - } - { - btVector3 ftorqueAxis1 = rel_pos2.cross(cpd->m_frictionWorldTangential1); - cpd->m_frictionAngularComponent1B = body1->getInvInertiaTensorWorld()*ftorqueAxis1; - } - - /// - - - - //apply previous frames impulse on both bodies - body0->applyImpulse(totalImpulse, rel_pos1); - body1->applyImpulse(-totalImpulse, rel_pos2); - } - - } - } -} - - -btScalar btSequentialImpulseConstraintSolver::solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) -{ - btScalar maxImpulse = btScalar(0.); - - { - - - { - if (cp.getDistance() <= btScalar(0.)) - { - - - - { - - //btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; - btScalar impulse = resolveSingleCollisionCombined( - *body0,*body1, - cp, - info); - - if (maxImpulse < impulse) - maxImpulse = impulse; - - } - } - } - } - return maxImpulse; -} - - - -btScalar btSequentialImpulseConstraintSolver::solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) -{ - - btScalar maxImpulse = btScalar(0.); - - { - - - { - if (cp.getDistance() <= btScalar(0.)) - { - - - - { - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; - btScalar impulse = cpd->m_contactSolverFunc( - *body0,*body1, - cp, - info); - - if (maxImpulse < impulse) - maxImpulse = impulse; - - } - } - } - } - return maxImpulse; -} - -btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) -{ - - (void)debugDrawer; - (void)iter; - - - { - - - { - - if (cp.getDistance() <= btScalar(0.)) - { - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; - cpd->m_frictionSolverFunc( - *body0,*body1, - cp, - info); - - - } - } - - - } - return btScalar(0.); -} void btSequentialImpulseConstraintSolver::reset() diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index 7143bc41991..467e37bb91f 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -23,67 +23,62 @@ class btIDebugDraw; #include "btSolverConstraint.h" -/// btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses -/// The approach is the 3D version of Erin Catto's GDC 2006 tutorial. See http://www.gphysics.com -/// Although Sequential Impulse is more intuitive, it is mathematically equivalent to Projected Successive Overrelaxation (iterative LCP) -/// Applies impulses for combined restitution and penetration recovery and to simulate friction + +///The btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses +///The approach is the 3D version of Erin Catto's GDC 2006 tutorial. See http://www.gphysics.com +///Although Sequential Impulse is more intuitive, it is mathematically equivalent to Projected Successive Overrelaxation (iterative LCP) +///Applies impulses for combined restitution and penetration recovery and to simulate friction class btSequentialImpulseConstraintSolver : public btConstraintSolver { +protected: btAlignedObjectArray m_tmpSolverBodyPool; - btAlignedObjectArray m_tmpSolverConstraintPool; - btAlignedObjectArray m_tmpSolverFrictionConstraintPool; + btConstraintArray m_tmpSolverContactConstraintPool; + btConstraintArray m_tmpSolverNonContactConstraintPool; + btConstraintArray m_tmpSolverContactFrictionConstraintPool; 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]; - + btSolverConstraint& 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); ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction unsigned long m_btSeed2; + void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject); + btScalar restitutionCurve(btScalar rel_vel, btScalar restitution); + + void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal); + + void resolveSplitPenetrationImpulseCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo); + + //internal method + int getOrInitSolverBody(btCollisionObject& body); + + void resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& contactConstraint); + public: btSequentialImpulseConstraintSolver(); - - ///Advanced: Override the default contact solving function for contacts, for certain types of rigidbody - ///See btRigidBody::m_contactSolverType and btRigidBody::m_frictionSolverType - void setContactSolverFunc(ContactSolverFunc func,int type0,int type1) - { - m_contactDispatch[type0][type1] = func; - } - - ///Advanced: Override the default friction solving function for contacts, for certain types of rigidbody - ///See btRigidBody::m_contactSolverType and btRigidBody::m_frictionSolverType - void SetFrictionSolverFunc(ContactSolverFunc func,int type0,int type1) - { - m_frictionDispatch[type0][type1] = func; - } - 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 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); - + btScalar solveGroupCacheFriendlyIterations(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); - - unsigned long btRand2(); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp index 4128f504bf1..50d06960379 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp @@ -68,7 +68,9 @@ void btSliderConstraint::initParams() btSliderConstraint::btSliderConstraint() :btTypedConstraint(SLIDER_CONSTRAINT_TYPE), - m_useLinearReferenceFrameA(true) + m_useLinearReferenceFrameA(true), + m_useSolveConstraintObsolete(false) +// m_useSolveConstraintObsolete(true) { initParams(); } // btSliderConstraint::btSliderConstraint() @@ -79,7 +81,9 @@ btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB) , m_frameInA(frameInA) , m_frameInB(frameInB), - m_useLinearReferenceFrameA(useLinearReferenceFrameA) + m_useLinearReferenceFrameA(useLinearReferenceFrameA), + m_useSolveConstraintObsolete(false) +// m_useSolveConstraintObsolete(true) { initParams(); } // btSliderConstraint::btSliderConstraint() @@ -88,6 +92,10 @@ btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const void btSliderConstraint::buildJacobian() { + if (!m_useSolveConstraintObsolete) + { + return; + } if(m_useLinearReferenceFrameA) { buildJacobianInt(m_rbA, m_rbB, m_frameInA, m_frameInB); @@ -155,27 +163,372 @@ void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, co //----------------------------------------------------------------------------- -void btSliderConstraint::solveConstraint(btScalar timeStep) +void btSliderConstraint::getInfo1(btConstraintInfo1* info) { - m_timeStep = timeStep; - if(m_useLinearReferenceFrameA) + if (m_useSolveConstraintObsolete) { - solveConstraintInt(m_rbA, m_rbB); + info->m_numConstraintRows = 0; + info->nub = 0; } else { - solveConstraintInt(m_rbB, m_rbA); + info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular + info->nub = 2; + //prepare constraint + calculateTransforms(); + testLinLimits(); + if(getSolveLinLimit() || getPoweredLinMotor()) + { + info->m_numConstraintRows++; // limit 3rd linear as well + info->nub--; + } + testAngLimits(); + if(getSolveAngLimit() || getPoweredAngMotor()) + { + info->m_numConstraintRows++; // limit 3rd angular as well + info->nub--; + } + } +} // btSliderConstraint::getInfo1() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::getInfo2(btConstraintInfo2* info) +{ + btAssert(!m_useSolveConstraintObsolete); + int i, s = info->rowskip; + const btTransform& trA = getCalculatedTransformA(); + const btTransform& trB = getCalculatedTransformB(); + btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f); + // make rotations around Y and Z equal + // the slider axis should be the only unconstrained + // rotational axis, the angular velocity of the two bodies perpendicular to + // the slider axis should be equal. thus the constraint equations are + // p*w1 - p*w2 = 0 + // q*w1 - q*w2 = 0 + // where p and q are unit vectors normal to the slider axis, and w1 and w2 + // are the angular velocity vectors of the two bodies. + // get slider axis (X) + btVector3 ax1 = trA.getBasis().getColumn(0); + // get 2 orthos to slider axis (Y, Z) + btVector3 p = trA.getBasis().getColumn(1); + btVector3 q = trA.getBasis().getColumn(2); + // set the two slider rows + info->m_J1angularAxis[0] = p[0]; + info->m_J1angularAxis[1] = p[1]; + info->m_J1angularAxis[2] = p[2]; + info->m_J1angularAxis[s+0] = q[0]; + info->m_J1angularAxis[s+1] = q[1]; + info->m_J1angularAxis[s+2] = q[2]; + + info->m_J2angularAxis[0] = -p[0]; + info->m_J2angularAxis[1] = -p[1]; + info->m_J2angularAxis[2] = -p[2]; + info->m_J2angularAxis[s+0] = -q[0]; + info->m_J2angularAxis[s+1] = -q[1]; + info->m_J2angularAxis[s+2] = -q[2]; + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the slider back into alignment. + // if ax1,ax2 are the unit length slider axes as computed from body1 and + // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if "theta" is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. + btScalar k = info->fps * info->erp * getSoftnessOrthoAng(); + btVector3 ax2 = trB.getBasis().getColumn(0); + btVector3 u = ax1.cross(ax2); + info->m_constraintError[0] = k * u.dot(p); + info->m_constraintError[s] = k * u.dot(q); + // pull out pos and R for both bodies. also get the connection + // vector c = pos2-pos1. + // next two rows. we want: vel2 = vel1 + w1 x c ... but this would + // result in three equations, so we project along the planespace vectors + // so that sliding along the slider axis is disregarded. for symmetry we + // also consider rotation around center of mass of two bodies (factA and factB). + btTransform bodyA_trans = m_rbA.getCenterOfMassTransform(); + btTransform bodyB_trans = m_rbB.getCenterOfMassTransform(); + int s2 = 2 * s, s3 = 3 * s; + btVector3 c; + btScalar miA = m_rbA.getInvMass(); + btScalar miB = m_rbB.getInvMass(); + btScalar miS = miA + miB; + btScalar factA, factB; + if(miS > btScalar(0.f)) + { + factA = miB / miS; + } + else + { + factA = btScalar(0.5f); + } + if(factA > 0.99f) factA = 0.99f; + if(factA < 0.01f) factA = 0.01f; + factB = btScalar(1.0f) - factA; + c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin(); + btVector3 tmp = c.cross(p); + for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i]; + tmp = c.cross(q); + for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i]; + + for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; + // compute two elements of right hand side. we want to align the offset + // point (in body 2's frame) with the center of body 1. + btVector3 ofs; // offset point in global coordinates + ofs = trB.getOrigin() - trA.getOrigin(); + k = info->fps * info->erp * getSoftnessOrthoLin(); + info->m_constraintError[s2] = k * p.dot(ofs); + info->m_constraintError[s3] = k * q.dot(ofs); + int nrow = 3; // last filled row + int srow; + // check linear limits linear + btScalar limit_err = btScalar(0.0); + int limit = 0; + if(getSolveLinLimit()) + { + limit_err = getLinDepth() * signFact; + limit = (limit_err > btScalar(0.0)) ? 2 : 1; + } + int powered = 0; + if(getPoweredLinMotor()) + { + powered = 1; + } + // if the slider has joint limits or motor, add in the extra row + if (limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1linearAxis[srow+0] = ax1[0]; + info->m_J1linearAxis[srow+1] = ax1[1]; + info->m_J1linearAxis[srow+2] = ax1[2]; + // linear torque decoupling step: + // + // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies + // do not create a torque couple. in other words, the points that the + // constraint force is applied at must lie along the same ax1 axis. + // a torque couple will result in limited slider-jointed free + // bodies from gaining angular momentum. + // the solution used here is to apply the constraint forces at the center of mass of the two bodies + btVector3 ltd; // Linear Torque Decoupling vector (a torque) +// c = btScalar(0.5) * c; + ltd = c.cross(ax1); + info->m_J1angularAxis[srow+0] = factA*ltd[0]; + info->m_J1angularAxis[srow+1] = factA*ltd[1]; + info->m_J1angularAxis[srow+2] = factA*ltd[2]; + info->m_J2angularAxis[srow+0] = factB*ltd[0]; + info->m_J2angularAxis[srow+1] = factB*ltd[1]; + info->m_J2angularAxis[srow+2] = factB*ltd[2]; + // right-hand part + btScalar lostop = getLowerLinLimit(); + btScalar histop = getUpperLinLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + info->m_constraintError[srow] = 0.; + info->m_lowerLimit[srow] = 0.; + info->m_upperLimit[srow] = 0.; + if(powered) + { + info->cfm[nrow] = btScalar(0.0); + btScalar tag_vel = getTargetLinMotorVelocity(); + btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * info->erp); +// info->m_constraintError[srow] += mot_fact * getTargetLinMotorVelocity(); + info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity(); + info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps; + info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps; + } + if(limit) + { + k = info->fps * info->erp; + info->m_constraintError[srow] += k * limit_err; + info->cfm[srow] = btScalar(0.0); // stop_cfm; + if(lostop == histop) + { // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + else + { // high limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that) + btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin()); + if(bounce > btScalar(0.0)) + { + btScalar vel = m_rbA.getLinearVelocity().dot(ax1); + vel -= m_rbB.getLinearVelocity().dot(ax1); + vel *= signFact; + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if (newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } + info->m_constraintError[srow] *= getSoftnessLimLin(); + } // if(limit) + } // if linear limit + // check angular limits + limit_err = btScalar(0.0); + limit = 0; + if(getSolveAngLimit()) + { + limit_err = getAngDepth(); + limit = (limit_err > btScalar(0.0)) ? 1 : 2; + } + // if the slider has joint limits, add in the extra row + powered = 0; + if(getPoweredAngMotor()) + { + powered = 1; + } + if(limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1angularAxis[srow+0] = ax1[0]; + info->m_J1angularAxis[srow+1] = ax1[1]; + info->m_J1angularAxis[srow+2] = ax1[2]; + + info->m_J2angularAxis[srow+0] = -ax1[0]; + info->m_J2angularAxis[srow+1] = -ax1[1]; + info->m_J2angularAxis[srow+2] = -ax1[2]; + + btScalar lostop = getLowerAngLimit(); + btScalar histop = getUpperAngLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + if(powered) + { + info->cfm[srow] = btScalar(0.0); + btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * info->erp); + info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity(); + info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps; + info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps; + } + if(limit) + { + k = info->fps * info->erp; + info->m_constraintError[srow] += k * limit_err; + info->cfm[srow] = btScalar(0.0); // stop_cfm; + if(lostop == histop) + { + // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { // high limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) + btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng()); + if(bounce > btScalar(0.0)) + { + btScalar vel = m_rbA.getAngularVelocity().dot(ax1); + vel -= m_rbB.getAngularVelocity().dot(ax1); + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if(newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } + info->m_constraintError[srow] *= getSoftnessLimAng(); + } // if(limit) + } // if angular limit or powered +} // btSliderConstraint::getInfo2() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) +{ + if (m_useSolveConstraintObsolete) + { + m_timeStep = timeStep; + if(m_useLinearReferenceFrameA) + { + solveConstraintInt(m_rbA,bodyA, m_rbB,bodyB); + } + else + { + solveConstraintInt(m_rbB,bodyB, m_rbA,bodyA); + } } } // btSliderConstraint::solveConstraint() //----------------------------------------------------------------------------- -void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) +void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB) { int i; // linear - btVector3 velA = rbA.getVelocityInLocalPoint(m_relPosA); - btVector3 velB = rbB.getVelocityInLocalPoint(m_relPosB); + btVector3 velA; + bodyA.getVelocityInLocalPointObsolete(m_relPosA,velA); + btVector3 velB; + bodyB.getVelocityInLocalPointObsolete(m_relPosB,velB); btVector3 vel = velA - velB; for(i = 0; i < 3; i++) { @@ -190,8 +543,18 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) // 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); + + //rbA.applyImpulse( impulse_vector, m_relPosA); + //rbB.applyImpulse(-impulse_vector, m_relPosB); + { + btVector3 ftorqueAxis1 = m_relPosA.cross(normal); + btVector3 ftorqueAxis2 = m_relPosB.cross(normal); + bodyA.applyImpulse(normal*rbA.getInvMass(), rbA.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse); + bodyB.applyImpulse(normal*rbB.getInvMass(), rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse); + } + + + if(m_poweredLinMotor && (!i)) { // apply linear motor if(m_accumulatedLinMotorImpulse < m_maxLinMotorForce) @@ -217,8 +580,18 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) m_accumulatedLinMotorImpulse = new_acc; // apply clamped impulse impulse_vector = normal * normalImpulse; - rbA.applyImpulse( impulse_vector, m_relPosA); - rbB.applyImpulse(-impulse_vector, m_relPosB); + //rbA.applyImpulse( impulse_vector, m_relPosA); + //rbB.applyImpulse(-impulse_vector, m_relPosB); + + { + btVector3 ftorqueAxis1 = m_relPosA.cross(normal); + btVector3 ftorqueAxis2 = m_relPosB.cross(normal); + bodyA.applyImpulse(normal*rbA.getInvMass(), rbA.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse); + bodyB.applyImpulse(normal*rbB.getInvMass(), rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse); + } + + + } } } @@ -227,8 +600,10 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) 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 angVelA; + bodyA.getAngularVelocity(angVelA); + btVector3 angVelB; + bodyB.getAngularVelocity(angVelB); btVector3 angVelAroundAxisA = axisA * axisA.dot(angVelA); btVector3 angVelAroundAxisB = axisB * axisB.dot(angVelB); @@ -238,24 +613,38 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) btVector3 velrelOrthog = angAorthog-angBorthog; //solve orthogonal angular velocity correction btScalar len = velrelOrthog.length(); + btScalar orthorImpulseMag = 0.f; + 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; + //velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng; + orthorImpulseMag = (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng; } //solve angular positional correction btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/m_timeStep); + btVector3 angularAxis = angularError; + btScalar angularImpulseMag = 0; + 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; + angularImpulseMag = (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng; + angularError *= angularImpulseMag; } // apply impulse - rbA.applyTorqueImpulse(-velrelOrthog+angularError); - rbB.applyTorqueImpulse(velrelOrthog-angularError); + //rbA.applyTorqueImpulse(-velrelOrthog+angularError); + //rbB.applyTorqueImpulse(velrelOrthog-angularError); + + bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*velrelOrthog,-orthorImpulseMag); + bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*velrelOrthog,orthorImpulseMag); + bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*angularAxis,angularImpulseMag); + bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*angularAxis,-angularImpulseMag); + + btScalar impulseMag; //solve angular limits if(m_solveAngLim) @@ -269,8 +658,14 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) impulseMag *= m_kAngle * m_softnessDirAng; } btVector3 impulse = axisA * impulseMag; - rbA.applyTorqueImpulse(impulse); - rbB.applyTorqueImpulse(-impulse); + //rbA.applyTorqueImpulse(impulse); + //rbB.applyTorqueImpulse(-impulse); + + bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*axisA,impulseMag); + bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*axisA,-impulseMag); + + + //apply angular motor if(m_poweredAngMotor) { @@ -301,8 +696,11 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) m_accumulatedAngMotorImpulse = new_acc; // apply clamped impulse btVector3 motorImp = angImpulse * axisA; - m_rbA.applyTorqueImpulse(motorImp); - m_rbB.applyTorqueImpulse(-motorImp); + //rbA.applyTorqueImpulse(motorImp); + //rbB.applyTorqueImpulse(-motorImp); + + bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*axisA,angImpulse); + bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*axisA,-angImpulse); } } } // btSliderConstraint::solveConstraint() @@ -312,7 +710,7 @@ void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) //----------------------------------------------------------------------------- void btSliderConstraint::calculateTransforms(void){ - if(m_useLinearReferenceFrameA) + if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete)) { m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; @@ -325,7 +723,14 @@ void btSliderConstraint::calculateTransforms(void){ 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; + if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete) + { + m_delta = m_realPivotBInW - m_realPivotAInW; + } + else + { + m_delta = m_realPivotAInW - m_realPivotBInW; + } m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; btVector3 normalWorld; int i; @@ -367,7 +772,6 @@ void btSliderConstraint::testLinLimits(void) } // btSliderConstraint::testLinLimits() //----------------------------------------------------------------------------- - void btSliderConstraint::testAngLimits(void) { @@ -379,6 +783,7 @@ void btSliderConstraint::testAngLimits(void) 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)); + m_angPos = rot; if(rot < m_lowerAngLimit) { m_angDepth = rot - m_lowerAngLimit; @@ -391,12 +796,9 @@ void btSliderConstraint::testAngLimits(void) } } } // btSliderConstraint::testAngLimits() - //----------------------------------------------------------------------------- - - btVector3 btSliderConstraint::getAncorInA(void) { btVector3 ancorInA; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h index 580dfa1178d..70fbce5d9b2 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -46,6 +46,8 @@ class btRigidBody; class btSliderConstraint : public btTypedConstraint { protected: + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; btTransform m_frameInA; btTransform m_frameInB; // use frameA fo define limits, if true @@ -104,6 +106,7 @@ protected: btVector3 m_relPosB; btScalar m_linPos; + btScalar m_angPos; btScalar m_angDepth; btScalar m_kAngle; @@ -126,7 +129,13 @@ public: btSliderConstraint(); // overrides virtual void buildJacobian(); - virtual void solveConstraint(btScalar timeStep); + virtual void getInfo1 (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); + + // access const btRigidBody& getRigidBodyA() const { return m_rbA; } const btRigidBody& getRigidBodyB() const { return m_rbB; } @@ -194,6 +203,7 @@ public: 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; } @@ -202,10 +212,11 @@ public: btScalar getAngDepth() { return m_angDepth; } // internal void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB); - void solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB); + void solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB); // shared code used by ODE solver void calculateTransforms(void); void testLinLimits(void); + void testLinLimits2(btConstraintInfo2* info); void testAngLimits(void); // access for PE Solver btVector3 getAncorInA(void); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h index b3f0c9d7444..98c9876ae46 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -23,86 +23,152 @@ class btRigidBody; #include "LinearMath/btAlignedAllocator.h" #include "LinearMath/btTransformUtil.h" +///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision +#ifdef BT_USE_SSE +#define USE_SIMD 1 +#endif // -///btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. + +#ifdef USE_SIMD + +struct btSimdScalar +{ + SIMD_FORCE_INLINE btSimdScalar() + { + + } + + SIMD_FORCE_INLINE btSimdScalar(float fl) + :m_vec128 (_mm_set1_ps(fl)) + { + } + + SIMD_FORCE_INLINE btSimdScalar(__m128 v128) + :m_vec128(v128) + { + } + union + { + __m128 m_vec128; + float m_floats[4]; + int m_ints[4]; + btScalar m_unusedPadding; + }; + SIMD_FORCE_INLINE __m128 get128() + { + return m_vec128; + } + + SIMD_FORCE_INLINE const __m128 get128() const + { + return m_vec128; + } + + SIMD_FORCE_INLINE void set128(__m128 v128) + { + m_vec128 = v128; + } + + SIMD_FORCE_INLINE operator __m128() + { + return m_vec128; + } + SIMD_FORCE_INLINE operator const __m128() const + { + return m_vec128; + } + + SIMD_FORCE_INLINE operator float() const + { + return m_floats[0]; + } + +}; + +///@brief Return the elementwise product of two btSimdScalar +SIMD_FORCE_INLINE btSimdScalar +operator*(const btSimdScalar& v1, const btSimdScalar& v2) +{ + return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128())); +} + +///@brief Return the elementwise product of two btSimdScalar +SIMD_FORCE_INLINE btSimdScalar +operator+(const btSimdScalar& v1, const btSimdScalar& v2) +{ + return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128())); +} + + +#else +#define btSimdScalar btScalar +#endif + +///The 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_angularVelocity; - float m_angularFactor; - float m_invMass; - float m_friction; + btVector3 m_deltaLinearVelocity; + btVector3 m_deltaAngularVelocity; + btScalar m_angularFactor; + btScalar m_invMass; + btScalar m_friction; btRigidBody* m_originalBody; - btVector3 m_linearVelocity; - btVector3 m_centerOfMassPosition; - btVector3 m_pushVelocity; - btVector3 m_turnVelocity; + //btVector3 m_turnVelocity; + - - SIMD_FORCE_INLINE void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const + SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const { - velocity = m_linearVelocity + m_angularVelocity.cross(rel_pos); + if (m_originalBody) + velocity = m_originalBody->getLinearVelocity()+m_deltaLinearVelocity + (m_originalBody->getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos); + else + velocity.setValue(0,0,0); } + SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const + { + if (m_originalBody) + angVel = m_originalBody->getAngularVelocity()+m_deltaAngularVelocity; + else + angVel.setValue(0,0,0); + } + + //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) + SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude) { - if (m_invMass) + //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_deltaLinearVelocity += linearComponent*impulseMagnitude; + m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); } } +/* + void writebackVelocity() { if (m_invMass) { - m_originalBody->setLinearVelocity(m_linearVelocity); - m_originalBody->setAngularVelocity(m_angularVelocity); + m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity); + m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity); //m_originalBody->setCompanionId(-1); } } - + */ - void writebackVelocity(btScalar timeStep) + void writebackVelocity(btScalar timeStep=0) { 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->setLinearVelocity(m_originalBody->getLinearVelocity()+m_deltaLinearVelocity); + m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity); //m_originalBody->setCompanionId(-1); } } - - void readVelocity() - { - if (m_invMass) - { - m_linearVelocity = m_originalBody->getLinearVelocity(); - m_angularVelocity = m_originalBody->getAngularVelocity(); - } - } - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h index 2c71360c5b9..867d62a301d 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -19,40 +19,64 @@ subject to the following restrictions: class btRigidBody; #include "LinearMath/btVector3.h" #include "LinearMath/btMatrix3x3.h" +#include "btJacobianEntry.h" //#define NO_FRICTION_TANGENTIALS 1 +#include "btSolverBody.h" + ///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_relpos1CrossNormal; + btVector3 m_contactNormal; - btVector3 m_relpos2CrossNormal; - btVector3 m_angularComponentA; + btVector3 m_relpos2CrossNormal; + //btVector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal - btVector3 m_angularComponentB; - - mutable btScalar m_appliedPushImpulse; + btVector3 m_angularComponentA; + btVector3 m_angularComponentB; + + mutable btSimdScalar m_appliedPushImpulse; + mutable btSimdScalar m_appliedImpulse; - mutable btScalar m_appliedImpulse; - int m_solverBodyIdA; - int m_solverBodyIdB; btScalar m_friction; - btScalar m_restitution; btScalar m_jacDiagABInv; - btScalar m_penetration; - + union + { + int m_numConsecutiveRowsPerKernel; + btScalar m_unusedPadding0; + }; + union + { + int m_frictionIndex; + btScalar m_unusedPadding1; + }; + union + { + int m_solverBodyIdA; + btScalar m_unusedPadding2; + }; + union + { + int m_solverBodyIdB; + btScalar m_unusedPadding3; + }; - int m_constraintType; - int m_frictionIndex; - void* m_originalContactPoint; - int m_unusedPadding[1]; + union + { + void* m_originalContactPoint; + btScalar m_unusedPadding4; + }; + btScalar m_rhs; + btScalar m_cfm; + btScalar m_lowerLimit; + btScalar m_upperLimit; enum btSolverConstraintType { @@ -61,9 +85,7 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint }; }; - - - +typedef btAlignedObjectArray btConstraintArray; #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..3fa98ee4c88 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -19,13 +19,16 @@ subject to the following restrictions: static btRigidBody s_fixed(0, 0,0); +#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.3f) + 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.)) +m_appliedImpulse(btScalar(0.)), +m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE) { s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); } @@ -35,7 +38,8 @@ m_userConstraintId(-1), m_constraintType (type), m_rbA(rbA), m_rbB(s_fixed), -m_appliedImpulse(btScalar(0.)) +m_appliedImpulse(btScalar(0.)), +m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE) { s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); @@ -48,9 +52,63 @@ m_userConstraintId(-1), m_constraintType (type), m_rbA(rbA), m_rbB(rbB), -m_appliedImpulse(btScalar(0.)) +m_appliedImpulse(btScalar(0.)), +m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE) { s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); } + +//----------------------------------------------------------------------------- + +btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact) +{ + if(lowLim > uppLim) + { + return btScalar(1.0f); + } + else if(lowLim == uppLim) + { + return btScalar(0.0f); + } + btScalar lim_fact = btScalar(1.0f); + btScalar delta_max = vel / timeFact; + if(delta_max < btScalar(0.0f)) + { + if((pos >= lowLim) && (pos < (lowLim - delta_max))) + { + lim_fact = (lowLim - pos) / delta_max; + } + else if(pos < lowLim) + { + lim_fact = btScalar(0.0f); + } + else + { + lim_fact = btScalar(1.0f); + } + } + else if(delta_max > btScalar(0.0f)) + { + if((pos <= uppLim) && (pos > (uppLim - delta_max))) + { + lim_fact = (uppLim - pos) / delta_max; + } + else if(pos > uppLim) + { + lim_fact = btScalar(0.0f); + } + else + { + lim_fact = btScalar(1.0f); + } + } + else + { + lim_fact = btScalar(0.0f); + } + return lim_fact; +} // btTypedConstraint::getMotorFactor() + + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index c50ec6ec579..78a770231b3 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -18,6 +18,11 @@ subject to the following restrictions: class btRigidBody; #include "LinearMath/btScalar.h" +#include "btSolverConstraint.h" +struct btSolverBody; + + + enum btTypedConstraintType { @@ -48,6 +53,7 @@ protected: btRigidBody& m_rbA; btRigidBody& m_rbB; btScalar m_appliedImpulse; + btScalar m_dbgDrawSize; public: @@ -55,13 +61,55 @@ public: btTypedConstraint(btTypedConstraintType type); virtual ~btTypedConstraint() {}; btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); - btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); + struct btConstraintInfo1 { + int m_numConstraintRows,nub; + }; + + struct btConstraintInfo2 { + // integrator parameters: frames per second (1/stepsize), default error + // reduction parameter (0..1). + btScalar fps,erp; + + // for the first and second body, pointers to two (linear and angular) + // n*3 jacobian sub matrices, stored by rows. these matrices will have + // been initialized to 0 on entry. if the second body is zero then the + // J2xx pointers may be 0. + btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis; + + // elements to jump from one row to the next in J's + int rowskip; + + // right hand sides of the equation J*v = c + cfm * lambda. cfm is the + // "constraint force mixing" vector. c is set to zero on entry, cfm is + // set to a constant value (typically very small or zero) value on entry. + btScalar *m_constraintError,*cfm; + + // lo and hi limits for variables (set to -/+ infinity on entry). + btScalar *m_lowerLimit,*m_upperLimit; + + // findex vector for variables. see the LCP solver interface for a + // description of what this does. this is set to -1 on entry. + // note that the returned indexes are relative to the first index of + // the constraint. + int *findex; + }; + + virtual void buildJacobian() = 0; - virtual void solveConstraint(btScalar timeStep) = 0; + virtual void setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep) + { + } + virtual void getInfo1 (btConstraintInfo1* info)=0; + virtual void getInfo2 (btConstraintInfo2* info)=0; + + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) = 0; + + btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact); + const btRigidBody& getRigidBodyA() const { return m_rbA; @@ -94,7 +142,7 @@ public: { m_userConstraintId = uid; } - + int getUserConstraintId() const { return m_userConstraintId; @@ -114,7 +162,16 @@ public: { return m_constraintType; } - + + void setDbgDrawSize(btScalar dbgDrawSize) + { + m_dbgDrawSize = dbgDrawSize; + } + btScalar getDbgDrawSize() + { + return m_dbgDrawSize; + } + }; #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..47addbac45b 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -38,7 +38,7 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" #include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" @@ -110,16 +110,16 @@ void plDeleteDynamicsWorld(plDynamicsWorldHandle world) void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep) { btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); - assert(dynamicsWorld); + btAssert(dynamicsWorld); dynamicsWorld->stepSimulation(timeStep); } void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) { btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); - assert(dynamicsWorld); + btAssert(dynamicsWorld); btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - assert(body); + btAssert(body); dynamicsWorld->addRigidBody(body); } @@ -127,9 +127,9 @@ void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) { btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); - assert(dynamicsWorld); + btAssert(dynamicsWorld); btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - assert(body); + btAssert(body); dynamicsWorld->removeRigidBody(body); } @@ -142,7 +142,7 @@ plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionSh trans.setIdentity(); btVector3 localInertia(0,0,0); btCollisionShape* shape = reinterpret_cast( cshape); - assert(shape); + btAssert(shape); if (mass) { shape->calculateLocalInertia(mass,localInertia); @@ -158,7 +158,7 @@ plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionSh void plDeleteRigidBody(plRigidBodyHandle cbody) { btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); - assert(body); + btAssert(body); btAlignedFree( body); } @@ -255,20 +255,20 @@ void plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z) (void)colShape; btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE); btConvexHullShape* convexHullShape = reinterpret_cast( cshape); - convexHullShape->addPoint(btPoint3(x,y,z)); + convexHullShape->addPoint(btVector3(x,y,z)); } void plDeleteShape(plCollisionShapeHandle cshape) { btCollisionShape* shape = reinterpret_cast( cshape); - assert(shape); + btAssert(shape); btAlignedFree(shape); } void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling) { btCollisionShape* shape = reinterpret_cast( cshape); - assert(shape); + btAssert(shape); btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); shape->setLocalScaling(scaling); } diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index 745694e2f70..ba48f404929 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -29,6 +29,11 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" //for debug rendering #include "BulletCollision/CollisionShapes/btBoxShape.h" @@ -51,6 +56,9 @@ subject to the following restrictions: #include "BulletDynamics/Vehicle/btRaycastVehicle.h" #include "BulletDynamics/Vehicle/btVehicleRaycaster.h" #include "BulletDynamics/Vehicle/btWheelInfo.h" +//character +#include "BulletDynamics/Character/btCharacterControllerInterface.h" + #include "LinearMath/btIDebugDraw.h" #include "LinearMath/btQuickprof.h" #include "LinearMath/btMotionState.h" @@ -110,7 +118,6 @@ void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) btRigidBody* body = btRigidBody::upcast(colObj); if (body) { - btTransform predictedTrans; if (body->getActivationState() != ISLAND_SLEEPING) { if (body->isKinematicObject()) @@ -125,6 +132,7 @@ void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) void btDiscreteDynamicsWorld::debugDrawWorld() { + BT_PROFILE("debugDrawWorld"); if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints) { @@ -144,13 +152,30 @@ void btDiscreteDynamicsWorld::debugDrawWorld() } } } + bool drawConstraints = false; + if (getDebugDrawer()) + { + int mode = getDebugDrawer()->getDebugMode(); + if(mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits)) + { + drawConstraints = true; + } + } + if(drawConstraints) + { + for(int i = getNumConstraints()-1; i>=0 ;i--) + { + btTypedConstraint* constraint = getConstraint(i); + debugDrawConstraint(constraint); + } + } + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)) { int i; - //todo: iterate over awake simulation islands! for ( i=0;igetDebugMode() & btIDebugDraw::DBG_DrawAabb)) { - btPoint3 minAabb,maxAabb; + btVector3 minAabb,maxAabb; btVector3 colorvec(1,0,0); colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); @@ -220,7 +245,7 @@ void btDiscreteDynamicsWorld::debugDrawWorld() void btDiscreteDynamicsWorld::clearForces() { - //todo: iterate over awake simulation islands! + ///@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 + ///@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); + } + } +} + void btDiscreteDynamicsWorld::synchronizeMotionStates() { + BT_PROFILE("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 (body) + synchronizeSingleMotionState(body); } } @@ -327,7 +361,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, //process some debugging flags if (getDebugDrawer()) { - gDisableDeactivation = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; + btIDebugDraw* debugDrawer = getDebugDrawer (); + gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; } if (numSimulationSubSteps) { @@ -392,7 +427,8 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) ///update vehicle simulation updateVehicles(timeStep); - + + updateCharacters(timeStep); updateActivationState( timeStep ); @@ -423,13 +459,6 @@ btVector3 btDiscreteDynamicsWorld::getGravity () const void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) { - //remove all constraints too - while (body->getNumConstraintRefs()) - { - btTypedConstraint* constraint = body->getConstraintRef(0); - removeConstraint(constraint); - } - removeCollisionObject(body); } @@ -475,6 +504,20 @@ void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) } } +void btDiscreteDynamicsWorld::updateCharacters(btScalar timeStep) +{ + BT_PROFILE("updateCharacters"); + + for ( int i=0;ipreStep (this); + character->playerStep (this,timeStep); + } +} + + + void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) { BT_PROFILE("updateActivationState"); @@ -539,6 +582,17 @@ void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) m_vehicles.remove(vehicle); } +void btDiscreteDynamicsWorld::addCharacter(btCharacterControllerInterface* character) +{ + m_characters.push_back(character); +} + +void btDiscreteDynamicsWorld::removeCharacter(btCharacterControllerInterface* character) +{ + m_characters.remove(character); +} + + SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) { int islandId; @@ -611,8 +665,11 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) { if (islandId<0) { - ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id - m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + if (numManifolds + m_numConstraints) + { + ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id + m_solver->solveGroup( 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 @@ -658,7 +715,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) sortedConstraints[i] = m_constraints[i]; } -// assert(0); +// btAssert(0); @@ -671,7 +728,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); /// solve all the constraints for this island - m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback); + m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),&solverCallback); m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc); } @@ -722,21 +779,27 @@ class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConve btCollisionObject* m_me; btScalar m_allowedPenetration; btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; public: - btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache) : + btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : btCollisionWorld::ClosestConvexResultCallback(fromA,toA), m_allowedPenetration(0.0f), m_me(me), - m_pairCache(pairCache) + m_pairCache(pairCache), + m_dispatcher(dispatcher) { } virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) { if (convexResult.m_hitCollisionObject == m_me) - return 1.0; + return 1.0f; + + //ignore result if there is no contact response + if(!convexResult.m_hitCollisionObject->hasContactResponse()) + return 1.0f; btVector3 linVelA,linVelB; linVelA = m_convexToWorld-m_convexFromWorld; @@ -757,23 +820,29 @@ public: return false; ///don't do CCD when the collision filters are not matching - if (!btCollisionWorld::ClosestConvexResultCallback::needsCollision(proxy0)) + if (!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* otherObj = (btCollisionObject*) proxy0->m_clientObject; + + //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179 + if (m_dispatcher->needsResponse(m_me,otherObj)) { - if (collisionPair->m_algorithm) + ///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) { - manifoldArray.resize(0); - collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); - for (int j=0;jm_algorithm) { - btPersistentManifold* manifold = manifoldArray[j]; - if (manifold->getNumContacts()>0) - return false; + manifoldArray.resize(0); + collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); + for (int j=0;jgetNumContacts()>0) + return false; + } } } } @@ -811,9 +880,13 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) { gNumClampedCcdMotions++; - btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache()); + btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); btConvexShape* convexShape = static_cast(body->getCollisionShape()); btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); + + sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup; + sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask; + convexSweepTest(&tmpSphere,body->getWorldTransform(),predictedTrans,sweepResults); if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) { @@ -833,6 +906,8 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) + + void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { BT_PROFILE("predictUnconstraintMotion"); @@ -844,14 +919,12 @@ void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { if (!body->isStaticOrKinematicObject()) { - if (body->isActive()) - { - body->integrateVelocities( timeStep); - //damping - body->applyDamping(timeStep); + + body->integrateVelocities( timeStep); + //damping + body->applyDamping(timeStep); - body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); - } + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } } @@ -1103,7 +1176,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, { btConcaveShape* concaveMesh = (btConcaveShape*) shape; - //todo pass camera, for some culling + ///@todo pass camera, for some culling? no -> we are not a graphics lib btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); @@ -1132,7 +1205,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, int i; for (i=0;igetNumEdges();i++) { - btPoint3 a,b; + btVector3 a,b; polyshape->getEdge(i,a,b); btVector3 wa = worldTransform * a; btVector3 wb = worldTransform * b; @@ -1148,6 +1221,189 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, } +void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint) +{ + bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0; + bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0; + btScalar dbgDrawSize = constraint->getDbgDrawSize(); + if(dbgDrawSize <= btScalar(0.f)) + { + return; + } + + switch(constraint->getConstraintType()) + { + case POINT2POINT_CONSTRAINT_TYPE: + { + btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint; + btTransform tr; + tr.setIdentity(); + btVector3 pivot = p2pC->getPivotInA(); + pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot; + tr.setOrigin(pivot); + getDebugDrawer()->drawTransform(tr, dbgDrawSize); + // that ideally should draw the same frame + pivot = p2pC->getPivotInB(); + pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot; + tr.setOrigin(pivot); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + } + break; + case HINGE_CONSTRAINT_TYPE: + { + btHingeConstraint* pHinge = (btHingeConstraint*)constraint; + btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + btScalar minAng = pHinge->getLowerLimit(); + btScalar maxAng = pHinge->getUpperLimit(); + if(minAng == maxAng) + { + break; + } + bool drawSect = true; + if(minAng > maxAng) + { + minAng = btScalar(0.f); + maxAng = SIMD_2_PI; + drawSect = false; + } + if(drawLimits) + { + btVector3& center = tr.getOrigin(); + btVector3 normal = tr.getBasis().getColumn(2); + btVector3 axis = tr.getBasis().getColumn(0); + getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect); + } + } + break; + case CONETWIST_CONSTRAINT_TYPE: + { + btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint; + btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + //const btScalar length = btScalar(5); + const btScalar length = dbgDrawSize; + static int nSegments = 8*4; + btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments); + btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length); + pPrev = tr * pPrev; + for (int i=0; iGetPointForAngle(fAngleInRadians, length); + pCur = tr * pCur; + getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0)); + + if (i%(nSegments/8) == 0) + getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0)); + + pPrev = pCur; + } + btScalar tws = pCT->getTwistSpan(); + btScalar twa = pCT->getTwistAngle(); + bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f)); + if(useFrameB) + { + tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame(); + } + else + { + tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame(); + } + btVector3 pivot = tr.getOrigin(); + btVector3 normal = tr.getBasis().getColumn(0); + btVector3 axis1 = tr.getBasis().getColumn(1); + getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true); + + } + } + break; + case D6_CONSTRAINT_TYPE: + { + btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint; + btTransform tr = p6DOF->getCalculatedTransformA(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = p6DOF->getCalculatedTransformB(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + tr = p6DOF->getCalculatedTransformA(); + const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin(); + btVector3 up = tr.getBasis().getColumn(2); + btVector3 axis = tr.getBasis().getColumn(0); + btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit; + btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit; + btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit; + btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit; + getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0)); + axis = tr.getBasis().getColumn(1); + btScalar ay = p6DOF->getAngle(1); + btScalar az = p6DOF->getAngle(2); + btScalar cy = btCos(ay); + btScalar sy = btSin(ay); + btScalar cz = btCos(az); + btScalar sz = btSin(az); + btVector3 ref; + ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2]; + ref[1] = -sz*axis[0] + cz*axis[1]; + ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2]; + tr = p6DOF->getCalculatedTransformB(); + btVector3 normal = -tr.getBasis().getColumn(0); + btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit; + btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit; + if(minFi > maxFi) + { + getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false); + } + else if(minFi < maxFi) + { + getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true); + } + tr = p6DOF->getCalculatedTransformA(); + btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit; + btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit; + getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0)); + } + } + break; + case SLIDER_CONSTRAINT_TYPE: + { + btSliderConstraint* pSlider = (btSliderConstraint*)constraint; + btTransform tr = pSlider->getCalculatedTransformA(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pSlider->getCalculatedTransformB(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + btTransform tr = pSlider->getCalculatedTransformA(); + btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f); + btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f); + getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0)); + btVector3 normal = tr.getBasis().getColumn(0); + btVector3 axis = tr.getBasis().getColumn(1); + btScalar a_min = pSlider->getLowerAngLimit(); + btScalar a_max = pSlider->getUpperAngLimit(); + const btVector3& center = pSlider->getCalculatedTransformB().getOrigin(); + getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true); + } + } + break; + default : + break; + } + return; +} // btDiscreteDynamicsWorld::debugDrawConstraint() + + + + + void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) @@ -1176,3 +1432,5 @@ const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const { return m_constraints[index]; } + + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index d9e2652aaf6..34d4e6b353f 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -26,6 +26,7 @@ class btTypedConstraint; class btRaycastVehicle; +class btCharacterControllerInterface; class btIDebugDraw; #include "LinearMath/btAlignedObjectArray.h" @@ -42,7 +43,6 @@ protected: btAlignedObjectArray m_constraints; - btVector3 m_gravity; //for variable timesteps @@ -54,6 +54,9 @@ protected: btAlignedObjectArray m_vehicles; + + btAlignedObjectArray m_characters; + int m_profileTimings; @@ -61,24 +64,26 @@ protected: virtual void integrateTransforms(btScalar timeStep); - void calculateSimulationIslands(); + virtual void calculateSimulationIslands(); - void solveConstraints(btContactSolverInfo& solverInfo); + virtual void solveConstraints(btContactSolverInfo& solverInfo); void updateActivationState(btScalar timeStep); void updateVehicles(btScalar timeStep); + void updateCharacters(btScalar timeStep); + void startProfiling(btScalar timeStep); virtual void internalSingleStepSimulation( btScalar timeStep); - void synchronizeMotionStates(); - void saveKinematicState(btScalar timeStep); + virtual void saveKinematicState(btScalar timeStep); void debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color); + public: @@ -91,13 +96,23 @@ public: virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); - void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); + virtual void synchronizeMotionStates(); - void removeConstraint(btTypedConstraint* constraint); + ///this can be useful to synchronize a single rigid body -> graphics object + void synchronizeSingleMotionState(btRigidBody* body); - void addVehicle(btRaycastVehicle* vehicle); + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); - void removeVehicle(btRaycastVehicle* vehicle); + virtual void removeConstraint(btTypedConstraint* constraint); + + virtual void addVehicle(btRaycastVehicle* vehicle); + + virtual void removeVehicle(btRaycastVehicle* vehicle); + + virtual void addCharacter(btCharacterControllerInterface* character); + + virtual void removeCharacter(btCharacterControllerInterface* character); + btSimulationIslandManager* getSimulationIslandManager() { @@ -114,7 +129,6 @@ public: return this; } - virtual void setGravity(const btVector3& gravity); virtual btVector3 getGravity () const; @@ -126,6 +140,8 @@ public: void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); + void debugDrawConstraint(btTypedConstraint* constraint); + virtual void debugDrawWorld(); virtual void setConstraintSolver(btConstraintSolver* solver); @@ -152,6 +168,7 @@ public: virtual void setNumTasks(int numTasks) { + (void) numTasks; } }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 929e24d337c..2d90e212f7a 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -23,6 +23,7 @@ class btTypedConstraint; class btRaycastVehicle; class btConstraintSolver; class btDynamicsWorld; +class btCharacterControllerInterface; /// Type for the callback for each tick typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep); @@ -75,11 +76,18 @@ public: virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} + virtual void addCharacter(btCharacterControllerInterface* character) {(void)character;} + + virtual void removeCharacter(btCharacterControllerInterface* character) {(void)character;} + + //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 synchronizeMotionStates() = 0; + virtual void addRigidBody(btRigidBody* body) = 0; virtual void removeRigidBody(btRigidBody* body) = 0; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp index 93d70de39d8..a2b8a7dade4 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -45,8 +45,8 @@ void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& 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_anisotropicFriction.setValue(1.f,1.f,1.f); m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_gravity_acceleration.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.); @@ -125,6 +125,7 @@ void btRigidBody::setGravity(const btVector3& acceleration) { m_gravity = acceleration * (btScalar(1.0) / m_inverseMass); } + m_gravity_acceleration = acceleration; } @@ -144,8 +145,17 @@ 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) { + //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74 + //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway + +//#define USE_OLD_DAMPING_METHOD 1 +#ifdef USE_OLD_DAMPING_METHOD 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)); +#else + m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep); + m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep); +#endif if (m_additionalDamping) { diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h index 4596f90a00f..ec570cab875 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h @@ -17,7 +17,6 @@ subject to the following restrictions: #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" @@ -31,7 +30,7 @@ extern btScalar gDeactivationTime; extern bool gDisableDeactivation; -///btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape. +///The 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. @@ -49,6 +48,7 @@ class btRigidBody : public btCollisionObject btScalar m_angularFactor; btVector3 m_gravity; + btVector3 m_gravity_acceleration; btVector3 m_invInertiaLocal; btVector3 m_totalForce; btVector3 m_totalTorque; @@ -75,7 +75,7 @@ class btRigidBody : public btCollisionObject public: - ///btRigidBodyConstructionInfo provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body. + ///The btRigidBodyConstructionInfo structure 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, @@ -182,7 +182,7 @@ public: const btVector3& getGravity() const { - return m_gravity; + return m_gravity_acceleration; } void setDamping(btScalar lin_damping, btScalar ang_damping); @@ -232,8 +232,18 @@ public: { m_totalForce += force; } + + const btVector3& getTotalForce() + { + return m_totalForce; + }; + + const btVector3& getTotalTorque() + { + return m_totalTorque; + }; - const btVector3& getInvInertiaDiagLocal() + const btVector3& getInvInertiaDiagLocal() const { return m_invInertiaLocal; }; @@ -303,7 +313,7 @@ public: void updateInertiaTensor(); - const btPoint3& getCenterOfMassPosition() const { + const btVector3& getCenterOfMassPosition() const { return m_worldTransform.getOrigin(); } btQuaternion getOrientation() const; @@ -321,15 +331,12 @@ public: inline void setLinearVelocity(const btVector3& lin_vel) { - assert (m_collisionFlags != btCollisionObject::CF_STATIC_OBJECT); m_linearVelocity = lin_vel; } - inline void setAngularVelocity(const btVector3& ang_vel) { - assert (m_collisionFlags != btCollisionObject::CF_STATIC_OBJECT); - { - m_angularVelocity = ang_vel; - } + inline void setAngularVelocity(const btVector3& ang_vel) + { + m_angularVelocity = ang_vel; } btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const @@ -353,7 +360,7 @@ public: - SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const + SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const { btVector3 r0 = pos - getCenterOfMassPosition(); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp index 3be04d1a4ad..3f6141463c3 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -97,7 +97,7 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b void btSimpleDynamicsWorld::clearForces() { - //todo: iterate over awake simulation islands! + ///@todo: iterate over awake simulation islands! for ( int i=0;iisActive() && (!body->isStaticObject())) { - btPoint3 minAabb,maxAabb; + btVector3 minAabb,maxAabb; colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); btBroadphaseInterface* bp = getBroadphase(); bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); @@ -210,7 +210,7 @@ void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) void btSimpleDynamicsWorld::synchronizeMotionStates() { - //todo: iterate over awake simulation islands! + ///@todo: iterate over awake simulation islands! for ( int i=0;icastRay(source,target,rayResults); @@ -188,7 +188,7 @@ btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel) wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; wheel.m_raycastInfo.m_isInContact = true; - wheel.m_raycastInfo.m_groundObject = &s_fixedObject;//todo for driving on dynamic/movable objects!; + wheel.m_raycastInfo.m_groundObject = &s_fixedObject;///@todo for driving on dynamic/movable objects!; //wheel.m_raycastInfo.m_groundObject = object; @@ -359,7 +359,7 @@ void btRaycastVehicle::updateVehicle( btScalar step ) void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel) { - assert(wheel>=0 && wheel < getNumWheels()); + btAssert(wheel>=0 && wheel < getNumWheels()); btWheelInfo& wheelInfo = getWheelInfo(wheel); wheelInfo.m_steering = steering; @@ -375,7 +375,7 @@ btScalar btRaycastVehicle::getSteeringValue(int wheel) const void btRaycastVehicle::applyEngineForce(btScalar force, int wheel) { - assert(wheel>=0 && wheel < getNumWheels()); + btAssert(wheel>=0 && wheel < getNumWheels()); btWheelInfo& wheelInfo = getWheelInfo(wheel); wheelInfo.m_engineForce = force; } @@ -691,7 +691,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; - rel_pos[2] *= wheelInfo.m_rollInfluence; + rel_pos[m_indexForwardAxis] *= wheelInfo.m_rollInfluence; m_chassisBody->applyImpulse(sideImp,rel_pos); //apply friction impulse on the ground diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h index 8361dcabe4b..bfe0d7df2fb 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -180,7 +180,18 @@ public: //not yet } - virtual void solveConstraint(btScalar timeStep) + virtual void getInfo1 (btConstraintInfo1* info) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + + virtual void getInfo2 (btConstraintInfo2* info) + { + btAssert(0); + } + + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) { (void)timeStep; //not yet diff --git a/extern/bullet2/src/BulletSoftBody/CMakeLists.txt b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt index a725e10ff77..dbd87afea38 100644 --- a/extern/bullet2/src/BulletSoftBody/CMakeLists.txt +++ b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt @@ -3,19 +3,41 @@ INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src } ) -ADD_LIBRARY(LibBulletSoftBody +SET(BulletSoftBody_SRCS 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 ) + +SET(BulletSoftBody_HDRS + btSoftBody.h + btSparseSDF.h + btSoftBodyHelpers.h + btSoftRigidCollisionAlgorithm.h + btSoftSoftCollisionAlgorithm.h + btSoftBodyConcaveCollisionAlgorithm.h + btSoftRigidDynamicsWorld.h +) + + + +ADD_LIBRARY(BulletSoftBody ${BulletSoftBody_SRCS} ${BulletSoftBody_HDRS}) +SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBody BulletDynamics) +ENDIF (BUILD_SHARED_LIBS) + +IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + INSTALL(TARGETS BulletSoftBody DESTINATION lib) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.h") +ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + +IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES PUBLIC_HEADER "${BulletSoftBody_HDRS}") +ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp index 1ec668c9c78..ee810c54082 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp @@ -150,98 +150,98 @@ bool btSoftBody::checkFace(int node0,int node1,int node2) const // btSoftBody::Material* btSoftBody::appendMaterial() { -Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material(); -if(m_materials.size()>0) - *pm=*m_materials[0]; + Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material(); + if(m_materials.size()>0) + *pm=*m_materials[0]; else - ZeroInitialize(*pm); -m_materials.push_back(pm); -return(pm); + 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) + 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); + 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) + const btVector3& o, + Node* feature) { -appendNote(text,o,btVector4(1,0,0,0),feature); + appendNote(text,o,btVector4(1,0,0,0),feature); } // void btSoftBody::appendNote( const char* text, - const btVector3& o, - Link* feature) + 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]); + 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) + 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]); + 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()) + if(m_nodes.capacity()==m_nodes.size()) { - pointersToIndices(); - m_nodes.reserve(m_nodes.size()*2+1); - indicesToPointers(); + 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); + 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]; + 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); + m_links.push_back(l); } // @@ -273,12 +273,12 @@ void btSoftBody::appendLink( Node* node0, // void btSoftBody::appendFace(int model,Material* mat) { -Face f; -if(model>=0) + 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); + m_faces.push_back(f); } // @@ -306,9 +306,9 @@ void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat) } // -void btSoftBody::appendAnchor(int node,btRigidBody* body,bool disableCollisionWithBody=false) +void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies) { - if (disableCollisionWithBody) + if (disableCollisionBetweenLinkedBodies) { if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size()) { @@ -327,54 +327,54 @@ void btSoftBody::appendAnchor(int node,btRigidBody* body,bool disableCollision // 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); + 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); + appendLinearJoint(specs,m_clusters[0],body); } // void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body) { -appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]); + 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); + 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); + appendAngularJoint(specs,m_clusters[0],body); } // void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body) { -appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]); + appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]); } // @@ -463,8 +463,8 @@ void btSoftBody::setTotalMass(btScalar mass,bool fromfaces) { const Face& f=m_faces[i]; const btScalar twicearea=AreaOf( f.m_n[0]->m_x, - f.m_n[1]->m_x, - f.m_n[2]->m_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; @@ -494,13 +494,17 @@ void btSoftBody::setTotalDensity(btScalar density) void btSoftBody::transform(const btTransform& trs) { const btScalar margin=getCollisionShape()->getMargin(); + ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; + for(int i=0,ni=m_nodes.size();igetMargin(); + ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; + for(int i=0,ni=m_nodes.size();i0 ? - 1/(m_nodes[i].m_im*tmass) : - kmass/tmass; + 1/(m_nodes[i].m_im*tmass) : + kmass/tmass; } /* Pos */ const btVector3 com=evaluateCom(); @@ -578,16 +585,16 @@ void btSoftBody::setPose(bool bvolume,bool bframe) m_pose.m_scl.setIdentity(); /* Aqq */ m_pose.m_aqq[0] = - m_pose.m_aqq[1] = - m_pose.m_aqq[2] = btVector3(0,0,0); + m_pose.m_aqq[1] = + m_pose.m_aqq[2] = btVector3(0,0,0); for( i=0,ni=m_nodes.size();im_nodes.size();im_nodes.size();im_nodes[i]->m_x*cluster->m_masses[i]; + com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i]; } -return(com*cluster->m_imass); + return(com*cluster->m_imass); } // btVector3 btSoftBody::clusterCom(int cluster) const { -return(clusterCom(m_clusters[cluster])); + return(clusterCom(m_clusters[cluster])); } // btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos) { -return(cluster->m_lv+cross(cluster->m_av,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++; + 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++; + 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); + 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++; + 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++; + 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); + 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++; + cluster->m_dimpulses[0]+=impulse*cluster->m_imass; + cluster->m_ndimpulses++; } // @@ -762,9 +769,9 @@ int btSoftBody::generateBendingConstraints(int distance,Material* mat) // void btSoftBody::randomizeConstraints() { -unsigned long seed=243703; + unsigned long seed=243703; #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff) -int i,ni; + int i,ni; for(i=0,ni=m_links.size();im_leaf) m_cdbvt.remove(c->m_leaf); -c->~Cluster(); -btAlignedFree(c); -m_clusters.remove(c); + Cluster* c=m_clusters[index]; + if(c->m_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); + 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; + m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster(); + m_clusters[i]->m_collide= true; } -k=m_clusters.size(); -if(k>0) + k=m_clusters.size(); + if(k>0) { - /* Initialize */ - btAlignedObjectArray centers; - btVector3 cog(0,0,0); - int i; - for(i=0;i centers; + btVector3 cog(0,0,0); + int i; + for(i=0;im_nodes.push_back(&m_nodes[i]); + cog+=m_nodes[i].m_x; + m_clusters[(i*29873)%m_clusters.size()]->m_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; + 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) + btVector3 c(0,0,0); + for(int j=0;jm_nodes.size();++j) { - c+=m_clusters[i]->m_nodes[j]->m_x; + c+=m_clusters[i]->m_nodes[j]->m_x; } - if(m_clusters[i]->m_nodes.size()) + 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); + 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]); + m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]); } } while(changed&&(iterations cids; - cids.resize(m_nodes.size(),-1); - for(i=0;i cids; + cids.resize(m_nodes.size(),-1); + for(i=0;im_nodes.size();++j) + for(int j=0;jm_nodes.size();++j) { - cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i; + 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()) + if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size()) { - m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]); + m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]); } } } } } - /* Master */ - if(m_clusters.size()>1) + /* 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]); + 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) + if(m_clusters[i]->m_nodes.size()==0) { - releaseCluster(i--); + releaseCluster(i--); } } - - initializeClusters(); - updateClusters(); - return(m_clusters.size()); + + initializeClusters(); + updateClusters(); + + //for self-collision + m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size()); + { + for (int c0=0;c0m_clusterIndex=c0; + for (int c1=0;c1m_nodes.size();i++) + { + for (int j=0;jm_nodes.size();j++) + { + if (cla->m_nodes[i] == clb->m_nodes[j]) + { + connected=true; + break; + } + } + } + m_clusterConnectivity[c0+c1*m_clusters.size()]=connected; + } + } + } + + return(m_clusters.size()); } -return(0); + 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; + 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))) + if(!SameSign(ifn->Eval(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; + btSwap(m_links[i],m_links[m_links.size()-1]); + m_links.pop_back();--i; } } } -/* Fill edges */ -for(i=0;i0) + Node& a=m_nodes[i]; + Node& b=m_nodes[j]; + const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary); + if(t>0) { - 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) + 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) + 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; + 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) + if(b.m_im>0) { b.m_im/=0.5;m=1/b.m_im; } else - m=0; + m=0; } - appendNode(x,m); - edges(i,j)=m_nodes.size()-1; - m_nodes[edges(i,j)].m_v=v; - ++newnodes; + 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 */ + /* Refine links */ for(i=0,ni=m_links.size();i0) { - appendLink(i); - todetach=m_links.size()-1; + 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]]; } - else + } + } + /* Refine faces */ + for(i=0;iEval(m_nodes[id[0]].m_x)Eval(m_nodes[id[1]].m_x)0) { - int cn=cnodes[int(l.m_n[j]-nbase)]; - if(cn) l.m_n[j]=&m_nodes[cn]; + 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)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 ranks; + btAlignedObjectArray todelete; + ranks.resize(nnodes,0); + for(i=0,ni=m_links.size();i=0;--i) +#if 0 + for(i=nnodes-1;i>=0;--i) { - if(!ranks[i]) todelete.push_back(i); + if(!ranks[i]) todelete.push_back(i); } - if(todelete.size()) + if(todelete.size()) { - btAlignedObjectArray& map=ranks; - for(int i=0;i& map=ranks; + for(int i=0;im_v=v; -pn[1]->m_v=v; -for(i=0,ni=m_links.size();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; + appendLink(i); + Link* pft[]={&m_links[i],&m_links[m_links.size()-1]}; + pft[0]->m_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); + appendFace(i); + Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]}; + pft[0]->m_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) + if(!done) { - m_ndbvt.remove(pn[0]->m_leaf); - m_ndbvt.remove(pn[1]->m_leaf); - m_nodes.pop_back(); - m_nodes.pop_back(); + m_ndbvt.remove(pn[0]->m_leaf); + m_ndbvt.remove(pn[1]->m_leaf); + m_nodes.pop_back(); + m_nodes.pop_back(); } -return(done); + return(done); } // -bool btSoftBody::rayCast(const btVector3& org, - const btVector3& dir, - sRayCast& results, - btScalar maxtime) +bool btSoftBody::rayTest(const btVector3& rayFrom, + const btVector3& rayTo, + sRayCast& results) { -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); + if(m_faces.size()&&m_fdbvt.empty()) + initializeFaceTree(); + + results.body = this; + results.fraction = 1.f; + results.feature = eFeature::None; + results.index = -1; + + return(rayTest(rayFrom,rayTo,results.fraction,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) + 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; + 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; + 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; } } @@ -1282,11 +1320,11 @@ void btSoftBody::predictMotion(btScalar dt) 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; @@ -1310,45 +1348,48 @@ void btSoftBody::predictMotion(btScalar dt) /* Bounds */ updateBounds(); /* Nodes */ + ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; for(i=0,ni=m_nodes.size();im_v+ - f.m_n[1]->m_v+ - f.m_n[2]->m_v)/3; + f.m_n[1]->m_v+ + f.m_n[2]->m_v)/3; + vol = VolumeOf(f,m_sst.radmrg); m_fdbvt.update( f.m_leaf, - VolumeOf(f,m_sst.radmrg), - v*m_sst.velmrg, - m_sst.updmrg); - } + vol, + 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); @@ -1361,104 +1402,104 @@ void btSoftBody::predictMotion(btScalar dt) // void btSoftBody::solveConstraints() { -/* Apply clusters */ -applyClusters(false); -/* Prepare links */ + /* Apply clusters */ + applyClusters(false); + /* Prepare links */ -int i,ni; + 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); + Link& l=m_links[i]; + l.m_c3 = l.m_n[1]->m_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(); + Anchor& a=m_anchors[i]; + const btVector3 ra=a.m_body->getWorldTransform().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 velocities */ + if(m_cfg.viterations>0) { - /* Solve */ - for(int isolve=0;isolve0) + /* Solve positions */ + if(m_cfg.piterations>0) { - for(int isolve=0;isolve0) + /* Solve drift */ + if(m_cfg.diterations>0) { - 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; + const int nb=bodies.size(); + int iterations=0; + int i; -for(i=0;im_cfg.citerations); + iterations=btMax(iterations,bodies[i]->m_cfg.citerations); } -for(i=0;iprepareClusters(iterations); + bodies[i]->prepareClusters(iterations); } -for(i=0;isolveClusters(sor); + bodies[j]->solveClusters(sor); } } -for(i=0;icleanupClusters(); + bodies[i]->cleanupClusters(); } } @@ -1506,48 +1547,54 @@ void btSoftBody::integrateMotion() } // - btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt) +btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt) { -o = org; -d = dir; -mint = mxt; -face = 0; -tests = 0; + m_rayFrom = rayFrom; + m_rayNormalizedDirection = (rayTo-rayFrom); + m_rayTo = rayTo; + m_mint = mxt; + m_face = 0; + m_tests = 0; } // -void btSoftBody::RayCaster::Process(const btDbvtNode* leaf) +void btSoftBody::RayFromToCaster::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)&&(tdata; + const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection, + f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + m_mint); + if((t>0)&&(tteps)&&(tceps) && (dot(n,cross(b-hit,c-hit))>ceps) && (dot(n,cross(c-hit,a-hit))>ceps)) @@ -1569,9 +1616,9 @@ void btSoftBody::pointersToIndices() 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); + + const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir, + f.m_n[0]->m_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; + } + else + {/* Use dbvt */ + RayFromToCaster collider(rayFrom,rayTo,mint); + + btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider); + if(collider.m_face) + { + mint=collider.m_mint; feature=btSoftBody::eFeature::Face; - index=(int)(collider.face-&m_faces[0]); + index=(int)(collider.m_face-&m_faces[0]); cnt=1; - } } + } return(cnt); } // void btSoftBody::initializeFaceTree() { -m_fdbvt.clear(); -for(int i=0;igetCollisionShape(); - const btTransform& wtr=prb->getInterpolationWorldTransform(); + btCollisionShape* shp=colObj->getCollisionShape(); + btRigidBody* tmpRigid = btRigidBody::upcast(colObj); + const btTransform& wtr=tmpRigid? tmpRigid->getInterpolationWorldTransform() : colObj->getWorldTransform(); btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x), - shp, - nrm, - margin); + shp, + nrm, + margin); if(dst<0) { - cti.m_body = prb; + cti.m_colObj = colObj; cti.m_normal = wtr.getBasis()*nrm; cti.m_offset = -dot( cti.m_normal, - x-cti.m_normal*dst); + x-cti.m_normal*dst); return(true); } return(false); @@ -1751,7 +1804,7 @@ void btSoftBody::updateNormals() { btSoftBody::Face& f=m_faces[i]; const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x, - f.m_n[2]->m_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; @@ -1769,28 +1822,28 @@ void btSoftBody::updateNormals() 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... + 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); - } + if(0!=getBroadphaseHandle()) + { + m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(), + m_bounds[0], + m_bounds[1], + m_worldInfo->m_dispatcher); } - else - { + } + else + { m_bounds[0]= - m_bounds[1]=btVector3(0,0,0); - } + m_bounds[1]=btVector3(0,0,0); + } } @@ -1821,12 +1874,12 @@ void btSoftBody::updatePose() pose.m_rot=r; pose.m_scl=pose.m_aqq*r.transpose()*Apq; if(m_cfg.maxvolume>1) - { + { const btScalar idet=Clamp( 1/pose.m_scl.determinant(), - 1,m_cfg.maxvolume); + 1,m_cfg.maxvolume); pose.m_scl=Mul(pose.m_scl,idet); - } - + } + } } @@ -1881,53 +1934,53 @@ 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_masses[j] = c.m_nodes[j]->m_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; + 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; + const btVector3 k=c.m_nodes[i]->m_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; } } } @@ -1936,49 +1989,49 @@ 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; + const btVector3 a=c.m_nodes[i]->m_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 */ + 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); - + 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 */ +#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; @@ -1988,74 +2041,79 @@ 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_v*c.m_masses[i]; + c.m_lv += v; + c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v); } } - /* Dbvt */ - if(c.m_collide) + 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) { - btVector3 mi=c.m_nodes[0]->m_x; - btVector3 mx=mi; - for(int j=1;jm_x); - mx.setMax(c.m_nodes[j]->m_x); + Node& n=*c.m_nodes[j]; + const btVector3 x=c.m_framexform*c.m_framerefs[j]; + n.m_x=Lerp(n.m_x,x,c.m_matching); + } + } + /* Dbvt */ + if(c.m_collide) + { + btVector3 mi=c.m_nodes[0]->m_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); + 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); + 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) + m_joints[i]->Terminate(m_sst.sdt); + if(m_joints[i]->m_delete) { - btAlignedFree(m_joints[i]); - m_joints.remove(m_joints[i--]); + btAlignedFree(m_joints[i]); + m_joints.remove(m_joints[i--]); } } } @@ -2063,9 +2121,9 @@ for(int i=0;iPrepare(m_sst.sdt,iterations); + m_joints[i]->Prepare(m_sst.sdt,iterations); } } @@ -2073,50 +2131,51 @@ for(int i=0;iSolve(m_sst.sdt,sor); + m_joints[i]->Solve(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; + 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) + 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; + const int idx=int(c.m_nodes[j]-&m_nodes[0]); + const btVector3& x=c.m_nodes[j]->m_x; + const btScalar q=c.m_masses[j]; + deltas[idx] += (v+cross(w,x-c.m_com))*q; + weights[idx] += q; } } } @@ -2131,18 +2190,21 @@ void btSoftBody::dampClusters() { int i; -for(i=0;i0) + Cluster& c=*m_clusters[i]; + if(c.m_ndamping>0) { - for(int j=0;j0) + Node& n=*c.m_nodes[j]; + if(n.m_im>0) { - 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); + const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com); + if(vx.length2()<=n.m_v.length2()) + { + n.m_v += c.m_ndamping*(vx-n.m_v); + } } } } @@ -2152,154 +2214,155 @@ for(i=0;i0) + 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_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; } -m_drift /=(btScalar)iterations; + 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]); + 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) + if(m_split>0) { - m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); - m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + 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) + 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_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; } -m_drift /=(btScalar)iterations; + 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); + 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) + if(m_split>0) { - m_bodies[0].applyDAImpulse(-m_sdrift); - m_bodies[1].applyDAImpulse( m_sdrift); + 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) + 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_drift=m_drift*m_erp/dt; + if(m_split>0) { - m_sdrift = m_massmatrix*(m_drift*m_split); - m_drift *= 1-m_split; + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; } - m_drift/=(btScalar)iterations; + m_drift/=(btScalar)iterations; } else { - m_drift=m_sdrift=btVector3(0,0,0); + 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 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; + 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]); + 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) + if(m_split>0) { - m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); - m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + 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; @@ -2311,14 +2374,14 @@ void btSoftBody::applyForces() const bool as_pressure=kPR!=0; const bool as_volume=kVC>0; const bool as_aero= as_lift || - as_drag ; + as_drag ; const bool as_vaero= as_aero && - (m_cfg.aeromodel=btSoftBody::eAeroModel::F_TwoSided); + (m_cfg.aeromodel>=btSoftBody::eAeroModel::F_TwoSided); const bool use_medium= as_aero; const bool use_volume= as_pressure || - as_volume ; + as_volume ; btScalar volume=0; btScalar ivolumetp=0; btScalar dvolumetv=0; @@ -2447,12 +2510,10 @@ void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti) for(int i=0,ni=psb->m_rcontacts.size();im_rcontacts[i]; - ///skip object that don't have collision response - if (!psb->getWorldInfo()->m_dispatcher->needsResponse(psb,c.m_cti.m_body)) - continue; - const sCti& cti=c.m_cti; - const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt; + btRigidBody* tmpRigid = btRigidBody::upcast(cti.m_colObj); + + const btVector3 va=tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0); 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); @@ -2462,7 +2523,8 @@ void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti) 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); + if (tmpRigid) + tmpRigid->applyImpulse(impulse,c.m_c1); } } } @@ -2470,32 +2532,32 @@ void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti) // void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti) { -for(int i=0,ni=psb->m_scontacts.size();im_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 SContact& c=psb->m_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; + 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()); + 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()); } } @@ -2522,107 +2584,114 @@ void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti) // void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst) { -for(int i=0,ni=psb->m_links.size();im_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); + Link& l=psb->m_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) + 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); + return(0); } // btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver) { -switch(solver) + switch(solver) { case eVSolver::Linear: return(&btSoftBody::VSolve_Links); } -return(0); + return(0); } // void btSoftBody::defaultCollisionHandler(btCollisionObject* pco) { -switch(m_cfg.collisions&fCollision::RVSmask) + 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); + btSoftColliders::CollideSDF_RS docollide; + btRigidBody* prb1=btRigidBody::upcast(pco); + btTransform wtr=prb1 ? prb1->getInterpolationWorldTransform() : pco->getWorldTransform(); + + const btTransform ctr=pco->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.m_colObj1 = pco; + docollide.m_rigidBody = prb1; + + docollide.dynmargin = basemargin+timemargin; + docollide.stamargin = basemargin; + m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide); } - break; + break; case fCollision::CL_RS: { - btSoftColliders::CollideCL_RS collider; - collider.Process(this,btRigidBody::upcast(pco)); + btSoftColliders::CollideCL_RS collider; + collider.Process(this,pco); } - break; + break; } } // void btSoftBody::defaultCollisionHandler(btSoftBody* psb) { -const int cf=m_cfg.collisions&psb->m_cfg.collisions; -switch(cf&fCollision::SVSmask) + 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); + btSoftColliders::CollideCL_SS docollide; + docollide.Process(this,psb); } - break; + 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); + //only self-collision for Cluster, not Vertex-Face yet + if (this!=psb) + { + 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; + docollide.psb[0]->m_ndbvt.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; + docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + } } - break; + break; } } diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h index 743462d259a..a62c21883c8 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h @@ -18,7 +18,6 @@ subject to the following restrictions: #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" @@ -45,7 +44,8 @@ struct btSoftBodyWorldInfo }; -/// btSoftBody is work-in-progress +///The btSoftBody is an class to simulate cloth and volumetric soft bodies. +///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject. class btSoftBody : public btCollisionObject { public: @@ -64,13 +64,13 @@ public: 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 @@ -79,7 +79,7 @@ public: SContacts, ///Soft contacts solver END };}; - + ///eSolverPresets struct eSolverPresets { enum _ { Positions, @@ -87,7 +87,7 @@ public: Default = Positions, END };}; - + ///eFeature struct eFeature { enum _ { None, @@ -96,20 +96,20 @@ public: 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 @@ -117,7 +117,7 @@ public: Default = SDF_RS, END };}; - + ///fMaterial struct fMaterial { enum _ { DebugDraw = 0x0001, /// Enable debug draw @@ -125,26 +125,26 @@ public: 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) + btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction) }; - + /* ImplicitFn */ struct ImplicitFn { virtual btScalar Eval(const btVector3& x)=0; }; - + // // Internal types // @@ -155,7 +155,7 @@ public: /* sCti is Softbody contact info */ struct sCti { - btRigidBody* m_body; /* Rigid body */ + btCollisionObject* m_colObj; /* Rigid body */ btVector3 m_normal; /* Outward normal */ btScalar m_offset; /* Offset from origin */ }; @@ -182,7 +182,7 @@ public: btScalar m_kVST; // Volume stiffness coefficient [0,1] int m_flags; // Flags }; - + /* Feature */ struct Feature : Element { @@ -293,12 +293,13 @@ public: btVector3 m_lv; btVector3 m_av; btDbvtNode* m_leaf; - btScalar m_ndamping; - btScalar m_ldamping; - btScalar m_adamping; + btScalar m_ndamping; /* Node damping */ + btScalar m_ldamping; /* Linear damping */ + btScalar m_adamping; /* Angular damping */ btScalar m_matching; bool m_collide; - Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) {} + int m_clusterIndex; + Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) {} }; /* Impulse */ struct Impulse @@ -309,109 +310,115 @@ public: 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) {} + Cluster* m_soft; + btRigidBody* m_rigid; + btCollisionObject* m_collisionObject; + + Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {} + Body(Cluster* p) : m_soft(p),m_rigid(0),m_collisionObject(0) {} + Body(btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj) + { + m_rigid = btRigidBody::upcast(m_collisionObject); + } + 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_collisionObject) return(m_collisionObject->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 @@ -419,15 +426,15 @@ public: struct eType { enum _ { Linear, Angular, - Contact, + Contact };}; struct Specs - { - Specs() : erp(1),cfm(1),split(1) {} + { + Specs() : erp(1),cfm(1),split(1) {} btScalar erp; btScalar cfm; btScalar split; - }; + }; Body m_bodies[2]; btVector3 m_refs[2]; btScalar m_cfm; @@ -438,7 +445,7 @@ public: btMatrix3x3 m_massmatrix; bool m_delete; virtual ~Joint() {} - Joint() : m_delete(false) {} + 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; @@ -448,9 +455,9 @@ public: 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); @@ -461,17 +468,17 @@ public: 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()) {} + { + Specs() : icontrol(IControl::Default()) {} btVector3 axis; IControl* icontrol; - }; + }; btVector3 m_axis[2]; IControl* m_icontrol; void Prepare(btScalar dt,int iterations); @@ -534,23 +541,26 @@ public: 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); + /// RayFromToCaster takes a ray from, ray to (instead of direction!) + struct RayFromToCaster : btDbvt::ICollide + { + btVector3 m_rayFrom; + btVector3 m_rayTo; + btVector3 m_rayNormalizedDirection; + btScalar m_mint; + Face* m_face; + int m_tests; + RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,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); - }; + + static inline btScalar rayFromToTriangle(const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayNormalizedDirection, + const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar maxt=SIMD_INFINITY); + }; // // Typedef's @@ -596,16 +606,19 @@ public: btDbvt m_fdbvt; // Faces tree btDbvt m_cdbvt; // Clusters tree tClusterArray m_clusters; // Clusters - - btTransform m_initialWorldTransform; //used to attach constraints etc. + + btAlignedObjectArraym_clusterConnectivity;//cluster connectivity, for self-collision + + btTransform m_initialWorldTransform; + // // Api // - + /* ctor */ btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, - const btVector3* x, - const btScalar* m); + const btVector3* x, + const btScalar* m); /* dtor */ virtual ~btSoftBody(); /* Check for existing link */ @@ -617,59 +630,60 @@ public: return m_worldInfo; } + ///@todo: avoid internal softbody shape hack and move collision code to collision library virtual void setCollisionShape(btCollisionShape* collisionShape) { - //don't do anything, due to the internal shape hack: todo: fix this + } bool checkLink( int node0, int node1) const; bool checkLink( const Node* node0, - const Node* node1) const; + const Node* node1) const; /* Check for existring face */ bool checkFace( int node0, - int node1, - int node2) const; + 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); + 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); + const btVector3& o, + Node* feature); void appendNote( const char* text, - const btVector3& o, - Link* feature); + const btVector3& o, + Link* feature); void appendNote( const char* text, - const btVector3& o, - Face* feature); + 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); + int node1, + Material* mat=0, + bool bcheckexist=false); void appendLink( Node* node0, - Node* node1, - Material* mat=0, - bool bcheckexist=false); + 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); + int node1, + int node2, + Material* mat=0); /* Append anchor */ void appendAnchor( int node, - btRigidBody* body,bool disableCollision); + btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false); /* Append linear joint */ void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); void appendLinearJoint(const LJoint::Specs& specs,Body body=Body()); @@ -682,7 +696,7 @@ public: void addForce( const btVector3& force); /* Add force (or gravity) to a node of the body */ void addForce( const btVector3& force, - int node); + int node); /* Add velocity to the entire body */ void addVelocity( const btVector3& velocity); @@ -691,17 +705,17 @@ public: /* Add velocity to a node of the body */ void addVelocity( const btVector3& velocity, - int node); + int node); /* Set mass */ void setMass( int node, - btScalar mass); + 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); + bool fromfaces=false); /* Set total density */ void setTotalDensity(btScalar density); /* Transform */ @@ -714,7 +728,7 @@ public: void scale( const btVector3& scl); /* Set current state as pose */ void setPose( bool bvolume, - bool bframe); + bool bframe); /* Return the volume */ btScalar getVolume() const; /* Cluster count */ @@ -734,7 +748,7 @@ public: 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); + Material* mat=0); /* Randomize constraints to reduce solver bias */ void randomizeConstraints(); /* Release clusters */ @@ -747,11 +761,11 @@ public: /* 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); + + ///Ray casting using rayFrom and rayTo in worldspace, (not direction!) + bool rayTest(const btVector3& rayFrom, + const btVector3& rayTo, + sRayCast& results); /* Solver presets */ void setSolver(eSolverPresets::_ preset); /* predictMotion */ @@ -769,11 +783,11 @@ public: /* defaultCollisionHandlers */ void defaultCollisionHandler(btCollisionObject* pco); void defaultCollisionHandler(btSoftBody* psb); - + // // Cast // - + static const btSoftBody* upcast(const btCollisionObject* colObj) { if (colObj->getInternalType()==CO_SOFT_BODY) @@ -801,11 +815,12 @@ public: // 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; + + int rayTest(const btVector3& rayFrom,const btVector3& rayTo, + 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; + bool checkContact(btCollisionObject* colObj,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const; void updateNormals(); void updateBounds(); void updatePose(); @@ -825,7 +840,7 @@ public: static void VSolve_Links(btSoftBody* psb,btScalar kst); static psolver_t getSolver(ePSolver::_ solver); static vsolver_t getSolver(eVSolver::_ solver); - + }; diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp index 61a57ea5da9..f334e15e0d3 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp @@ -32,7 +32,7 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" #include "BulletSoftBody/btSoftBody.h" -#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.3)//make this configurable +#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) : btCollisionAlgorithm(ci), @@ -50,27 +50,27 @@ btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm() btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): - m_dispatcher(dispatcher), - m_dispatchInfoPtr(0) +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(); + // + // 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 ); - + // m_dispatcher->releaseManifold( m_manifoldPtr ); + } - + void btSoftBodyTriangleCallback::clearCache() { @@ -83,18 +83,18 @@ void btSoftBodyTriangleCallback::clearCache() delete tmp->m_childShape; } m_shapeCache.clear(); -}; +} void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) { - //just for debugging purposes + //just for debugging purposes //printf("triangle %d",m_triangleCount++); btCollisionObject* ob = static_cast(m_triBody); btCollisionAlgorithmConstructionInfo ci; ci.m_dispatcher1 = m_dispatcher; - ///debug drawing of the overlapping triangles + ///debug drawing of the overlapping triangles if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0) { btVector3 color(255,255,0); @@ -107,7 +107,7 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, btTriIndex triIndex(partId,triangleIndex,0); btHashKey triKey(triIndex.getUid()); - + btTriIndex* shapeIndex = m_shapeCache[triKey]; if (shapeIndex) { @@ -116,13 +116,13 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, //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); @@ -133,56 +133,56 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, //aabb filter is already applied! //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); - -// if (m_softBody->getCollisionShape()->getShapeType()== + + // if (m_softBody->getCollisionShape()->getShapeType()== { -// btVector3 other; + // 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], - triangle[1], - triangle[2], - triangle[0]-normal, - triangle[1]-normal, - triangle[2]-normal}; + // 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); - + // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other); + //btTriangleShape tm(triangle[0],triangle[1],triangle[2]); - // tm.setMargin(m_collisionMarginTriangle); - + // 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); + // 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 ); triIndex.m_childShape = tm; m_shapeCache.insert(triKey,triIndex); } - + } @@ -194,7 +194,7 @@ void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMargin m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION); m_resultOut = resultOut; - + btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax; m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax); btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5); @@ -217,8 +217,8 @@ void btSoftBodyConcaveCollisionAlgorithm::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; @@ -228,26 +228,26 @@ void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* b btCollisionObject* triOb = triBody; btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); - - // if (convexBody->getCollisionShape()->isConvex()) + + // if (convexBody->getCollisionShape()->isConvex()) { btScalar collisionMarginTriangle = concaveShape->getMargin(); - -// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); + + // 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); + // m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax()); - - // resultOut->refreshContactPoints(); - + + // resultOut->refreshContactPoints(); + } - + } } @@ -287,7 +287,7 @@ btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionO btScalar m_ccdSphereRadius; btScalar m_hitFraction; - + LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) :m_ccdSphereFromTrans(from), @@ -296,8 +296,8 @@ btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionO m_hitFraction(hitFraction) { } - - + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) { (void)partId; @@ -327,9 +327,9 @@ btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionO }; - - + + if (triBody->getCollisionShape()->isConcave()) { btVector3 rayAabbMin = convexFromLocal.getOrigin(); @@ -349,12 +349,12 @@ btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionO btCollisionObject* concavebody = triBody; btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); - + if (triangleMesh) { triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); } - + if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h index 08ac3f11e20..a6ea33717bc 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h @@ -35,7 +35,7 @@ struct btTriIndex { int m_PartIdTriangleIndex; class btCollisionShape* m_childShape; - + btTriIndex(int partId,int triangleIndex,btCollisionShape* shape) { m_PartIdTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; @@ -75,11 +75,11 @@ class btSoftBodyTriangleCallback : public btTriangleCallback btScalar m_collisionMarginTriangle; btHashMap,btTriIndex> m_shapeCache; - + public: -int m_triangleCount; - -// btPersistentManifold* m_manifoldPtr; + int m_triangleCount; + + // btPersistentManifold* m_manifoldPtr; btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); @@ -88,7 +88,7 @@ int m_triangleCount; virtual ~btSoftBodyTriangleCallback(); virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); - + void clearCache(); SIMD_FORCE_INLINE const btVector3& getAabbMin() const diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp index d9919967233..6ab93c16402 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -22,57 +22,57 @@ subject to the following restrictions: // 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); - } + 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& 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); + 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) + const btDbvtNode* node, + int depth, + const btVector3& ncolor, + const btVector3& lcolor, + int mindepth, + int maxdepth) { -if(node) + if(node) { - if(node->isinternal()&&((depthisinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); - drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); + drawTree(idraw,node->childs[0],depth+1,ncolor,lcolor,mindepth,maxdepth); + drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); } - if(depth>=mindepth) + 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); + 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); } } } @@ -81,25 +81,25 @@ if(node) template static inline T sum(const btAlignedObjectArray& items) { -T v; -if(items.size()) + 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); + const btScalar n=(btScalar)(items.size()>0?items.size():1); + return(sum(items)/n); } // @@ -136,27 +136,27 @@ static inline btScalar tetravolume(const btVector3& x0, // #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)}; + 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) + btIDebugDraw* idraw, + int drawflags) { const btScalar scl=(btScalar)0.1; const btScalar nscl=scl*5; @@ -251,29 +251,29 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, 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); + (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); + 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; @@ -284,32 +284,32 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, 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); + hres.m_OutputVertices[idx[1]], + hres.m_OutputVertices[idx[2]], + color,1); } + hlib.ReleaseResult(hres); + } /* Velocities */ - #if 0 +#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 + } +#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)) { @@ -318,9 +318,9 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, 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); } } @@ -333,33 +333,33 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, /* Joints */ if(0!=(drawflags&fDrawFlags::Joints)) { - for(i=0;im_joints.size();++i) + for(i=0;im_joints.size();++i) { - const btSoftBody::Joint* pj=psb->m_joints[i]; - switch(pj->Type()) + 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)); + 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; + 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)); + 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)); } } } @@ -368,10 +368,10 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, // void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, - btIDebugDraw* idraw, - bool masses, - bool areas, - bool /*stress*/) + btIDebugDraw* idraw, + bool masses, + bool areas, + bool /*stress*/) { for(int i=0;im_nodes.size();++i) { @@ -394,34 +394,34 @@ void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, // void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) + btIDebugDraw* idraw, + int mindepth, + int maxdepth) { -drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,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) + btIDebugDraw* idraw, + int mindepth, + int maxdepth) { -drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,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) + btIDebugDraw* idraw, + int mindepth, + int maxdepth) { -drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,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) + btIDebugDraw* idraw) { if(psb->m_pose.m_bframe) { @@ -445,9 +445,9 @@ void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, // btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from, - const btVector3& to, - int res, - int fixeds) + const btVector3& to, + int res, + int fixeds) { /* Create nodes */ const int r=res+2; @@ -477,13 +477,13 @@ btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, cons // 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) + 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 */ @@ -552,10 +552,216 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const return(psb); } +// +btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags, + float* tex_coords) +{ + + /* + * + * corners: + * + * [0][0] corner00 ------- corner01 [resx][0] + * | | + * | | + * [0][resy] corner10 -------- corner11 [resx][resy] + * + * + * + * + * + * + * "fixedgs" map: + * + * corner00 --> +1 + * corner01 --> +2 + * corner10 --> +4 + * corner11 --> +8 + * upper middle --> +16 + * left middle --> +32 + * right middle --> +64 + * lower middle --> +128 + * center --> +256 + * + * + * tex_coords size (resx-1)*(resy-1)*12 + * + * + * + * SINGLE QUAD INTERNALS + * + * 1) btSoftBody's nodes and links, + * diagonal link is optional ("gendiags") + * + * + * node00 ------ node01 + * | . + * | . + * | . + * | . + * | . + * node10 node11 + * + * + * + * 2) Faces: + * two triangles, + * UV Coordinates (hier example for single quad) + * + * (0,1) (0,1) (1,1) + * 1 |\ 3 \-----| 2 + * | \ \ | + * | \ \ | + * | \ \ | + * | \ \ | + * 2 |-----\ 3 \| 1 + * (0,0) (1,0) (1,0) + * + * + * + * + * + * + */ + +#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); + if(fixeds&16) psb->setMass(IDX((rx-1)/2,0),0); + if(fixeds&32) psb->setMass(IDX(0,(ry-1)/2),0); + if(fixeds&64) psb->setMass(IDX(rx-1,(ry-1)/2),0); + if(fixeds&128) psb->setMass(IDX((rx-1)/2,ry-1),0); + if(fixeds&256) psb->setMass(IDX((rx-1)/2,(ry-1)/2),0); + delete[] x; + delete[] m; + + + int z = 0; + /* Create links and faces */ + for(iy=0;iyappendLink(node00,node01); + if(mdy) psb->appendLink(node00,node10); + if(mdx&&mdy) + { + psb->appendFace(node00,node10,node11); + if (tex_coords) { + tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1); + tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2); + tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2); + } + psb->appendFace(node11,node01,node00); + if (tex_coords) { + tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2); + tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1); + tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1); + } + if (gendiags) psb->appendLink(node00,node11); + z += 12; + } + } + } + /* Finished */ +#undef IDX + return(psb); +} + +float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id) +{ + + /* + * + * + * node00 --- node01 + * | | + * node10 --- node11 + * + * + * ID map: + * + * node00 s --> 0 + * node00 t --> 1 + * + * node01 s --> 3 + * node01 t --> 1 + * + * node10 s --> 0 + * node10 t --> 2 + * + * node11 s --> 3 + * node11 t --> 2 + * + * + */ + + float tc=0.0f; + if (id == 0) { + tc = (1.0f/((resx-1))*ix); + } + else if (id==1) { + tc = (1.0f/((resy-1))*(resy-1-iy)); + } + else if (id==2) { + tc = (1.0f/((resy-1))*(resy-1-iy-1)); + } + else if (id==3) { + tc = (1.0f/((resx-1))*(ix+1)); + } + return tc; +} // btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center, - const btVector3& radius, - int res) + const btVector3& radius, + int res) { struct Hammersley { @@ -586,8 +792,8 @@ btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,c // btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,const btScalar* vertices, - const int* triangles, - int ntriangles) + const int* triangles, + int ntriangles) { int maxidx=0; int i,j,ni; @@ -615,7 +821,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo if(!chks[IDX(idx[j],idx[k])]) { chks[IDX(idx[j],idx[k])]=true; - chks[IDX(idx[k],idx[k])]=true; + chks[IDX(idx[k],idx[j])]=true; psb->appendLink(idx[j],idx[k]); } } @@ -628,7 +834,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo // btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, - int nvertices) + int nvertices) { HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); HullResult hres; diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h index e9c6cb20657..0e3b50397ee 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h @@ -39,69 +39,81 @@ struct fDrawFlags { enum _ { Joints = 0x1000, /* presets */ Std = Links+Faces+Tetras+Anchors+Notes+Joints, - StdTetra = Std-Faces+Tetras, + StdTetra = Std-Faces+Tetras };}; struct btSoftBodyHelpers { /* Draw body */ static void Draw( btSoftBody* psb, - btIDebugDraw* idraw, - int drawflags=fDrawFlags::Std); + btIDebugDraw* idraw, + int drawflags=fDrawFlags::Std); /* Draw body infos */ static void DrawInfos( btSoftBody* psb, - btIDebugDraw* idraw, - bool masses, - bool areas, - bool stress); + btIDebugDraw* idraw, + bool masses, + bool areas, + bool stress); /* Draw node tree */ static void DrawNodeTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); /* Draw face tree */ static void DrawFaceTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); /* Draw cluster tree */ static void DrawClusterTree(btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); /* Draw rigid frame */ static void DrawFrame( btSoftBody* psb, - btIDebugDraw* idraw); + btIDebugDraw* idraw); /* Create a rope */ static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo, - const btVector3& from, - const btVector3& to, - int res, - int fixeds); + 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); + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags); + /* Create a patch with UV Texture Coordinates */ + static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags, + float* tex_coords=0); + static float CalculateUV(int resx,int resy,int ix,int iy,int id); /* Create an ellipsoid */ static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, - const btVector3& center, - const btVector3& radius, - int res); + const btVector3& center, + const btVector3& radius, + int res); /* Create from trimesh */ static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo, - const btScalar* vertices, - const int* triangles, - int ntriangles); + const btScalar* vertices, + const int* triangles, + int ntriangles); /* Create from convex-hull */ static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo, - const btVector3* vertices, - int nvertices); + 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 index 8fcf633fecc..5f0f7d54318 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h @@ -31,14 +31,14 @@ subject to the following restrictions: 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; + 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; }; // @@ -48,10 +48,11 @@ class btSoftBodyCollisionShape : public btConcaveShape { public: btSoftBody* m_body; - + btSoftBodyCollisionShape(btSoftBody* backptr) { - m_body=backptr; + m_shapeType = SOFTBODY_SHAPE_PROXYTYPE; + m_body=backptr; } virtual ~btSoftBodyCollisionShape() @@ -68,37 +69,34 @@ public: ///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) + /* 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]); + aabbMin.setMin(crns[i]); + aabbMax.setMax(crns[i]); } } - virtual int getShapeType() const - { - return SOFTBODY_SHAPE_PROXYTYPE; - } + virtual void setLocalScaling(const btVector3& /*scaling*/) { ///na } virtual const btVector3& getLocalScaling() const { - static const btVector3 dummy(1,1,1); - return dummy; + static const btVector3 dummy(1,1,1); + return dummy; } virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const { @@ -121,24 +119,24 @@ 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 {} @@ -151,7 +149,7 @@ public: {} virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; } - + //debugging virtual const char* getName()const {return "SOFTCLUSTER";} @@ -173,8 +171,8 @@ public: template static inline void ZeroInitialize(T& value) { -static const T zerodummy; -value=zerodummy; + static const T zerodummy; + value=zerodummy; } // template @@ -194,23 +192,23 @@ 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) + 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); + 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)); + const btScalar sql=v.length2(); + if(sql>(maxlength*maxlength)) + return((v*maxlength)/btSqrt(sql)); else - return(v); + return(v); } // template @@ -235,8 +233,8 @@ static inline bool SameSign(const T& x,const T& y) // 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])); + const btVector3 d=x-y; + return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2])); } // static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s) @@ -273,7 +271,7 @@ static inline btMatrix3x3 Diagonal(btScalar x) } // static inline btMatrix3x3 Add(const btMatrix3x3& a, - const btMatrix3x3& b) + const btMatrix3x3& b) { btMatrix3x3 r; for(int i=0;i<3;++i) r[i]=a[i]+b[i]; @@ -281,7 +279,7 @@ static inline btMatrix3x3 Add(const btMatrix3x3& a, } // static inline btMatrix3x3 Sub(const btMatrix3x3& a, - const btMatrix3x3& b) + const btMatrix3x3& b) { btMatrix3x3 r; for(int i=0;i<3;++i) r[i]=a[i]-b[i]; @@ -289,7 +287,7 @@ static inline btMatrix3x3 Sub(const btMatrix3x3& a, } // static inline btMatrix3x3 Mul(const btMatrix3x3& a, - btScalar b) + btScalar b) { btMatrix3x3 r; for(int i=0;i<3;++i) r[i]=a[i]*b; @@ -298,9 +296,9 @@ static inline btMatrix3x3 Mul(const btMatrix3x3& a, // 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(); + 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) @@ -311,90 +309,90 @@ static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const bt // static inline btMatrix3x3 ImpulseMatrix( btScalar dt, - btScalar ima, - btScalar imb, - const btMatrix3x3& iwi, - const btVector3& r) + 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) + btScalar imb,const btMatrix3x3& iib,const btVector3& rb) { -return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse()); + return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse()); } // static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia, - const btMatrix3x3& iib) + const btMatrix3x3& iib) { -return(Add(iia,iib).inverse()); + return(Add(iia,iib).inverse()); } // static inline btVector3 ProjectOnAxis( const btVector3& v, - const btVector3& a) + const btVector3& a) { return(a*dot(v,a)); } // static inline btVector3 ProjectOnPlane( const btVector3& v, - const btVector3& a) + const btVector3& a) { return(v-ProjectOnAxis(v,a)); } // static inline void ProjectOrigin( const btVector3& a, - const btVector3& b, - btVector3& prj, - btScalar& sqd) + const btVector3& b, + btVector3& prj, + btScalar& sqd) { -const btVector3 d=b-a; -const btScalar m2=d.length2(); -if(m2>SIMD_EPSILON) + 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(l2(-dot(a,d)/m2,0,1); + const btVector3 p=a+d*t; + const btScalar l2=p.length2(); + if(l2SIMD_EPSILON) + const btVector3& q=cross(b-a,c-a); + const btScalar m2=q.length2(); + if(m2>SIMD_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)) + const btVector3 p=n*k; + if( (dot(cross(a-p,b-p),q)>0)&& + (dot(cross(b-p,c-p),q)>0)&& + (dot(cross(c-p,a-p),q)>0)) { - prj=p; - sqd=k2; + prj=p; + sqd=k2; } else { - ProjectOrigin(a,b,prj,sqd); - ProjectOrigin(b,c,prj,sqd); - ProjectOrigin(c,a,prj,sqd); + ProjectOrigin(a,b,prj,sqd); + ProjectOrigin(b,c,prj,sqd); + ProjectOrigin(c,a,prj,sqd); } } } @@ -403,53 +401,53 @@ if(m2>SIMD_EPSILON) // template static inline T BaryEval( const T& a, - const T& b, - const T& c, - const btVector3& coord) + 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 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)); + 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) + 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]) + 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]); + 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;i-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)Eval(Lerp(a,b,t)); + if((t<=0)||(t>=1)) break; + if(btFabs(v)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); + 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); + 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& x1, + const btVector3& x2) { const btVector3 a=x1-x0; const btVector3 b=x2-x0; @@ -494,9 +492,9 @@ static inline btScalar AreaOf( const btVector3& x0, // static inline btScalar VolumeOf( const btVector3& x0, - const btVector3& x1, - const btVector3& x2, - const btVector3& x3) + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) { const btVector3 a=x1-x0; const btVector3 b=x2-x0; @@ -506,8 +504,8 @@ static inline btScalar VolumeOf( const btVector3& x0, // static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, - const btVector3& x, - btSoftBody::sMedium& medium) + const btVector3& x, + btSoftBody::sMedium& medium) { medium.m_velocity = btVector3(0,0,0); medium.m_pressure = 0; @@ -525,8 +523,8 @@ static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, // static inline void ApplyClampedForce( btSoftBody::Node& n, - const btVector3& f, - btScalar dt) + const btVector3& f, + btScalar dt) { const btScalar dtim=dt*n.m_im; if((f*dtim).length2()>n.m_v.length2()) @@ -541,13 +539,13 @@ static inline void ApplyClampedForce( btSoftBody::Node& n, // static inline int MatchEdge( const btSoftBody::Node* a, - const btSoftBody::Node* b, - const btSoftBody::Node* ma, - const btSoftBody::Node* mb) + 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); + if((a==ma)&&(b==mb)) return(0); + if((a==mb)&&(b==ma)) return(1); + return(-1); } // @@ -557,56 +555,56 @@ return(-1); // struct btEigen { -static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0) + 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) + 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 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); + 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)data; - 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::Cluster* cluster=(btSoftBody::Cluster*)leaf->data; + btSoftClusterCollisionShape cshape(cluster); + const btConvexShape* rshape=(const btConvexShape*)m_colObj->getCollisionShape(); + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(), + rshape,m_colObj->getInterpolationWorldTransform(), + btVector3(1,0,0),res)) { - btSoftBody::CJoint joint; - if(SolveContact(res,cluster,prb,joint)) + btSoftBody::CJoint joint; + if(SolveContact(res,cluster,m_colObj,joint))//prb,joint)) { - btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); - *pj=joint;psb->m_joints.push_back(pj); - if(prb->isStaticOrKinematicObject()) + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;psb->m_joints.push_back(pj); + if(m_colObj->isStaticOrKinematicObject()) { - pj->m_erp *= psb->m_cfg.kSKHR_CL; - pj->m_split *= psb->m_cfg.kSK_SPLT_CL; + 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; + pj->m_erp *= psb->m_cfg.kSRHR_CL; + pj->m_split *= psb->m_cfg.kSR_SPLT_CL; } } } } - void Process(btSoftBody* ps,btRigidBody* pr) + void Process(btSoftBody* ps,btCollisionObject* colOb) { - 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); + psb = ps; + m_colObj = colOb; + idt = ps->m_sst.isdt; + margin = m_colObj->getCollisionShape()->getMargin(); + ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful. + friction = btMin(psb->m_cfg.kDF,m_colObj->getFriction()); + btVector3 mins; + btVector3 maxs; + + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + colOb->getCollisionShape()->getAabb(colOb->getInterpolationWorldTransform(),mins,maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(1,1,1)*margin); + ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this); } }; // @@ -762,36 +761,53 @@ struct btSoftColliders // struct CollideCL_SS : ClusterBase { - btSoftBody* bodies[2]; - void Process(const btDbvtNode* la,const btDbvtNode* lb) + 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::Cluster* cla=(btSoftBody::Cluster*)la->data; + btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data; + + + bool connected=false; + if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size())) { - btSoftBody::CJoint joint; - if(SolveContact(res,cla,clb,joint)) + connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex]; + } + + if (!connected) + { + 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* 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; + 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; + } } + } else + { + static int count=0; + count++; + //printf("count=%d\n",count); + } } - void Process(btSoftBody* psa,btSoftBody* psb) + 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); + 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; + psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this); } }; // @@ -799,96 +815,99 @@ struct btSoftColliders // struct CollideSDF_RS : btDbvt::ICollide { - void Process(const btDbvtNode* leaf) + void Process(const btDbvtNode* leaf) { - btSoftBody::Node* node=(btSoftBody::Node*)leaf->data; - DoNode(*node); + btSoftBody::Node* node=(btSoftBody::Node*)leaf->data; + DoNode(*node); } - void DoNode(btSoftBody::Node& n) const + 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 m=n.m_im>0?dynmargin:stamargin; + btSoftBody::RContact c; + if( (!n.m_battach)&& + psb->checkContact(m_colObj1,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 btScalar ima=n.m_im; + const btScalar imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f; + 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(); + const btTransform& wtr=m_rigidBody?m_rigidBody->getInterpolationWorldTransform() : m_colObj1->getWorldTransform(); + static const btMatrix3x3 iwiStatic(0,0,0,0,0,0,0,0,0); + const btMatrix3x3& iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic; + const btVector3 ra=n.m_x-wtr.getOrigin(); + const btVector3 va=m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra)*psb->m_sst.sdt : btVector3(0,0,0); + 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*m_colObj1->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 = m_colObj1->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR; + psb->m_rcontacts.push_back(c); + if (m_rigidBody) + m_rigidBody->activate(); } } } - btSoftBody* psb; - btRigidBody* prb; - btScalar dynmargin; - btScalar stamargin; + btSoftBody* psb; + btCollisionObject* m_colObj1; + btRigidBody* m_rigidBody; + btScalar dynmargin; + btScalar stamargin; }; // // CollideVF_SS // struct CollideVF_SS : btDbvt::ICollide { - void Process(const btDbvtNode* lnode, - const btDbvtNode* lface) + 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)) + 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)) + 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; + mb=0; } - const btScalar ms=ma+mb; - if(ms>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::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; + btSoftBody* psb[2]; + btScalar mrg; }; }; diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp index 53ac2782583..f5a67f6d895 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp @@ -29,10 +29,10 @@ btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfigura 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; @@ -40,26 +40,27 @@ btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfigura #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 //replace pool by a new one, with potential larger size - + if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool) { int curElemSize = m_collisionAlgorithmPool->getElementSize(); ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool - - + + int maxSize0 = sizeof(btSoftSoftCollisionAlgorithm); int maxSize1 = sizeof(btSoftRigidCollisionAlgorithm); int maxSize2 = sizeof(btSoftBodyConcaveCollisionAlgorithm); int collisionAlgorithmMaxElementSize = btMax(maxSize0,maxSize1); collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2); + if (collisionAlgorithmMaxElementSize > curElemSize) { m_collisionAlgorithmPool->~btPoolAllocator(); @@ -69,9 +70,6 @@ btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfigura } } - - - } btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration() @@ -93,7 +91,7 @@ btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfigur 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) { diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h index 41c3af96939..21addcfe2e1 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h @@ -32,7 +32,7 @@ class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfi btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc; btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc; btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc; - + public: btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp index e5feb5ef749..11ad9e7daba 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp @@ -35,13 +35,13 @@ m_isSwapped(isSwapped) btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm() { - + //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject); /*if (m_ownManifold) { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); } */ diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h index 74327e6c635..adc3844e363 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h @@ -28,15 +28,15 @@ class btSoftBody; /// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm { -// bool m_ownManifold; -// btPersistentManifold* m_manifoldPtr; + // 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); @@ -52,7 +52,7 @@ public: //we don't add any manifolds } - + struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp index b363a2efbc1..a0069b95145 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -28,17 +28,17 @@ subject to the following restrictions: 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; -m_sbi.m_broadphase = pairCache; -m_sbi.m_dispatcher = dispatcher; -m_sbi.m_sparsesdf.Initialize(); -m_sbi.m_sparsesdf.Reset(); + m_drawFlags = fDrawFlags::Std; + m_drawNodeTree = true; + m_drawFaceTree = false; + m_drawClusterTree = false; + m_sbi.m_broadphase = pairCache; + m_sbi.m_dispatcher = dispatcher; + m_sbi.m_sparsesdf.Initialize(); + m_sbi.m_sparsesdf.Reset(); } - + btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld() { @@ -55,7 +55,7 @@ void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) psb->predictMotion(timeStep); } } - + void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) { btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); @@ -63,6 +63,13 @@ void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) ///solve soft bodies constraints solveSoftBodiesConstraints(); + //self collisions + for ( int i=0;idefaultCollisionHandler(psb); + } + ///update soft bodies updateSoftBodies(); @@ -71,7 +78,7 @@ void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) void btSoftRigidDynamicsWorld::updateSoftBodies() { BT_PROFILE("updateSoftBodies"); - + for ( int i=0;i btSoftBodyArray; class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld { - + btSoftBodyArray m_softBodies; int m_drawFlags; bool m_drawNodeTree; @@ -32,9 +32,9 @@ class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld btSoftBodyWorldInfo m_sbi; protected: - + virtual void predictUnconstraintMotion(btScalar timeStep); - + virtual void internalSingleStepSimulation( btScalar timeStep); void updateSoftBodies(); @@ -43,17 +43,17 @@ protected: 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; } @@ -66,7 +66,7 @@ public: return m_sbi; } - + btSoftBodyArray& getSoftBodyArray() { return m_softBodies; @@ -76,7 +76,7 @@ public: { return m_softBodies; } - + }; #endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h index 7ca9c3415c9..1b34e0af60f 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h @@ -33,7 +33,7 @@ class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm btSoftBody* m_softBody0; btSoftBody* m_softBody1; - + public: btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) : btCollisionAlgorithm(ci) {} diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h index eafe74be1ae..cc4266732ae 100644 --- a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h +++ b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h @@ -23,139 +23,139 @@ subject to the following restrictions: // 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; } + 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... */ - } + ++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; } + pp=pc;pc=pn; } - return(refcount); } + return(refcount); + } // btScalar Evaluate( const btVector3& x, - btCollisionShape* shape, - btVector3& normal, - btScalar margin) - { + btCollisionShape* shape, + btVector3& normal, + btScalar margin) + { /* Lookup cell */ const btVector3 scx=x/voxelsz; const IntFrac ix=Decompose(scx.x()); @@ -166,19 +166,19 @@ struct btSparseSdf 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; } - } + { break; } + else + { c=c->next; } + } if(!c) - { + { ++nprobes; ++ncells; c=new Cell(); @@ -187,82 +187,82 @@ struct btSparseSdf 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]}; + 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 +#if 1 const btScalar gx[]={ d[1]-d[0],d[2]-d[3], - d[5]-d[4],d[6]-d[7]}; + 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]}; + 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]}; + 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)); + 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)); + 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)); + Lerp(gz[2],gz[3],ix.f),iy.f)); normal = normal.normalized(); - #else +#else normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized(); - #endif +#endif /* Distance */ const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f), - Lerp(d[3],d[2],ix.f),iy.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); + 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; + (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); - } + c.pclient); } } } + } // static inline btScalar DistanceToShape(const btVector3& x, - btCollisionShape* shape) - { + 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); } + return(0); + } // static inline IntFrac Decompose(btScalar x) - { + { /* That one need a lot of improvements... */ /* Remove test, faster floor... */ IntFrac r; @@ -272,18 +272,18 @@ struct btSparseSdf 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; @@ -291,16 +291,16 @@ struct btSparseSdf }; 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..99d5a6a2fef 100644 --- a/extern/bullet2/src/LinearMath/CMakeLists.txt +++ b/extern/bullet2/src/LinearMath/CMakeLists.txt @@ -3,7 +3,14 @@ INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src } ) -ADD_LIBRARY(LibLinearMath +SET(LinearMath_SRCS + btConvexHull.cpp + btQuickprof.cpp + btGeometryUtil.cpp + btAlignedAllocator.cpp +) + +SET(LinearMath_HDRS btAlignedObjectArray.h btList.h btPoolAllocator.h @@ -16,7 +23,6 @@ ADD_LIBRARY(LibLinearMath btScalar.h btAabbUtil2.h btConvexHull.h - btConvexHull.cpp btMinMax.h btQuaternion.h btStackAlloc.h @@ -25,11 +31,21 @@ ADD_LIBRARY(LibLinearMath btTransform.h btAlignedAllocator.h btIDebugDraw.h - btPoint3.h btQuickprof.h btTransformUtil.h - btQuickprof.cpp - btGeometryUtil.cpp - btAlignedAllocator.cpp ) +ADD_LIBRARY(LinearMath ${LinearMath_SRCS} ${LinearMath_HDRS}) +SET_TARGET_PROPERTIES(LinearMath PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(LinearMath PROPERTIES SOVERSION ${BULLET_VERSION}) + +#FILES_MATCHING requires CMake 2.6 +IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + INSTALL(TARGETS LinearMath DESTINATION lib) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.h") +ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + +IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(LinearMath PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(LinearMath PROPERTIES PUBLIC_HEADER "${LinearMath_HDRS}") +ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h index 275c4914628..532ce1bf633 100644 --- a/extern/bullet2/src/LinearMath/btAabbUtil2.h +++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h @@ -21,6 +21,8 @@ subject to the following restrictions: #include "btVector3.h" #include "btMinMax.h" + + SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin, btVector3& aabbMax, const btVector3& expansionMin, @@ -30,15 +32,26 @@ SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin, aabbMax = aabbMax + expansionMax; } +/// conservative test for overlap between two aabbs +SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, + const btVector3 &point) +{ + bool overlap = true; + overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap; + overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap; + overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap; + return overlap; +} + /// conservative test for overlap between two aabbs SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, const btVector3 &aabbMin2, const btVector3 &aabbMax2) { 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; + overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap; + overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap; + overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap; return overlap; } @@ -73,6 +86,7 @@ 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], @@ -82,10 +96,10 @@ SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom, 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]; + tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX(); + tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX(); + tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY(); + tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY(); if ( (tmin > tymax) || (tymin > tmax) ) return false; @@ -96,8 +110,8 @@ SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom, if (tymax < tmax) tmax = tymax; - tzmin = (bounds[raySign[2]][2] - rayFrom[2]) * rayInvDirection[2]; - tzmax = (bounds[1-raySign[2]][2] - rayFrom[2]) * rayInvDirection[2]; + tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ(); + tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ(); if ( (tmin > tzmax) || (tzmin > tmax) ) return false; @@ -196,6 +210,26 @@ SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVec aabbMaxOut = center+extent; } +#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(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) + { + 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(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) + { + 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 #endif diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp index e120289e061..a3d790f8abc 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp @@ -19,6 +19,21 @@ int gNumAlignedAllocs = 0; int gNumAlignedFree = 0; int gTotalBytesAlignedAllocs = 0;//detect memory leaks +static void *btAllocDefault(size_t size) +{ + return malloc(size); +} + +static void btFreeDefault(void *ptr) +{ + free(ptr); +} + +static btAllocFunc *sAllocFunc = btAllocDefault; +static btFreeFunc *sFreeFunc = btFreeDefault; + + + #if defined (BT_HAS_ALIGNED_ALLOCATOR) #include static void *btAlignedAllocDefault(size_t size, int alignment) @@ -49,7 +64,7 @@ static inline void *btAlignedAllocDefault(size_t size, int alignment) char *real; unsigned long offset; - real = (char *)malloc(size + sizeof(void *) + (alignment-1)); + real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); if (real) { offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); ret = (void *)((real + sizeof(void *)) + offset); @@ -66,25 +81,14 @@ static inline void btAlignedFreeDefault(void *ptr) if (ptr) { real = *((void **)(ptr)-1); - free(real); + sFreeFunc(real); } } #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) { diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.h b/extern/bullet2/src/LinearMath/btAlignedAllocator.h index a252f324d77..f168f3c66c7 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.h +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.h @@ -38,7 +38,7 @@ void btAlignedFreeInternal (void* ptr,int line,char* filename); void* btAlignedAllocInternal (size_t size, int alignment); void btAlignedFreeInternal (void* ptr); - #define btAlignedAlloc(a,b) btAlignedAllocInternal(a,b) + #define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment) #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) #endif @@ -49,8 +49,11 @@ typedef void (btAlignedFreeFunc)(void *memblock); typedef void *(btAllocFunc)(size_t size); typedef void (btFreeFunc)(void *memblock); -void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc); +///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); +///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it. +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *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. diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h index 5598f0d7236..bad1eee1f63 100644 --- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h +++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h @@ -58,7 +58,7 @@ class btAlignedObjectArray { return (size ? size*2 : 1); } - SIMD_FORCE_INLINE void copy(int start,int end, T* dest) + SIMD_FORCE_INLINE void copy(int start,int end, T* dest) const { int i; for (i=start;iid = m_tris.size(); m_tris.push_back(tr); return tr; } -void HullLibrary::deAllocateTriangle(Tri* tri) +void HullLibrary::deAllocateTriangle(btHullTriangle* tri) { btAssert(m_tris[tri->id]==tri); m_tris[tri->id]=NULL; - tri->~Tri(); + tri->~btHullTriangle(); btAlignedFree(tri); } -void HullLibrary::extrude(Tri *t0,int v) +void HullLibrary::extrude(btHullTriangle *t0,int v) { int3 t= *t0; int n = m_tris.size(); - Tri* ta = allocateTriangle(v,t[1],t[2]); + btHullTriangle* 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]); + btHullTriangle* 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]); + btHullTriangle* 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); @@ -469,10 +469,10 @@ void HullLibrary::extrude(Tri *t0,int v) } -Tri* HullLibrary::extrudable(btScalar epsilon) +btHullTriangle* HullLibrary::extrudable(btScalar epsilon) { int i; - Tri *t=NULL; + btHullTriangle *t=NULL; for(i=0;iriserise)) @@ -550,23 +550,23 @@ int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit) btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0); // a valid interior point - Tri *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=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); + btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1); + btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0); + btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3); + btHullTriangle *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; + btHullTriangle *te; vlimit-=4; while(vlimit >0 && ((te=extrudable(epsilon)) != 0)) { @@ -594,7 +594,7 @@ int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit) 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]]; + btHullTriangle *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]]); diff --git a/extern/bullet2/src/LinearMath/btConvexHull.h b/extern/bullet2/src/LinearMath/btConvexHull.h index 8c36307dfd6..92560bddb9c 100644 --- a/extern/bullet2/src/LinearMath/btConvexHull.h +++ b/extern/bullet2/src/LinearMath/btConvexHull.h @@ -137,13 +137,9 @@ class ConvexH }; ConvexH() { - int i; - i=0; } ~ConvexH() { - int i; - i=0; } btAlignedObjectArray vertices; btAlignedObjectArray edges; @@ -188,7 +184,7 @@ public: class HullLibrary { - btAlignedObjectArray m_tris; + btAlignedObjectArray m_tris; public: @@ -203,15 +199,15 @@ 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); + class btHullTriangle* allocateTriangle(int a,int b,int c); + void deAllocateTriangle(btHullTriangle*); + void b2bfix(btHullTriangle* s,btHullTriangle*t); - void removeb2b(Tri* s,Tri*t); + void removeb2b(btHullTriangle* s,btHullTriangle*t); - void checkit(Tri *t); + void checkit(btHullTriangle *t); - Tri* extrudable(btScalar epsilon); + btHullTriangle* extrudable(btScalar epsilon); int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit); @@ -221,7 +217,7 @@ private: class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice); - void extrude(class Tri* t0,int v); + void extrude(class btHullTriangle* t0,int v); ConvexH* test_cube(); diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h index 563615a9a32..e5a0061b779 100644 --- a/extern/bullet2/src/LinearMath/btIDebugDraw.h +++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h @@ -29,6 +29,7 @@ DEALINGS IN THE SOFTWARE. #define IDEBUG_DRAW__H #include "btVector3.h" +#include "btTransform.h" ///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations. @@ -52,11 +53,26 @@ class btIDebugDraw DBG_EnableSatComparison = 256, DBG_DisableBulletLCP = 512, DBG_EnableCCD = 1024, + DBG_DrawConstraints = (1 << 11), + DBG_DrawConstraintLimits = (1 << 12), DBG_MAX_DEBUG_DRAW_MODE }; virtual ~btIDebugDraw() {}; + virtual void drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor) + { + drawLine (from, to, fromColor); + } + + virtual void drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha) + { + } + + virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color) + { + } + 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) @@ -109,6 +125,171 @@ class btIDebugDraw edgecoord[i]*=-1.f; } } + void drawTransform(const btTransform& transform, btScalar orthoLen) + { + btVector3 start = transform.getOrigin(); + drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(0.7f,0,0)); + drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0,0.7f,0)); + drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0,0,0.7f)); + } + + void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle, + const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f)) + { + const btVector3& vx = axis; + btVector3 vy = normal.cross(axis); + btScalar step = stepDegrees * SIMD_RADS_PER_DEG; + int nSteps = (int)((maxAngle - minAngle) / step); + if(!nSteps) nSteps = 1; + btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle); + if(drawSect) + { + drawLine(center, prev, color); + } + for(int i = 1; i <= nSteps; i++) + { + btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps); + btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle); + drawLine(prev, next, color); + prev = next; + } + if(drawSect) + { + drawLine(center, prev, color); + } + } + void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius, + btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f)) + { + btVector3 vA[74]; + btVector3 vB[74]; + btVector3 *pvA = vA, *pvB = vB, *pT; + btVector3 npole = center + up * radius; + btVector3 spole = center - up * radius; + btVector3 arcStart; + btScalar step = stepDegrees * SIMD_RADS_PER_DEG; + const btVector3& kv = up; + const btVector3& iv = axis; + btVector3 jv = kv.cross(iv); + bool drawN = false; + bool drawS = false; + if(minTh <= -SIMD_HALF_PI) + { + minTh = -SIMD_HALF_PI + step; + drawN = true; + } + if(maxTh >= SIMD_HALF_PI) + { + maxTh = SIMD_HALF_PI - step; + drawS = true; + } + if(minTh > maxTh) + { + minTh = -SIMD_HALF_PI + step; + maxTh = SIMD_HALF_PI - step; + drawN = drawS = true; + } + int n_hor = (int)((maxTh - minTh) / step) + 1; + if(n_hor < 2) n_hor = 2; + btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1); + bool isClosed = false; + if(minPs > maxPs) + { + minPs = -SIMD_PI + step; + maxPs = SIMD_PI; + isClosed = true; + } + else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f)) + { + isClosed = true; + } + else + { + isClosed = false; + } + int n_vert = (int)((maxPs - minPs) / step) + 1; + if(n_vert < 2) n_vert = 2; + btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1); + for(int i = 0; i < n_hor; i++) + { + btScalar th = minTh + btScalar(i) * step_h; + btScalar sth = radius * btSin(th); + btScalar cth = radius * btCos(th); + for(int j = 0; j < n_vert; j++) + { + btScalar psi = minPs + btScalar(j) * step_v; + btScalar sps = btSin(psi); + btScalar cps = btCos(psi); + pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv; + if(i) + { + drawLine(pvA[j], pvB[j], color); + } + else if(drawS) + { + drawLine(spole, pvB[j], color); + } + if(j) + { + drawLine(pvB[j-1], pvB[j], color); + } + else + { + arcStart = pvB[j]; + } + if((i == (n_hor - 1)) && drawN) + { + drawLine(npole, pvB[j], color); + } + if(isClosed) + { + if(j == (n_vert-1)) + { + drawLine(arcStart, pvB[j], color); + } + } + else + { + if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1)))) + { + drawLine(center, pvB[j], color); + } + } + } + pT = pvA; pvA = pvB; pvB = pT; + } + } + + void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color) + { + drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color); + drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + } + void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color) + { + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + } }; diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h index 14aa4ae2348..e45afc3c055 100644 --- a/extern/bullet2/src/LinearMath/btMatrix3x3.h +++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h @@ -23,14 +23,16 @@ subject to the following restrictions: -///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. +/**@brief 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: + /** @brief No initializaion constructor */ btMatrix3x3 () {} // explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); } + /**@brief Constructor from Quaternion */ explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); } /* template @@ -39,6 +41,7 @@ class btMatrix3x3 { setEulerYPR(yaw, pitch, roll); } */ + /** @brief Constructor with row major formatting */ btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz, const btScalar& yx, const btScalar& yy, const btScalar& yz, const btScalar& zx, const btScalar& zy, const btScalar& zz) @@ -47,14 +50,14 @@ class btMatrix3x3 { yx, yy, yz, zx, zy, zz); } - + /** @brief Copy constructor */ SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other) { m_el[0] = other.m_el[0]; m_el[1] = other.m_el[1]; m_el[2] = other.m_el[2]; } - + /** @brief Assignment Operator */ SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other) { m_el[0] = other.m_el[0]; @@ -63,34 +66,45 @@ class btMatrix3x3 { return *this; } + /** @brief Get a column of the matrix as a vector + * @param i Column number 0 indexed */ SIMD_FORCE_INLINE btVector3 getColumn(int i) const { return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]); } - + /** @brief Get a row of the matrix as a vector + * @param i Row number 0 indexed */ SIMD_FORCE_INLINE const btVector3& getRow(int i) const { + btFullAssert(0 <= i && i < 3); return m_el[i]; } - + /** @brief Get a mutable reference to a row of the matrix as a vector + * @param i Row number 0 indexed */ SIMD_FORCE_INLINE btVector3& operator[](int i) { btFullAssert(0 <= i && i < 3); return m_el[i]; } + /** @brief Get a const reference to a row of the matrix as a vector + * @param i Row number 0 indexed */ SIMD_FORCE_INLINE const btVector3& operator[](int i) const { btFullAssert(0 <= i && i < 3); return m_el[i]; } + /** @brief Multiply by the target matrix on the right + * @param m Rotation matrix to be applied + * Equivilant to this = this * m */ btMatrix3x3& operator*=(const btMatrix3x3& m); - + /** @brief Set from a carray of btScalars + * @param m A pointer to the beginning of an array of 9 btScalars */ void setFromOpenGLSubMatrix(const btScalar *m) { m_el[0].setValue(m[0],m[4],m[8]); @@ -98,7 +112,16 @@ class btMatrix3x3 { m_el[2].setValue(m[2],m[6],m[10]); } - + /** @brief Set the values of the matrix explicitly (row major) + * @param xx Top left + * @param xy Top Middle + * @param xz Top Right + * @param yx Middle Left + * @param yy Middle Middle + * @param yz Middle Right + * @param zx Bottom Left + * @param zy Bottom Middle + * @param zz Bottom Right*/ void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz, const btScalar& yx, const btScalar& yy, const btScalar& yz, const btScalar& zx, const btScalar& zy, const btScalar& zz) @@ -107,7 +130,9 @@ class btMatrix3x3 { m_el[1].setValue(yx,yy,yz); m_el[2].setValue(zx,zy,zz); } - + + /** @brief Set the matrix from a quaternion + * @param q The Quaternion to match */ void setRotation(const btQuaternion& q) { btScalar d = q.length2(); @@ -123,35 +148,27 @@ class btMatrix3x3 { } - + /** @brief Set the matrix from euler angles using YPR around YXZ respectively + * @param yaw Yaw about Y axis + * @param pitch Pitch about X axis + * @param roll Roll about Z axis + */ void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) { - - btScalar cy(btCos(yaw)); - btScalar sy(btSin(yaw)); - btScalar cp(btCos(pitch)); - btScalar sp(btSin(pitch)); - btScalar cr(btCos(roll)); - btScalar sr(btSin(roll)); - btScalar cc = cy * cr; - btScalar cs = cy * sr; - btScalar sc = sy * cr; - btScalar ss = sy * sr; - setValue(cc - sp * ss, -cs - sp * sc, -sy * cp, - cp * sr, cp * cr, -sp, - sc + sp * cs, -ss + sp * cc, cy * cp); - + setEulerZYX(roll, pitch, yaw); } - /** - * setEulerZYX - * @param euler a const reference to a btVector3 of euler angles + /** @brief Set the matrix from euler angles YPR around ZYX axes + * @param eulerX Roll about X axis + * @param eulerY Pitch around Y axis + * @param eulerZ Yaw aboud Z axis + * * These angles are used to produce a rotation matrix. The euler * angles are applied in ZYX order. I.e a vector is first rotated * about X then Y and then Z **/ - - void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) { + void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) { + ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code btScalar ci ( btCos(eulerX)); btScalar cj ( btCos(eulerY)); btScalar ch ( btCos(eulerZ)); @@ -168,13 +185,24 @@ class btMatrix3x3 { -sj, cj * si, cj * ci); } + /**@brief Set the matrix to the identity */ void setIdentity() { setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0), btScalar(0.0), btScalar(1.0), btScalar(0.0), btScalar(0.0), btScalar(0.0), btScalar(1.0)); } - + + static const btMatrix3x3& getIdentity() + { + static const btMatrix3x3 identityMatrix(btScalar(1.0), btScalar(0.0), btScalar(0.0), + btScalar(0.0), btScalar(1.0), btScalar(0.0), + btScalar(0.0), btScalar(0.0), btScalar(1.0)); + return identityMatrix; + } + + /**@brief Fill the values of the matrix into a 9 element array + * @param m The array to be filled */ void getOpenGLSubMatrix(btScalar *m) const { m[0] = btScalar(m_el[0].x()); @@ -191,6 +219,8 @@ class btMatrix3x3 { m[11] = btScalar(0.0); } + /**@brief Get the matrix represented as a quaternion + * @param q The quaternion which will be set */ void getRotation(btQuaternion& q) const { btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z(); @@ -224,35 +254,102 @@ class btMatrix3x3 { } q.setValue(temp[0],temp[1],temp[2],temp[3]); } - - void getEuler(btScalar& yaw, btScalar& pitch, btScalar& roll) const + + /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR + * @param yaw Yaw around Y axis + * @param pitch Pitch around X axis + * @param roll around Z axis */ + void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const { - if (btScalar(m_el[1].z()) < btScalar(1)) - { - if (btScalar(m_el[1].z()) > -btScalar(1)) - { - yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x())); - pitch = btScalar(btAsin(-m_el[1].y())); - roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z())); - } - else - { - yaw = btScalar(-btAtan2(-m_el[0].y(), m_el[0].z())); - pitch = SIMD_HALF_PI; - roll = btScalar(0.0); - } - } - else - { - yaw = btScalar(btAtan2(-m_el[0].y(), m_el[0].z())); - pitch = -SIMD_HALF_PI; - roll = btScalar(0.0); - } - } - + // first use the normal calculus + yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x())); + pitch = btScalar(btAsin(-m_el[2].x())); + roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z())); + // on pitch = +/-HalfPI + if (btFabs(pitch)==SIMD_HALF_PI) + { + if (yaw>0) + yaw-=SIMD_PI; + else + yaw+=SIMD_PI; + + if (roll>0) + roll-=SIMD_PI; + else + roll+=SIMD_PI; + } + }; + + + /**@brief Get the matrix represented as euler angles around ZYX + * @param yaw Yaw around X axis + * @param pitch Pitch around Y axis + * @param roll around X axis + * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/ + void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const + { + struct Euler{btScalar yaw, pitch, roll;}; + Euler euler_out; + Euler euler_out2; //second solution + //get the pointer to the raw data + + // Check that pitch is not at a singularity + if (btFabs(m_el[2].x()) >= 1) + { + euler_out.yaw = 0; + euler_out2.yaw = 0; + // From difference of angles formula + btScalar delta = btAtan2(m_el[0].x(),m_el[0].z()); + if (m_el[2].x() > 0) //gimbal locked up + { + euler_out.pitch = SIMD_PI / btScalar(2.0); + euler_out2.pitch = SIMD_PI / btScalar(2.0); + euler_out.roll = euler_out.pitch + delta; + euler_out2.roll = euler_out.pitch + delta; + } + else // gimbal locked down + { + euler_out.pitch = -SIMD_PI / btScalar(2.0); + euler_out2.pitch = -SIMD_PI / btScalar(2.0); + euler_out.roll = -euler_out.pitch + delta; + euler_out2.roll = -euler_out.pitch + delta; + } + } + else + { + euler_out.pitch = - btAsin(m_el[2].x()); + euler_out2.pitch = SIMD_PI - euler_out.pitch; + + euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch), + m_el[2].z()/btCos(euler_out.pitch)); + euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch), + m_el[2].z()/btCos(euler_out2.pitch)); + + euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch), + m_el[0].x()/btCos(euler_out.pitch)); + euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch), + m_el[0].x()/btCos(euler_out2.pitch)); + } + + if (solution_number == 1) + { + yaw = euler_out.yaw; + pitch = euler_out.pitch; + roll = euler_out.roll; + } + else + { + yaw = euler_out2.yaw; + pitch = euler_out2.pitch; + roll = euler_out2.roll; + } + } + + /**@brief Create a scaled copy of the matrix + * @param s Scaling vector The elements of the vector will scale each column */ btMatrix3x3 scaled(const btVector3& s) const { @@ -261,10 +358,15 @@ class btMatrix3x3 { m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z()); } + /**@brief Return the determinant of the matrix */ btScalar determinant() const; + /**@brief Return the adjoint of the matrix */ btMatrix3x3 adjoint() const; + /**@brief Return the matrix with all values non negative */ btMatrix3x3 absolute() const; + /**@brief Return the transpose of the matrix */ btMatrix3x3 transpose() const; + /**@brief Return the inverse of the matrix */ btMatrix3x3 inverse() const; btMatrix3x3 transposeTimes(const btMatrix3x3& m) const; @@ -284,12 +386,15 @@ 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. + /**@brief diagonalizes this matrix by the Jacobi method. + * @param 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. + * @param threshold See iteration + * @param iteration 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(); @@ -371,11 +476,18 @@ class btMatrix3x3 { protected: + /**@brief Calculate the matrix cofactor + * @param r1 The first row to use for calculating the cofactor + * @param c1 The first column to use for calculating the cofactor + * @param r1 The second row to use for calculating the cofactor + * @param c1 The second column to use for calculating the cofactor + * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details + */ btScalar cofac(int r1, int c1, int r2, int c2) const { return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1]; } - + ///Data storage for the matrix, each vector is a row of the matrix btVector3 m_el[3]; }; @@ -494,6 +606,8 @@ class btMatrix3x3 { } */ +/**@brief Equality operator between two matrices + * It will test all elements are equal. */ 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] && diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h index 2e80fc2ca47..c657afd2bb1 100644 --- a/extern/bullet2/src/LinearMath/btQuadWord.h +++ b/extern/bullet2/src/LinearMath/btQuadWord.h @@ -18,121 +18,159 @@ subject to the following restrictions: #include "btScalar.h" #include "btMinMax.h" -#include +#if defined (__CELLOS_LV2) && defined (__SPU__) +#include +#endif -///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 +/**@brief The btQuadWord 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. + */ +#ifndef USE_LIBSPE2 +ATTRIBUTE_ALIGNED16(class) btQuadWord +#else +class btQuadWord +#endif { protected: - btScalar m_x; - btScalar m_y; - btScalar m_z; - btScalar m_unusedW; - +#if defined (__SPU__) && defined (__CELLOS_LV2__) + union { + vec_float4 mVec128; + btScalar m_floats[4]; + }; public: + vec_float4 get128() const + { + return mVec128; + } +protected: +#else //__CELLOS_LV2__ __SPU__ + btScalar m_floats[4]; +#endif //__CELLOS_LV2__ __SPU__ -}; - - -///btQuadWord is base-class for vectors, points -class btQuadWord : public btQuadWordStorage -{ public: - -// SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; } -// SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_x)[i]; } + - SIMD_FORCE_INLINE const btScalar& getX() const { return m_x; } + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; } + /**@brief Set the x value */ + SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;}; + /**@brief Set the y value */ + SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;}; + /**@brief Set the z value */ + SIMD_FORCE_INLINE void setZ(btScalar z) { m_floats[2] = z;}; + /**@brief Set the w value */ + SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;}; + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; } + /**@brief Return the w value */ + SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; } - SIMD_FORCE_INLINE const btScalar& getY() const { return m_y; } - - SIMD_FORCE_INLINE const btScalar& getZ() const { return m_z; } - - SIMD_FORCE_INLINE void setX(btScalar x) { m_x = x;}; - - SIMD_FORCE_INLINE void setY(btScalar y) { m_y = y;}; - - SIMD_FORCE_INLINE void setZ(btScalar z) { m_z = z;}; - - SIMD_FORCE_INLINE void setW(btScalar w) { m_unusedW = w;}; - - SIMD_FORCE_INLINE const btScalar& x() const { return m_x; } - - SIMD_FORCE_INLINE const btScalar& y() const { return m_y; } - - SIMD_FORCE_INLINE const btScalar& z() const { return m_z; } - - SIMD_FORCE_INLINE const btScalar& w() const { return m_unusedW; } - - - SIMD_FORCE_INLINE operator btScalar *() { return &m_x; } - SIMD_FORCE_INLINE operator const btScalar *() const { return &m_x; } + //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; } + //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; } + ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons. + SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; } + SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; } + SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const + { + return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0])); + } + SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const + { + return !(*this == other); + } + /**@brief Set x,y,z and zero w + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) { - m_x=x; - m_y=y; - m_z=z; - m_unusedW = 0.f; + m_floats[0]=x; + m_floats[1]=y; + m_floats[2]=z; + m_floats[3] = 0.f; } /* void getValue(btScalar *m) const { - m[0] = m_x; - m[1] = m_y; - m[2] = m_z; + m[0] = m_floats[0]; + m[1] = m_floats[1]; + m[2] = m_floats[2]; } */ +/**@brief Set the values + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ SIMD_FORCE_INLINE void setValue(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_floats[0]=x; + m_floats[1]=y; + m_floats[2]=z; + m_floats[3]=w; } - + /**@brief No initialization constructor */ SIMD_FORCE_INLINE btQuadWord() - // :m_x(btScalar(0.)),m_y(btScalar(0.)),m_z(btScalar(0.)),m_unusedW(btScalar(0.)) + // :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.)) { } - - SIMD_FORCE_INLINE btQuadWord(const btQuadWordStorage& q) - { - *((btQuadWordStorage*)this) = q; - } - + + /**@brief Three argument constructor (zeros w) + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ 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; + m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = 0.0f; } +/**@brief Initializing constructor + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ 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_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = w; } - + /**@brief Set each element to the max of the current values and the values of another btQuadWord + * @param other The other btQuadWord to compare with + */ 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); + btSetMax(m_floats[0], other.m_floats[0]); + btSetMax(m_floats[1], other.m_floats[1]); + btSetMax(m_floats[2], other.m_floats[2]); + btSetMax(m_floats[3], other.m_floats[3]); } - + /**@brief Set each element to the min of the current values and the values of another btQuadWord + * @param other The other btQuadWord to compare with + */ 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); + btSetMin(m_floats[0], other.m_floats[0]); + btSetMin(m_floats[1], other.m_floats[1]); + btSetMin(m_floats[2], other.m_floats[2]); + btSetMin(m_floats[3], other.m_floats[3]); } diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h index 264751b33e7..cbeca2681cc 100644 --- a/extern/bullet2/src/LinearMath/btQuaternion.h +++ b/extern/bullet2/src/LinearMath/btQuaternion.h @@ -17,39 +17,56 @@ subject to the following restrictions: #ifndef SIMD__QUATERNION_H_ #define SIMD__QUATERNION_H_ -#include "btVector3.h" -///The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. +#include "btVector3.h" +#include "btQuadWord.h" + +/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */ class btQuaternion : public btQuadWord { public: + /**@brief No initialization constructor */ btQuaternion() {} // template // explicit Quaternion(const btScalar *v) : Tuple4(v) {} - + /**@brief Constructor from scalars */ btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w) : btQuadWord(x, y, z, w) {} - + /**@brief Axis angle Constructor + * @param axis The axis which the rotation is around + * @param angle The magnitude of the rotation around the angle (Radians) */ btQuaternion(const btVector3& axis, const btScalar& angle) { setRotation(axis, angle); } - + /**@brief Constructor from Euler angles + * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z + * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y + * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */ btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) { +#ifndef BT_EULER_DEFAULT_ZYX setEuler(yaw, pitch, roll); +#else + setEulerZYX(yaw, pitch, roll); +#endif } - + /**@brief Set the rotation using axis angle notation + * @param axis The axis around which to rotate + * @param angle The magnitude of the rotation in Radians */ void setRotation(const btVector3& axis, const btScalar& angle) { btScalar d = axis.length(); - assert(d != btScalar(0.0)); + btAssert(d != btScalar(0.0)); btScalar s = btSin(angle * btScalar(0.5)) / d; setValue(axis.x() * s, axis.y() * s, axis.z() * s, btCos(angle * btScalar(0.5))); } - + /**@brief Set the quaternion using Euler angles + * @param yaw Angle around Y + * @param pitch Angle around X + * @param roll Angle around Z */ void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) { btScalar halfYaw = btScalar(yaw) * btScalar(0.5); @@ -66,122 +83,165 @@ public: sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); } - - btQuaternion& operator+=(const btQuaternion& q) + /**@brief Set the quaternion using euler angles + * @param yaw Angle around Z + * @param pitch Angle around Y + * @param roll Angle around X */ + void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) { - m_x += q.x(); m_y += q.y(); m_z += q.z(); m_unusedW += q.m_unusedW; + btScalar halfYaw = btScalar(yaw) * btScalar(0.5); + btScalar halfPitch = btScalar(pitch) * btScalar(0.5); + btScalar halfRoll = btScalar(roll) * btScalar(0.5); + btScalar cosYaw = btCos(halfYaw); + btScalar sinYaw = btSin(halfYaw); + btScalar cosPitch = btCos(halfPitch); + btScalar sinPitch = btSin(halfPitch); + btScalar cosRoll = btCos(halfRoll); + btScalar sinRoll = btSin(halfRoll); + setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x + cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y + cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z + cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx + } + /**@brief Add two quaternions + * @param q The quaternion to add to this one */ + SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q) + { + m_floats[0] += q.x(); m_floats[1] += q.y(); m_floats[2] += q.z(); m_floats[3] += q.m_floats[3]; return *this; } + /**@brief Subtract out a quaternion + * @param q The quaternion to subtract from this one */ btQuaternion& operator-=(const btQuaternion& q) { - m_x -= q.x(); m_y -= q.y(); m_z -= q.z(); m_unusedW -= q.m_unusedW; + m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3]; return *this; } + /**@brief Scale this quaternion + * @param s The scalar to scale by */ btQuaternion& operator*=(const btScalar& s) { - m_x *= s; m_y *= s; m_z *= s; m_unusedW *= s; + m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s; return *this; } - + /**@brief Multiply this quaternion by q on the right + * @param q The other quaternion + * Equivilant to this = this * q */ btQuaternion& operator*=(const btQuaternion& q) { - setValue(m_unusedW * q.x() + m_x * q.m_unusedW + m_y * q.z() - m_z * q.y(), - m_unusedW * q.y() + m_y * q.m_unusedW + m_z * q.x() - m_x * q.z(), - m_unusedW * q.z() + m_z * q.m_unusedW + m_x * q.y() - m_y * q.x(), - m_unusedW * q.m_unusedW - m_x * q.x() - m_y * q.y() - m_z * q.z()); + setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(), + m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(), + m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(), + m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z()); return *this; } - + /**@brief Return the dot product between this quaternion and another + * @param q The other quaternion */ btScalar dot(const btQuaternion& q) const { - return m_x * q.x() + m_y * q.y() + m_z * q.z() + m_unusedW * q.m_unusedW; + return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3]; } + /**@brief Return the length squared of the quaternion */ btScalar length2() const { return dot(*this); } + /**@brief Return the length of the quaternion */ btScalar length() const { return btSqrt(length2()); } + /**@brief Normalize the quaternion + * Such that x^2 + y^2 + z^2 +w^2 = 1 */ btQuaternion& normalize() { return *this /= length(); } + /**@brief Return a scaled version of this quaternion + * @param s The scale factor */ SIMD_FORCE_INLINE btQuaternion operator*(const btScalar& s) const { - return btQuaternion(x() * s, y() * s, z() * s, m_unusedW * s); + return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s); } - + /**@brief Return an inversely scaled versionof this quaternion + * @param s The inverse scale factor */ btQuaternion operator/(const btScalar& s) const { - assert(s != btScalar(0.0)); + btAssert(s != btScalar(0.0)); return *this * (btScalar(1.0) / s); } - + /**@brief Inversely scale this quaternion + * @param s The scale factor */ btQuaternion& operator/=(const btScalar& s) { - assert(s != btScalar(0.0)); + btAssert(s != btScalar(0.0)); return *this *= btScalar(1.0) / s; } - + /**@brief Return a normalized version of this quaternion */ btQuaternion normalized() const { return *this / length(); } - + /**@brief Return the angle between this quaternion and the other + * @param q The other quaternion */ btScalar angle(const btQuaternion& q) const { btScalar s = btSqrt(length2() * q.length2()); - assert(s != btScalar(0.0)); + btAssert(s != btScalar(0.0)); return btAcos(dot(q) / s); } - + /**@brief Return the angle of rotation represented by this quaternion */ btScalar getAngle() const { - btScalar s = btScalar(2.) * btAcos(m_unusedW); + btScalar s = btScalar(2.) * btAcos(m_floats[3]); return s; } - + /**@brief Return the inverse of this quaternion */ btQuaternion inverse() const { - return btQuaternion(-m_x, -m_y, -m_z, m_unusedW); + return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]); } + /**@brief Return the sum of this quaternion and the other + * @param q2 The other quaternion */ SIMD_FORCE_INLINE btQuaternion operator+(const btQuaternion& q2) const { const btQuaternion& q1 = *this; - return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_unusedW + q2.m_unusedW); + return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]); } + /**@brief Return the difference between this quaternion and the other + * @param q2 The other quaternion */ SIMD_FORCE_INLINE btQuaternion operator-(const btQuaternion& q2) const { const btQuaternion& q1 = *this; - return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_unusedW - q2.m_unusedW); + return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]); } + /**@brief Return the negative of this quaternion + * This simply negates each element */ SIMD_FORCE_INLINE btQuaternion operator-() const { const btQuaternion& q2 = *this; - return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_unusedW); + return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_floats[3]); } - + /**@todo document this and it's use */ SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const { btQuaternion diff,sum; @@ -192,6 +252,10 @@ public: return (-qd); } + /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion + * @param q The other quaternion to interpolate with + * @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q. + * Slerp interpolates assuming constant velocity. */ btQuaternion slerp(const btQuaternion& q, const btScalar& t) const { btScalar theta = angle(q); @@ -200,10 +264,10 @@ public: btScalar d = btScalar(1.0) / btSin(theta); btScalar s0 = btSin((btScalar(1.0) - t) * theta); btScalar s1 = btSin(t * theta); - return btQuaternion((m_x * s0 + q.x() * s1) * d, - (m_y * s0 + q.y() * s1) * d, - (m_z * s0 + q.z() * s1) * d, - (m_unusedW * s0 + q.m_unusedW * s1) * d); + return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d, + (m_floats[1] * s0 + q.y() * s1) * d, + (m_floats[2] * s0 + q.z() * s1) * d, + (m_floats[3] * s0 + q.m_floats[3] * s1) * d); } else { @@ -211,13 +275,19 @@ public: } } - SIMD_FORCE_INLINE const btScalar& getW() const { return m_unusedW; } + static const btQuaternion& getIdentity() + { + static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.)); + return identityQuat; + } + + SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; } }; - +/**@brief Return the negative of a quaternion */ SIMD_FORCE_INLINE btQuaternion operator-(const btQuaternion& q) { @@ -226,7 +296,7 @@ operator-(const btQuaternion& q) - +/**@brief Return the product of two quaternions */ SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q1, const btQuaternion& q2) { return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(), @@ -253,6 +323,7 @@ operator*(const btVector3& w, const btQuaternion& q) -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); } +/**@brief Calculate the dot product between two quaternions */ SIMD_FORCE_INLINE btScalar dot(const btQuaternion& q1, const btQuaternion& q2) { @@ -260,25 +331,32 @@ dot(const btQuaternion& q1, const btQuaternion& q2) } +/**@brief Return the length of a quaternion */ SIMD_FORCE_INLINE btScalar length(const btQuaternion& q) { return q.length(); } +/**@brief Return the angle between two quaternions*/ SIMD_FORCE_INLINE btScalar angle(const btQuaternion& q1, const btQuaternion& q2) { return q1.angle(q2); } - +/**@brief Return the inverse of a quaternion*/ SIMD_FORCE_INLINE btQuaternion inverse(const btQuaternion& q) { return q.inverse(); } +/**@brief Return the result of spherical linear interpolation betwen two quaternions + * @param q1 The first quaternion + * @param q2 The second quaternion + * @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2 + * Slerp assumes constant velocity between positions. */ SIMD_FORCE_INLINE btQuaternion slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) { diff --git a/extern/bullet2/src/LinearMath/btQuickprof.cpp b/extern/bullet2/src/LinearMath/btQuickprof.cpp index e5b1196149b..fa45d02b3d3 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.cpp +++ b/extern/bullet2/src/LinearMath/btQuickprof.cpp @@ -110,7 +110,7 @@ void CProfileNode::Reset( void ) { TotalCalls = 0; TotalTime = 0.0f; - gProfileClock.reset(); + if ( Child ) { Child->Reset(); @@ -251,6 +251,7 @@ void CProfileManager::Stop_Profile( void ) *=============================================================================================*/ void CProfileManager::Reset( void ) { + gProfileClock.reset(); Root.Reset(); Root.Call(); FrameCounter = 0; @@ -278,5 +279,68 @@ float CProfileManager::Get_Time_Since_Reset( void ) return (float)time / Profile_Get_Tick_Rate(); } +#include + +void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing) +{ + profileIterator->First(); + if (profileIterator->Is_Done()) + return; + + float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time(); + int i; + int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset(); + for (i=0;iGet_Current_Parent_Name(), parent_time ); + float totalTime = 0.f; + + + int numChildren = 0; + + for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next()) + { + numChildren++; + float current_total_time = profileIterator->Get_Current_Total_Time(); + accumulated_time += current_total_time; + float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f; + { + int i; for (i=0;iGet_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls()); + totalTime += current_total_time; + //recurse into children + } + + if (parent_time < accumulated_time) + { + printf("what's wrong\n"); + } + for (i=0;i SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time); + + for (i=0;iEnter_Child(i); + dumpRecursive(profileIterator,spacing+3); + profileIterator->Enter_Parent(); + } +} + + + +void CProfileManager::dumpAll() +{ + CProfileIterator* profileIterator = 0; + profileIterator = CProfileManager::Get_Iterator(); + + dumpRecursive(profileIterator,0); + + CProfileManager::Release_Iterator(profileIterator); +} + + + #endif //USE_BT_CLOCK diff --git a/extern/bullet2/src/LinearMath/btQuickprof.h b/extern/bullet2/src/LinearMath/btQuickprof.h index b033940ca5c..f8d47c36861 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.h +++ b/extern/bullet2/src/LinearMath/btQuickprof.h @@ -10,14 +10,20 @@ // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). + + #ifndef QUICK_PROF_H #define QUICK_PROF_H +//To disable built-in profiling, please comment out next line +//#define BT_NO_PROFILE 1 +#ifndef BT_NO_PROFILE + #include "btScalar.h" #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 @@ -321,6 +327,10 @@ public: } static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } + static void dumpRecursive(CProfileIterator* profileIterator, int spacing); + + static void dumpAll(); + private: static CProfileNode Root; static CProfileNode * CurrentNode; @@ -344,12 +354,14 @@ public: } }; -#if !defined(BT_NO_PROFILE) -#define BT_PROFILE( name ) CProfileSample __profile( name ) -#else -#define BT_PROFILE( name ) -#endif +#define BT_PROFILE( name ) CProfileSample __profile( name ) + +#else + +#define BT_PROFILE( name ) + +#endif //#ifndef BT_NO_PROFILE diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h index e8433405b20..822296164c1 100644 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -18,13 +18,14 @@ 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 +#define BT_BULLET_VERSION 274 inline int btGetVersion() { @@ -44,7 +45,7 @@ inline int btGetVersion() #define ATTRIBUTE_ALIGNED16(a) a #define ATTRIBUTE_ALIGNED128(a) a #else - #define BT_HAS_ALIGNED_ALLOCATOR + //#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 @@ -60,12 +61,18 @@ inline int btGetVersion() #define BT_HAVE_NATIVE_FSEL #define btFsel(a,b,c) __fsel((a),(b),(c)) #else + +#if (defined (WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION)) #define BT_USE_SSE - #endif + #include +#endif + + #endif//_XBOX + #endif //__MINGW32__ #include -#if defined(DEBUG) || defined (_DEBUG) +#ifdef BT_DEBUG #define btAssert assert #else #define btAssert(x) @@ -85,7 +92,11 @@ inline int btGetVersion() #ifndef assert #include #endif +#ifdef BT_DEBUG #define btAssert assert +#else + #define btAssert(x) +#endif //btFullAssert is optional, slows down a lot #define btFullAssert(x) @@ -102,7 +113,11 @@ inline int btGetVersion() #ifndef assert #include #endif +#ifdef BT_DEBUG #define btAssert assert +#else + #define btAssert(x) +#endif //btFullAssert is optional, slows down a lot #define btFullAssert(x) @@ -115,6 +130,9 @@ inline int btGetVersion() //non-windows systems #define SIMD_FORCE_INLINE inline + ///@todo: check out alignment methods for other platforms/compilers + ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) #define ATTRIBUTE_ALIGNED16(a) a #define ATTRIBUTE_ALIGNED128(a) a #ifndef assert @@ -141,10 +159,6 @@ inline int btGetVersion() /// older compilers (gcc 3.x) and Sun needs double version of sqrt etc. /// exclude Apple Intel (i's assumed to be a Macbook or new Intel Dual Core Processor) #if defined (__sun) || defined (__sun__) || defined (__sparc) || (defined (__APPLE__) && ! defined (__i386__)) -/* XXX Need to fix these... needed for SunOS 5.8 */ -#define sinf(a) sin((double)(a)) -#define cosf(a) cos((double)(a)) -#define fabsf(a) fabs((double)(a)) //use slow double float precision operation on those platforms #ifndef BT_USE_DOUBLE_PRECISION #define BT_FORCE_DOUBLE_FUNCTIONS @@ -198,7 +212,7 @@ SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) tempf = y; *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ x = tempf; - z = y*btScalar(0.5); /* hoist out the ô/2ö */ + 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); diff --git a/extern/bullet2/src/LinearMath/btStackAlloc.h b/extern/bullet2/src/LinearMath/btStackAlloc.h index 050d44bdfe9..397b084877f 100644 --- a/extern/bullet2/src/LinearMath/btStackAlloc.h +++ b/extern/bullet2/src/LinearMath/btStackAlloc.h @@ -23,6 +23,7 @@ Nov.2006 #include "btScalar.h" //for btAssert #include "btAlignedAllocator.h" +///The btBlock class is an internal structure for the btStackAlloc memory allocator. struct btBlock { btBlock* previous; diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h index a8cdb428100..c4fe33eecd7 100644 --- a/extern/bullet2/src/LinearMath/btTransform.h +++ b/extern/bullet2/src/LinearMath/btTransform.h @@ -21,34 +21,39 @@ 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. +/**@brief 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 { public: - + /**@brief No initialization constructor */ btTransform() {} - + /**@brief Constructor from btQuaternion (optional btVector3 ) + * @param q Rotation from quaternion + * @param c Translation from Vector (default 0,0,0) */ explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q, const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) : m_basis(q), m_origin(c) {} + /**@brief Constructor from btMatrix3x3 (optional btVector3) + * @param b Rotation from Matrix + * @param c Translation from Vector default (0,0,0)*/ explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b, const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) : m_basis(b), m_origin(c) {} - + /**@brief Copy constructor */ SIMD_FORCE_INLINE btTransform (const btTransform& other) : m_basis(other.m_basis), m_origin(other.m_origin) { } - + /**@brief Assignment Operator */ SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other) { m_basis = other.m_basis; @@ -57,6 +62,10 @@ public: } + /**@brief Set the current transform as the value of the product of two transforms + * @param t1 Transform 1 + * @param t2 Transform 2 + * This = Transform1 * Transform2 */ SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) { m_basis = t1.m_basis * t2.m_basis; m_origin = t1(t2.m_origin); @@ -69,7 +78,7 @@ public: } */ - +/**@brief Return the transform of the vector */ SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const { return btVector3(m_basis[0].dot(x) + m_origin.x(), @@ -77,17 +86,29 @@ public: m_basis[2].dot(x) + m_origin.z()); } + /**@brief Return the transform of the vector */ SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const { return (*this)(x); } + /**@brief Return the transform of the btQuaternion */ + SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const + { + return getRotation() * q; + } + + /**@brief Return the basis matrix for the rotation */ SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; } + /**@brief Return the basis matrix for the rotation */ SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; } + /**@brief Return the origin vector translation */ SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; } + /**@brief Return the origin vector translation */ SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; } + /**@brief Return a quaternion representing the rotation */ btQuaternion getRotation() const { btQuaternion q; m_basis.getRotation(q); @@ -95,12 +116,16 @@ public: } + /**@brief Set from an array + * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */ void setFromOpenGLMatrix(const btScalar *m) { m_basis.setFromOpenGLSubMatrix(m); m_origin.setValue(m[12],m[13],m[14]); } + /**@brief Fill an array representation + * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */ void getOpenGLMatrix(btScalar *m) const { m_basis.getOpenGLSubMatrix(m); @@ -110,6 +135,8 @@ public: m[15] = btScalar(1.0); } + /**@brief Set the translational element + * @param origin The vector to set the translation to */ SIMD_FORCE_INLINE void setOrigin(const btVector3& origin) { m_origin = origin; @@ -118,26 +145,28 @@ public: SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const; - + /**@brief Set the rotational element by btMatrix3x3 */ SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis) { m_basis = basis; } + /**@brief Set the rotational element by btQuaternion */ SIMD_FORCE_INLINE void setRotation(const btQuaternion& q) { m_basis.setRotation(q); } - + /**@brief Set this transformation to the identity */ void setIdentity() { m_basis.setIdentity(); m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); } - + /**@brief Multiply this Transform by another(this = this * another) + * @param t The other transform */ btTransform& operator*=(const btTransform& t) { m_origin += m_basis * t.m_origin; @@ -145,26 +174,32 @@ public: return *this; } + /**@brief Return the inverse of this transform */ btTransform inverse() const { btMatrix3x3 inv = m_basis.transpose(); return btTransform(inv, inv * -m_origin); } + /**@brief Return the inverse of this transform times the other transform + * @param t The other transform + * return this.inverse() * the other */ btTransform inverseTimes(const btTransform& t) const; + /**@brief Return the product of this transform and the other */ btTransform operator*(const btTransform& t) const; - static btTransform getIdentity() + /**@brief Return an identity transform */ + static const btTransform& getIdentity() { - btTransform tr; - tr.setIdentity(); - return tr; + static const btTransform identityTransform(btMatrix3x3::getIdentity()); + return identityTransform; } private: - + ///Storage for the rotation btMatrix3x3 m_basis; + ///Storage for the translation btVector3 m_origin; }; @@ -191,6 +226,7 @@ btTransform::operator*(const btTransform& t) const (*this)(t.m_origin)); } +/**@brief Test if two transforms have all elements equal */ SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2) { return ( t1.getBasis() == t2.getBasis() && diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h index 86ee1da5edf..e8328da4ca6 100644 --- a/extern/bullet2/src/LinearMath/btTransformUtil.h +++ b/extern/bullet2/src/LinearMath/btTransformUtil.h @@ -100,6 +100,38 @@ public: predictedTransform.setRotation(predictedOrn); } + static void calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel) + { + linVel = (pos1 - pos0) / timeStep; + btVector3 axis; + btScalar angle; + if (orn0 != orn1) + { + calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle); + angVel = axis * angle / timeStep; + } else + { + angVel.setValue(0,0,0); + } + } + + static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle) + { + btQuaternion orn1 = orn0.farthest(orn1a); + btQuaternion dorn = orn1 * orn0.inverse(); + ///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.); + //check for axis length + btScalar len = axis.length2(); + if (len < SIMD_EPSILON*SIMD_EPSILON) + axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.)); + else + axis /= btSqrt(len); + } + static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel) { linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep; @@ -111,20 +143,11 @@ public: static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle) { - - #ifdef USE_QUATERNION_DIFF - btQuaternion orn0 = transform0.getRotation(); - btQuaternion orn1a = transform1.getRotation(); - btQuaternion orn1 = orn0.farthest(orn1a); - btQuaternion dorn = orn1 * orn0.inverse(); -#else btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse(); btQuaternion dorn; dmat.getRotation(dorn); -#endif//USE_QUATERNION_DIFF - - ///floating point inaccuracy can lead to w component > 1..., which breaks + ///floating point inaccuracy can lead to w component > 1..., which breaks dorn.normalize(); angle = dorn.getAngle(); @@ -140,5 +163,85 @@ public: }; + +///The btConvexSeparatingDistanceUtil can help speed up convex collision detection +///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance +class btConvexSeparatingDistanceUtil +{ + btQuaternion m_ornA; + btQuaternion m_ornB; + btVector3 m_posA; + btVector3 m_posB; + + btVector3 m_separatingNormal; + + btScalar m_boundingRadiusA; + btScalar m_boundingRadiusB; + btScalar m_separatingDistance; + +public: + + btConvexSeparatingDistanceUtil(btScalar boundingRadiusA,btScalar boundingRadiusB) + :m_boundingRadiusA(boundingRadiusA), + m_boundingRadiusB(boundingRadiusB), + m_separatingDistance(0.f) + { + } + + btScalar getConservativeSeparatingDistance() + { + return m_separatingDistance; + } + + void updateSeparatingDistance(const btTransform& transA,const btTransform& transB) + { + const btVector3& toPosA = transA.getOrigin(); + const btVector3& toPosB = transB.getOrigin(); + btQuaternion toOrnA = transA.getRotation(); + btQuaternion toOrnB = transB.getRotation(); + + if (m_separatingDistance>0.f) + { + + + btVector3 linVelA,angVelA,linVelB,angVelB; + btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA); + btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB); + btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB; + btVector3 relLinVel = (linVelB-linVelA); + btScalar relLinVelocLength = (linVelB-linVelA).dot(m_separatingNormal); + if (relLinVelocLength<0.f) + { + relLinVelocLength = 0.f; + } + + btScalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength; + m_separatingDistance -= projectedMotion; + } + + m_posA = toPosA; + m_posB = toPosB; + m_ornA = toOrnA; + m_ornB = toOrnB; + } + + void initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB) + { + m_separatingNormal = separatingVector; + m_separatingDistance = separatingDistance; + + const btVector3& toPosA = transA.getOrigin(); + const btVector3& toPosB = transB.getOrigin(); + btQuaternion toOrnA = transA.getRotation(); + btQuaternion toOrnB = transB.getRotation(); + m_posA = toPosA; + m_posB = toPosB; + m_ornA = toOrnA; + m_ornB = toOrnB; + } + +}; + + #endif //SIMD_TRANSFORM_UTIL_H diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h index 96548c6ba60..5d5c39e8587 100644 --- a/extern/bullet2/src/LinearMath/btVector3.h +++ b/extern/bullet2/src/LinearMath/btVector3.h @@ -17,127 +17,190 @@ subject to the following restrictions: #ifndef SIMD__VECTOR3_H #define SIMD__VECTOR3_H -#include "btQuadWord.h" -///btVector3 can be used to represent 3D points and vectors. -///It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user -///Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers -class btVector3 : public btQuadWord { +#include "btScalar.h" +#include "btScalar.h" +#include "btMinMax.h" +/**@brief btVector3 can be used to represent 3D points and vectors. + * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user + * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers + */ +ATTRIBUTE_ALIGNED16(class) btVector3 +{ public: + +#if defined (__SPU__) && defined (__CELLOS_LV2__) + union { + vec_float4 mVec128; + btScalar m_floats[4]; + }; +public: + vec_float4 get128() const + { + return mVec128; + } +public: +#else //__CELLOS_LV2__ __SPU__ +#ifdef BT_USE_SSE // WIN32 + union { + __m128 mVec128; + btScalar m_floats[4]; + }; + SIMD_FORCE_INLINE __m128 get128() const + { + return mVec128; + } + SIMD_FORCE_INLINE void set128(__m128 v128) + { + mVec128 = v128; + } +#else + btScalar m_floats[4]; +#endif +#endif //__CELLOS_LV2__ __SPU__ + + public: + + /**@brief No initialization constructor */ 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) - :btQuadWord(x,y,z,btScalar(0.)) + /**@brief Constructor from scalars + * @param x X value + * @param y Y value + * @param z Z value + */ + SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) { + m_floats[0] = x; + m_floats[1] = y; + m_floats[2] = z; + m_floats[3] = btScalar(0.); } -// SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) -// : btQuadWord(x,y,z,w) -// { -// } - - +/**@brief Add a vector to this one + * @param The vector to add to this one */ SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) { - m_x += v.x(); m_y += v.y(); m_z += v.z(); + m_floats[0] += v.m_floats[0]; m_floats[1] += v.m_floats[1];m_floats[2] += v.m_floats[2]; return *this; } - + /**@brief Subtract a vector from this one + * @param The vector to subtract */ SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) { - m_x -= v.x(); m_y -= v.y(); m_z -= v.z(); + m_floats[0] -= v.m_floats[0]; m_floats[1] -= v.m_floats[1];m_floats[2] -= v.m_floats[2]; return *this; } - + /**@brief Scale the vector + * @param s Scale factor */ SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s) { - m_x *= s; m_y *= s; m_z *= s; + m_floats[0] *= s; m_floats[1] *= s;m_floats[2] *= s; return *this; } + /**@brief Inversely scale the vector + * @param s Scale factor to divide by */ SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s) { btFullAssert(s != btScalar(0.0)); return *this *= btScalar(1.0) / s; } + /**@brief Return the dot product + * @param v The other vector in the dot product */ SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const { - return m_x * v.x() + m_y * v.y() + m_z * v.z(); + return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] +m_floats[2] * v.m_floats[2]; } + /**@brief Return the length of the vector squared */ SIMD_FORCE_INLINE btScalar length2() const { return dot(*this); } + /**@brief Return the length of the vector */ SIMD_FORCE_INLINE btScalar length() const { return btSqrt(length2()); } + /**@brief Return the distance squared between the ends of this and another vector + * This is symantically treating the vector like a point */ SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const; + /**@brief Return the distance between the ends of this and another vector + * This is symantically treating the vector like a point */ SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const; + /**@brief Normalize this vector + * x^2 + y^2 + z^2 = 1 */ SIMD_FORCE_INLINE btVector3& normalize() { return *this /= length(); } + /**@brief Return a normalized version of this vector */ SIMD_FORCE_INLINE btVector3 normalized() const; + /**@brief Rotate this vector + * @param wAxis The axis to rotate about + * @param angle The angle to rotate by */ SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ); + /**@brief Return the angle between this and another vector + * @param v The other vector */ SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const { btScalar s = btSqrt(length2() * v.length2()); btFullAssert(s != btScalar(0.0)); return btAcos(dot(v) / s); } - + /**@brief Return a vector will the absolute values of each element */ SIMD_FORCE_INLINE btVector3 absolute() const { return btVector3( - btFabs(m_x), - btFabs(m_y), - btFabs(m_z)); + btFabs(m_floats[0]), + btFabs(m_floats[1]), + btFabs(m_floats[2])); } - + /**@brief Return the cross product between this and another vector + * @param v The other vector */ SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const { return btVector3( - m_y * v.z() - m_z * v.y(), - m_z * v.x() - m_x * v.z(), - m_x * v.y() - m_y * v.x()); + m_floats[1] * v.m_floats[2] -m_floats[2] * v.m_floats[1], + m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2], + m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]); } SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const { - return m_x * (v1.y() * v2.z() - v1.z() * v2.y()) + - m_y * (v1.z() * v2.x() - v1.x() * v2.z()) + - m_z * (v1.x() * v2.y() - v1.y() * v2.x()); + return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) + + m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) + + m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]); } + /**@brief Return the axis with the smallest value + * Note return values are 0,1,2 for x, y, or z */ SIMD_FORCE_INLINE int minAxis() const { - return m_x < m_y ? (m_x < m_z ? 0 : 2) : (m_y < m_z ? 1 : 2); + return m_floats[0] < m_floats[1] ? (m_floats[0] return this, t=1 => return other) */ SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const { - return btVector3(m_x + (v.x() - m_x) * t, - m_y + (v.y() - m_y) * t, - m_z + (v.z() - m_z) * t); + return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t, + m_floats[1] + (v.m_floats[1] - m_floats[1]) * t, + m_floats[2] + (v.m_floats[2] -m_floats[2]) * t); } - + /**@brief Elementwise multiply this vector by the other + * @param v The other vector */ SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v) { - m_x *= v.x(); m_y *= v.y(); m_z *= v.z(); + m_floats[0] *= v.m_floats[0]; m_floats[1] *= v.m_floats[1];m_floats[2] *= v.m_floats[2]; return *this; } - + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; } + /**@brief Set the x value */ + SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;}; + /**@brief Set the y value */ + SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;}; + /**@brief Set the z value */ + SIMD_FORCE_INLINE void setZ(btScalar z) {m_floats[2] = z;}; + /**@brief Set the w value */ + SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;}; + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; } + /**@brief Return the w value */ + SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; } + + //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; } + //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; } + ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons. + SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; } + SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; } + + SIMD_FORCE_INLINE bool operator==(const btVector3& other) const + { + return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0])); + } + + SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const + { + return !(*this == other); + } + + /**@brief Set each element to the max of the current values and the values of another btVector3 + * @param other The other btVector3 to compare with + */ + SIMD_FORCE_INLINE void setMax(const btVector3& other) + { + btSetMax(m_floats[0], other.m_floats[0]); + btSetMax(m_floats[1], other.m_floats[1]); + btSetMax(m_floats[2], other.m_floats[2]); + btSetMax(m_floats[3], other.w()); + } + /**@brief Set each element to the min of the current values and the values of another btVector3 + * @param other The other btVector3 to compare with + */ + SIMD_FORCE_INLINE void setMin(const btVector3& other) + { + btSetMin(m_floats[0], other.m_floats[0]); + btSetMin(m_floats[1], other.m_floats[1]); + btSetMin(m_floats[2], other.m_floats[2]); + btSetMin(m_floats[3], other.w()); + } + + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_floats[0]=x; + m_floats[1]=y; + m_floats[2]=z; + m_floats[3] = 0.f; + } + + void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const + { + v0->setValue(0. ,-z() ,y()); + v1->setValue(z() ,0. ,-x()); + v2->setValue(-y() ,x() ,0.); + } }; +/**@brief Return the sum of two vectors (Point symantics)*/ SIMD_FORCE_INLINE btVector3 operator+(const btVector3& v1, const btVector3& v2) { - return btVector3(v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z()); + return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]); } +/**@brief Return the elementwise product of two vectors */ SIMD_FORCE_INLINE btVector3 operator*(const btVector3& v1, const btVector3& v2) { - return btVector3(v1.x() * v2.x(), v1.y() * v2.y(), v1.z() * v2.z()); + return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]); } +/**@brief Return the difference between two vectors */ SIMD_FORCE_INLINE btVector3 operator-(const btVector3& v1, const btVector3& v2) { - return btVector3(v1.x() - v2.x(), v1.y() - v2.y(), v1.z() - v2.z()); + return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]); } - +/**@brief Return the negative of the vector */ SIMD_FORCE_INLINE btVector3 operator-(const btVector3& v) { - return btVector3(-v.x(), -v.y(), -v.z()); + return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]); } +/**@brief Return the vector scaled by s */ SIMD_FORCE_INLINE btVector3 operator*(const btVector3& v, const btScalar& s) { - return btVector3(v.x() * s, v.y() * s, v.z() * s); + return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s); } +/**@brief Return the vector scaled by s */ SIMD_FORCE_INLINE btVector3 operator*(const btScalar& s, const btVector3& v) { return v * s; } +/**@brief Return the vector inversely scaled by s */ SIMD_FORCE_INLINE btVector3 operator/(const btVector3& v, const btScalar& s) { @@ -221,12 +367,14 @@ operator/(const btVector3& v, const btScalar& s) return v * (btScalar(1.0) / s); } +/**@brief Return the vector inversely scaled by s */ SIMD_FORCE_INLINE btVector3 operator/(const btVector3& v1, const btVector3& v2) { - return btVector3(v1.x() / v2.x(),v1.y() / v2.y(),v1.z() / v2.z()); + return btVector3(v1.m_floats[0] / v2.m_floats[0],v1.m_floats[1] / v2.m_floats[1],v1.m_floats[2] / v2.m_floats[2]); } +/**@brief Return the dot product between two vectors */ SIMD_FORCE_INLINE btScalar dot(const btVector3& v1, const btVector3& v2) { @@ -234,7 +382,7 @@ dot(const btVector3& v1, const btVector3& v2) } - +/**@brief Return the distance squared between two vectors */ SIMD_FORCE_INLINE btScalar distance2(const btVector3& v1, const btVector3& v2) { @@ -242,18 +390,21 @@ distance2(const btVector3& v1, const btVector3& v2) } +/**@brief Return the distance between two vectors */ SIMD_FORCE_INLINE btScalar distance(const btVector3& v1, const btVector3& v2) { return v1.distance(v2); } +/**@brief Return the angle between two vectors */ SIMD_FORCE_INLINE btScalar angle(const btVector3& v1, const btVector3& v2) { return v1.angle(v2); } +/**@brief Return the cross product of two vectors */ SIMD_FORCE_INLINE btVector3 cross(const btVector3& v1, const btVector3& v2) { @@ -266,6 +417,10 @@ triple(const btVector3& v1, const btVector3& v2, const btVector3& v3) return v1.triple(v2, v3); } +/**@brief Return the linear interpolation between two vectors + * @param v1 One vector + * @param v2 The other vector + * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */ SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v1, const btVector3& v2, const btScalar& t) { @@ -273,10 +428,6 @@ lerp(const btVector3& v1, const btVector3& v2, const btScalar& t) } -SIMD_FORCE_INLINE bool operator==(const btVector3& p1, const btVector3& p2) -{ - return p1.x() == p2.x() && p1.y() == p2.y() && p1.z() == p2.z(); -} SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const { @@ -316,47 +467,47 @@ public: SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) : btVector3(x,y,z) { - m_unusedW = w; + m_floats[3] = w; } SIMD_FORCE_INLINE btVector4 absolute4() const { return btVector4( - btFabs(m_x), - btFabs(m_y), - btFabs(m_z), - btFabs(m_unusedW)); + btFabs(m_floats[0]), + btFabs(m_floats[1]), + btFabs(m_floats[2]), + btFabs(m_floats[3])); } - btScalar getW() const { return m_unusedW;} + btScalar getW() const { return m_floats[3];} SIMD_FORCE_INLINE int maxAxis4() const { int maxIndex = -1; btScalar maxVal = btScalar(-1e30); - if (m_x > maxVal) + if (m_floats[0] > maxVal) { maxIndex = 0; - maxVal = m_x; + maxVal = m_floats[0]; } - if (m_y > maxVal) + if (m_floats[1] > maxVal) { maxIndex = 1; - maxVal = m_y; + maxVal = m_floats[1]; } - if (m_z > maxVal) + if (m_floats[2] > maxVal) { maxIndex = 2; - maxVal = m_z; + maxVal =m_floats[2]; } - if (m_unusedW > maxVal) + if (m_floats[3] > maxVal) { maxIndex = 3; - maxVal = m_unusedW; + maxVal = m_floats[3]; } @@ -371,25 +522,25 @@ public: { int minIndex = -1; btScalar minVal = btScalar(1e30); - if (m_x < minVal) + if (m_floats[0] < minVal) { minIndex = 0; - minVal = m_x; + minVal = m_floats[0]; } - if (m_y < minVal) + if (m_floats[1] < minVal) { minIndex = 1; - minVal = m_y; + minVal = m_floats[1]; } - if (m_z < minVal) + if (m_floats[2] < minVal) { minIndex = 2; - minVal = m_z; + minVal =m_floats[2]; } - if (m_unusedW < minVal) + if (m_floats[3] < minVal) { minIndex = 3; - minVal = m_unusedW; + minVal = m_floats[3]; } return minIndex; @@ -402,6 +553,40 @@ public: return absolute4().maxAxis4(); } + + + + /**@brief Set x,y,z and zero w + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ + + +/* void getValue(btScalar *m) const + { + m[0] = m_floats[0]; + m[1] = m_floats[1]; + m[2] =m_floats[2]; + } +*/ +/**@brief Set the values + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + { + m_floats[0]=x; + m_floats[1]=y; + m_floats[2]=z; + m_floats[3]=w; + } + + + + }; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index fc76af15301..eecdea55349 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1457,11 +1457,12 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() { collisionMeshData = new btTriangleMesh(); + bool removeDuplicateVertices=true; // m_vertexArray is necessarily a multiple of 3 for (int i=0;iaddTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i]); + collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i],removeDuplicateVertices); } btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(collisionMeshData); @@ -1476,10 +1477,11 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() collisionMeshData = new btTriangleMesh(true,false); collisionMeshData->m_weldingThreshold = m_weldingThreshold; + bool removeDuplicateVertices=true; // m_vertexArray is necessarily a multiple of 3 for (int i=0;iaddTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i]); + collisionMeshData->addTriangle(m_vertexArray[i+2],m_vertexArray[i+1],m_vertexArray[i],removeDuplicateVertices); } // this shape will be shared and not deleted until shapeInfo is deleted m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 63ad427852e..6504f77ec53 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -356,6 +356,7 @@ m_ownDispatcher(NULL) setSolverType(1);//issues with quickstep and memory allocations // m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + //m_dynamicsWorld->getSolverInfo().m_solverMode= SOLVER_USE_WARMSTARTING + SOLVER_USE_2_FRICTION_DIRECTIONS + SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING; m_debugDrawer = 0; m_gravity = btVector3(0.f,-10.f,0.f); @@ -845,7 +846,8 @@ void CcdPhysicsEnvironment::setSolverType(int solverType) { m_solver = new btSequentialImpulseConstraintSolver(); -// ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); + + break; } } From 151317e990a432879a6978087d8d9bad831d5981 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 3 Mar 2009 14:31:10 +0000 Subject: [PATCH 235/252] Fix build: don't use Character stuff, it wasn't meant to be included in Blender/extern/bullet2 distro. --- .../BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index ba48f404929..ec803df06f7 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -56,8 +56,10 @@ subject to the following restrictions: #include "BulletDynamics/Vehicle/btRaycastVehicle.h" #include "BulletDynamics/Vehicle/btVehicleRaycaster.h" #include "BulletDynamics/Vehicle/btWheelInfo.h" +#ifdef USE_CHARACTER //character #include "BulletDynamics/Character/btCharacterControllerInterface.h" +#endif //USE_CHARACTER #include "LinearMath/btIDebugDraw.h" #include "LinearMath/btQuickprof.h" @@ -506,6 +508,7 @@ void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) void btDiscreteDynamicsWorld::updateCharacters(btScalar timeStep) { +#ifdef USE_CHARACTER BT_PROFILE("updateCharacters"); for ( int i=0;ipreStep (this); character->playerStep (this,timeStep); } +#endif //USE_CHARACTER } @@ -584,12 +588,16 @@ void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) void btDiscreteDynamicsWorld::addCharacter(btCharacterControllerInterface* character) { +#ifdef USE_CHARACTER m_characters.push_back(character); +#endif //USE_CHARACTER } void btDiscreteDynamicsWorld::removeCharacter(btCharacterControllerInterface* character) { +#ifdef USE_CHARACTER m_characters.remove(character); +#endif //USE_CHARACTER } From 7b197fcfdda39a3016efe4179ab9c67e2224f6a3 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 5 Mar 2009 09:50:16 +0000 Subject: [PATCH 236/252] MSVC9 project file update for Bullet upgrade. --- extern/bullet2/make/msvc_9_0/Bullet.vcproj | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/extern/bullet2/make/msvc_9_0/Bullet.vcproj b/extern/bullet2/make/msvc_9_0/Bullet.vcproj index d22b98efade..6ec064913a5 100644 --- a/extern/bullet2/make/msvc_9_0/Bullet.vcproj +++ b/extern/bullet2/make/msvc_9_0/Bullet.vcproj @@ -728,6 +728,14 @@ + + + + @@ -824,6 +832,14 @@ RelativePath="..\..\src\BulletCollision\CollisionDispatch\btEmptyCollisionAlgorithm.h" > + + + + @@ -960,6 +976,14 @@ RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexInternalShape.h" > + + + + From ab8e9ba3dd54fe8781f763644b882bbcb8cc7e8d Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 5 Mar 2009 15:16:43 +0000 Subject: [PATCH 237/252] VideoTexture: reactivate VideoTexture for scons/cmake/makefile compilation systems, fix video streaming, fix camera support in Linux, add multi-thread cache service, fix crash when a VideoFFmpeg object could not be created. The multi-thread cache service is activated only on multi-core processors. It consists in loading, decoding and caching the video frames in a separate thread. The cache size is 5 decoded frames and 30 raw frames. Note that the opening of video file/stream/camera is not multi-thread: you will still experience a delay at the VideoFFmpeg object creation. Processing of the video frame (resize, loading to texture) is still done in the main thread. Caching is automatically enabled for video file, video streaming and video camera. Video streaming now works correctly: the videos frames are loaded at the correct rate. Network delays and frequency drifts are automatically compensated. Note: an http video source is always treated as a streaming source, even though the http protocol allows seeking. For the user it means that he cannot define start/stop range and cannot restart the video except by reopening the source. Pause/play is however possible. Video camera is now correctly handled on Linux: it will not slow down the BGE. A video camera is treated as a streaming source. --- .../gameengine/BlenderRoutines/CMakeLists.txt | 4 + source/gameengine/BlenderRoutines/Makefile | 3 + source/gameengine/BlenderRoutines/SConscript | 3 + source/gameengine/VideoTexture/CMakeLists.txt | 2 +- source/gameengine/VideoTexture/Makefile | 3 + source/gameengine/VideoTexture/SConscript | 2 +- .../gameengine/VideoTexture/VideoFFmpeg.cpp | 546 +++++++++++++++--- source/gameengine/VideoTexture/VideoFFmpeg.h | 44 +- 8 files changed, 508 insertions(+), 99 deletions(-) diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index 340a1ae310b..d65e6a012df 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -38,5 +38,9 @@ SET(INC ${PYTHON_INC} ) +IF(WITH_FFMPEG) + ADD_DEFINITIONS(-DWITH_FFMPEG) +ENDIF(WITH_FFMPEG) + BLENDERLIB(bf_blroutines "${SRC}" "${INC}") #env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , compileflags=cxxflags) diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile index c2f19ae1d8a..e77d8e8380e 100644 --- a/source/gameengine/BlenderRoutines/Makefile +++ b/source/gameengine/BlenderRoutines/Makefile @@ -76,3 +76,6 @@ endif CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +ifeq ($(WITH_FFMPEG), true) + CPPFLAGS += -DWITH_FFMPEG +endif diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index f2d92384e3c..4a9c0e1286b 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -23,6 +23,9 @@ if env['WITH_BF_SOLID']: incs += ' ' + env['BF_SOLID_INC'] defs.append('USE_SUMO_SOLID') +if env['WITH_BF_FFMPEG']: + defs.append('WITH_FFMPEG') + incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_BULLET_INC'] incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/gameengine/VideoTexture/CMakeLists.txt b/source/gameengine/VideoTexture/CMakeLists.txt index 1674602edd7..1fca5374991 100644 --- a/source/gameengine/VideoTexture/CMakeLists.txt +++ b/source/gameengine/VideoTexture/CMakeLists.txt @@ -52,7 +52,7 @@ SET(INC ) IF(WITH_FFMPEG) - SET(INC ${INC} ${FFMPEG_INC}) + SET(INC ${INC} ${FFMPEG_INC} ${PTHREADS_INC}) ADD_DEFINITIONS(-DWITH_FFMPEG) ADD_DEFINITIONS(-D__STDC_CONSTANT_MACROS) ENDIF(WITH_FFMPEG) diff --git a/source/gameengine/VideoTexture/Makefile b/source/gameengine/VideoTexture/Makefile index bead176808b..a4611937a65 100644 --- a/source/gameengine/VideoTexture/Makefile +++ b/source/gameengine/VideoTexture/Makefile @@ -60,6 +60,9 @@ CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include ifeq ($(WITH_FFMPEG),true) CPPFLAGS += -DWITH_FFMPEG CPPFLAGS += $(NAN_FFMPEGCFLAGS) + ifdef NAN_PTHREADS + CPPFLAGS += -I$(NAN_PTHREADS)/include + endif endif diff --git a/source/gameengine/VideoTexture/SConscript b/source/gameengine/VideoTexture/SConscript index 28737ed06e5..edd44f98783 100644 --- a/source/gameengine/VideoTexture/SConscript +++ b/source/gameengine/VideoTexture/SConscript @@ -27,7 +27,7 @@ incs += ' ' + env['BF_PYTHON_INC'] if env['WITH_BF_FFMPEG']: defs += ' WITH_FFMPEG' - incs += ' ' + env['BF_FFMPEG_INC'] + incs += ' ' + env['BF_FFMPEG_INC'] + ' ' + env['BF_PTHREADS_INC'] defs += ' __STDC_CONSTANT_MACROS' env.BlenderLib ( 'bf_videotex', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], cxx_compileflags = cxxflags ) diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 02798c7e596..5265b0ecb93 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -55,7 +55,8 @@ m_codec(NULL), m_formatCtx(NULL), m_codecCtx(NULL), m_frame(NULL), m_frameDeinterlaced(NULL), m_frameRGB(NULL), m_imgConvertCtx(NULL), m_deinterlace(false), m_preseek(0), m_videoStream(-1), m_baseFrameRate(25.0), m_lastFrame(-1), m_eof(false), m_curPosition(-1), m_startTime(0), -m_captWidth(0), m_captHeight(0), m_captRate(0.f), m_isImage(false) +m_captWidth(0), m_captHeight(0), m_captRate(0.f), m_isImage(false), +m_isThreaded(false), m_stopThread(false), m_cacheStarted(false) { // set video format m_format = RGB24; @@ -63,6 +64,12 @@ m_captWidth(0), m_captHeight(0), m_captRate(0.f), m_isImage(false) setFlip(true); // construction is OK *hRslt = S_OK; + m_thread.first = m_thread.last = NULL; + pthread_mutex_init(&m_cacheMutex, NULL); + m_frameCacheFree.first = m_frameCacheFree.last = NULL; + m_frameCacheBase.first = m_frameCacheBase.last = NULL; + m_packetCacheFree.first = m_packetCacheFree.last = NULL; + m_packetCacheBase.first = m_packetCacheBase.last = NULL; } // destructor @@ -75,6 +82,7 @@ VideoFFmpeg::~VideoFFmpeg () bool VideoFFmpeg::release() { // release + stopCache(); if (m_codecCtx) { avcodec_close(m_codecCtx); @@ -112,6 +120,29 @@ bool VideoFFmpeg::release() return true; } +AVFrame *VideoFFmpeg::allocFrameRGB() +{ + AVFrame *frame; + frame = avcodec_alloc_frame(); + if (m_format == RGBA32) + { + avpicture_fill((AVPicture*)frame, + (uint8_t*)MEM_callocN(avpicture_get_size( + PIX_FMT_RGBA, + m_codecCtx->width, m_codecCtx->height), + "ffmpeg rgba"), + PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height); + } else + { + avpicture_fill((AVPicture*)frame, + (uint8_t*)MEM_callocN(avpicture_get_size( + PIX_FMT_RGB24, + m_codecCtx->width, m_codecCtx->height), + "ffmpeg rgb"), + PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height); + } + return frame; +} // set initial parameters void VideoFFmpeg::initParams (short width, short height, float rate, bool image) @@ -122,6 +153,7 @@ void VideoFFmpeg::initParams (short width, short height, float rate, bool image) m_isImage = image; } + int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams) { AVFormatContext *formatCtx; @@ -189,7 +221,6 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV m_videoStream = videoStream; m_frame = avcodec_alloc_frame(); m_frameDeinterlaced = avcodec_alloc_frame(); - m_frameRGB = avcodec_alloc_frame(); // allocate buffer if deinterlacing is required avpicture_fill((AVPicture*)m_frameDeinterlaced, @@ -207,12 +238,6 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV { // allocate buffer to store final decoded frame m_format = RGBA32; - avpicture_fill((AVPicture*)m_frameRGB, - (uint8_t*)MEM_callocN(avpicture_get_size( - PIX_FMT_RGBA, - m_codecCtx->width, m_codecCtx->height), - "ffmpeg rgba"), - PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height); // allocate sws context m_imgConvertCtx = sws_getContext( m_codecCtx->width, @@ -227,12 +252,6 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV { // allocate buffer to store final decoded frame m_format = RGB24; - avpicture_fill((AVPicture*)m_frameRGB, - (uint8_t*)MEM_callocN(avpicture_get_size( - PIX_FMT_RGB24, - m_codecCtx->width, m_codecCtx->height), - "ffmpeg rgb"), - PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height); // allocate sws context m_imgConvertCtx = sws_getContext( m_codecCtx->width, @@ -244,19 +263,247 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV SWS_FAST_BILINEAR, NULL, NULL, NULL); } + m_frameRGB = allocFrameRGB(); + if (!m_imgConvertCtx) { avcodec_close(m_codecCtx); + m_codecCtx = NULL; av_close_input_file(m_formatCtx); + m_formatCtx = NULL; av_free(m_frame); + m_frame = NULL; MEM_freeN(m_frameDeinterlaced->data[0]); av_free(m_frameDeinterlaced); + m_frameDeinterlaced = NULL; MEM_freeN(m_frameRGB->data[0]); av_free(m_frameRGB); + m_frameRGB = NULL; return -1; } return 0; } +/* + * This thread is used to load video frame asynchronously. + * It provides a frame caching service. + * The main thread is responsible for positionning the frame pointer in the + * file correctly before calling startCache() which starts this thread. + * The cache is organized in two layers: 1) a cache of 20-30 undecoded packets to keep + * memory and CPU low 2) a cache of 5 decoded frames. + * If the main thread does not find the frame in the cache (because the video has restarted + * or because the GE is lagging), it stops the cache with StopCache() (this is a synchronous + * function: it sends a signal to stop the cache thread and wait for confirmation), then + * change the position in the stream and restarts the cache thread. + */ +void *VideoFFmpeg::cacheThread(void *data) +{ + VideoFFmpeg* video = (VideoFFmpeg*)data; + // holds the frame that is being decoded + CacheFrame *currentFrame = NULL; + CachePacket *cachePacket; + bool endOfFile = false; + int frameFinished = 0; + + while (!video->m_stopThread) + { + // packet cache is used solely by this thread, no need to lock + // In case the stream/file contains other stream than the one we are looking for, + // allow a bit of cycling to get rid quickly of those frames + frameFinished = 0; + while ( !endOfFile + && (cachePacket = (CachePacket *)video->m_packetCacheFree.first) != NULL + && frameFinished < 25) + { + // free packet => packet cache is not full yet, just read more + if (av_read_frame(video->m_formatCtx, &cachePacket->packet)>=0) + { + if (cachePacket->packet.stream_index == video->m_videoStream) + { + // make sure fresh memory is allocated for the packet and move it to queue + av_dup_packet(&cachePacket->packet); + BLI_remlink(&video->m_packetCacheFree, cachePacket); + BLI_addtail(&video->m_packetCacheBase, cachePacket); + break; + } else { + // this is not a good packet for us, just leave it on free queue + // Note: here we could handle sound packet + av_free_packet(&cachePacket->packet); + frameFinished++; + } + + } else { + if (video->m_isFile) + // this mark the end of the file + endOfFile = true; + // if we cannot read a packet, no need to continue + break; + } + } + // frame cache is also used by main thread, lock + if (currentFrame == NULL) + { + // no current frame being decoded, take free one + pthread_mutex_lock(&video->m_cacheMutex); + if ((currentFrame = (CacheFrame *)video->m_frameCacheFree.first) != NULL) + BLI_remlink(&video->m_frameCacheFree, currentFrame); + pthread_mutex_unlock(&video->m_cacheMutex); + } + if (currentFrame != NULL) + { + // this frame is out of free and busy queue, we can manipulate it without locking + frameFinished = 0; + while (!frameFinished && (cachePacket = (CachePacket *)video->m_packetCacheBase.first) != NULL) + { + BLI_remlink(&video->m_packetCacheBase, cachePacket); + // use m_frame because when caching, it is not used in main thread + // we can't use currentFrame directly because we need to convert to RGB first + avcodec_decode_video(video->m_codecCtx, + video->m_frame, &frameFinished, + cachePacket->packet.data, cachePacket->packet.size); + if(frameFinished) + { + AVFrame * input = video->m_frame; + + /* This means the data wasnt read properly, this check stops crashing */ + if ( input->data[0]!=0 || input->data[1]!=0 + || input->data[2]!=0 || input->data[3]!=0) + { + if (video->m_deinterlace) + { + if (avpicture_deinterlace( + (AVPicture*) video->m_frameDeinterlaced, + (const AVPicture*) video->m_frame, + video->m_codecCtx->pix_fmt, + video->m_codecCtx->width, + video->m_codecCtx->height) >= 0) + { + input = video->m_frameDeinterlaced; + } + } + // convert to RGB24 + sws_scale(video->m_imgConvertCtx, + input->data, + input->linesize, + 0, + video->m_codecCtx->height, + currentFrame->frame->data, + currentFrame->frame->linesize); + // move frame to queue, this frame is necessarily the next one + currentFrame->framePosition = ++video->m_curPosition; + pthread_mutex_lock(&video->m_cacheMutex); + BLI_addtail(&video->m_frameCacheBase, currentFrame); + pthread_mutex_unlock(&video->m_cacheMutex); + currentFrame = NULL; + } + } + av_free_packet(&cachePacket->packet); + BLI_addtail(&video->m_packetCacheFree, cachePacket); + } + if (currentFrame && endOfFile) + { + // no more packet and end of file => put a special frame that indicates that + currentFrame->framePosition = -1; + pthread_mutex_lock(&video->m_cacheMutex); + BLI_addtail(&video->m_frameCacheBase, currentFrame); + pthread_mutex_unlock(&video->m_cacheMutex); + currentFrame = NULL; + // no need to stay any longer in this thread + break; + } + } + // small sleep to avoid unnecessary looping + PIL_sleep_ms(10); + } + // before quitting, put back the current frame to queue to allow freeing + if (currentFrame) + { + pthread_mutex_lock(&video->m_cacheMutex); + BLI_addtail(&video->m_frameCacheFree, currentFrame); + pthread_mutex_unlock(&video->m_cacheMutex); + } + return 0; +} + +// start thread to cache video frame from file/capture/stream +// this function should be called only when the position in the stream is set for the +// first frame to cache +bool VideoFFmpeg::startCache() +{ + if (!m_cacheStarted && m_isThreaded) + { + m_stopThread = false; + for (int i=0; iframe = allocFrameRGB(); + BLI_addtail(&m_frameCacheFree, frame); + } + for (int i=0; iframe->data[0]); + av_free(frame->frame); + delete frame; + } + while ((frame = (CacheFrame *)m_frameCacheFree.first) != NULL) + { + BLI_remlink(&m_frameCacheFree, frame); + MEM_freeN(frame->frame->data[0]); + av_free(frame->frame); + delete frame; + } + while((packet = (CachePacket *)m_packetCacheBase.first) != NULL) + { + BLI_remlink(&m_packetCacheBase, packet); + av_free_packet(&packet->packet); + delete packet; + } + while((packet = (CachePacket *)m_packetCacheFree.first) != NULL) + { + BLI_remlink(&m_packetCacheFree, packet); + delete packet; + } + m_cacheStarted = false; + } +} + +void VideoFFmpeg::releaseFrame(AVFrame* frame) +{ + if (frame == m_frameRGB) + { + // this is not a frame from the cache, ignore + return; + } + // this frame MUST be the first one of the queue + pthread_mutex_lock(&m_cacheMutex); + CacheFrame *cacheFrame = (CacheFrame *)m_frameCacheBase.first; + assert (cacheFrame != NULL && cacheFrame->frame == frame); + BLI_remlink(&m_frameCacheBase, cacheFrame); + BLI_addtail(&m_frameCacheFree, cacheFrame); + pthread_mutex_unlock(&m_cacheMutex); +} + // open video file void VideoFFmpeg::openFile (char * filename) { @@ -280,8 +527,12 @@ void VideoFFmpeg::openFile (char * filename) VideoBase::openFile(filename); if ( + // ffmpeg reports that http source are actually non stream + // but it is really not desirable to seek on http file, so force streaming. + // It would be good to find this information from the context but there are no simple indication + !strncmp(filename, "http://", 7) || #ifdef FFMPEG_PB_IS_POINTER - m_formatCtx->pb && m_formatCtx->pb->is_streamed + (m_formatCtx->pb && m_formatCtx->pb->is_streamed) #else m_formatCtx->pb.is_streamed #endif @@ -304,7 +555,13 @@ void VideoFFmpeg::openFile (char * filename) m_avail = false; play(); } - + // check if we should do multi-threading? + if (!m_isImage && BLI_system_thread_count() > 1) + { + // never thread image: there are no frame to read ahead + // no need to thread if the system has a single core + m_isThreaded = true; + } } @@ -385,6 +642,12 @@ void VideoFFmpeg::openCam (char * file, short camIdx) m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK; // open base class VideoBase::openCam(file, camIdx); + // check if we should do multi-threading? + if (BLI_system_thread_count() > 1) + { + // no need to thread if the system has a single core + m_isThreaded = true; + } } // play video @@ -427,9 +690,12 @@ void VideoFFmpeg::setRange (double start, double stop) try { // set range - VideoBase::setRange(start, stop); - // set range for video - setPositions(); + if (m_isFile) + { + VideoBase::setRange(start, stop); + // set range for video + setPositions(); + } } CATCH_EXCP; } @@ -451,43 +717,61 @@ void VideoFFmpeg::calcImage (unsigned int texId) // load frame from video void VideoFFmpeg::loadFrame (void) { - // get actual time - double actTime = PIL_check_seconds_timer() - m_startTime; - // if video has ended - if (m_isFile && actTime * m_frameRate >= m_range[1]) - { - // if repeats are set, decrease them - if (m_repeat > 0) - --m_repeat; - // if video has to be replayed - if (m_repeat != 0) - { - // reset its position - actTime -= (m_range[1] - m_range[0]) / m_frameRate; - m_startTime += (m_range[1] - m_range[0]) / m_frameRate; - } - // if video has to be stopped, stop it - else - m_status = SourceStopped; - } - // if video is playing if (m_status == SourcePlaying) { + // get actual time + double startTime = PIL_check_seconds_timer(); + double actTime = startTime - m_startTime; + // if video has ended + if (m_isFile && actTime * m_frameRate >= m_range[1]) + { + // in any case, this resets the cache + stopCache(); + // if repeats are set, decrease them + if (m_repeat > 0) + --m_repeat; + // if video has to be replayed + if (m_repeat != 0) + { + // reset its position + actTime -= (m_range[1] - m_range[0]) / m_frameRate; + m_startTime += (m_range[1] - m_range[0]) / m_frameRate; + } + // if video has to be stopped, stop it + else + { + m_status = SourceStopped; + return; + } + } // actual frame - long actFrame = m_isFile ? long(actTime * actFrameRate()) : m_lastFrame + 1; + long actFrame = (m_isImage) ? m_lastFrame+1 : long(actTime * actFrameRate()); // if actual frame differs from last frame if (actFrame != m_lastFrame) { + AVFrame* frame; // get image - if(grabFrame(actFrame)) + if((frame = grabFrame(actFrame)) != NULL) { - AVFrame* frame = getFrame(); + if (!m_isFile && !m_cacheStarted) + { + // streaming without cache: detect synchronization problem + double execTime = PIL_check_seconds_timer() - startTime; + if (execTime > 0.005) + { + // exec time is too long, it means that the function was blocking + // resynchronize the stream from this time + m_startTime += execTime; + } + } // save actual frame m_lastFrame = actFrame; // init image, if needed init(short(m_codecCtx->width), short(m_codecCtx->height)); // process image process((BYTE*)(frame->data[0])); + // finished with the frame, release it so that cache can reuse it + releaseFrame(frame); // in case it is an image, automatically stop reading it if (m_isImage) { @@ -495,6 +779,12 @@ void VideoFFmpeg::loadFrame (void) // close the file as we don't need it anymore release(); } + } else if (!m_isFile) + { + // we didn't get a frame and we are streaming, this may be due to + // a delay in the network or because we are getting the frame too fast. + // In the later case, shift time by a small amount to compensate for a drift + m_startTime += 0.01; } } } @@ -507,77 +797,135 @@ void VideoFFmpeg::setPositions (void) // set video start time m_startTime = PIL_check_seconds_timer(); // if file is played and actual position is before end position - if (m_isFile && !m_eof && m_lastFrame >= 0 && m_lastFrame < m_range[1] * actFrameRate()) + if (!m_eof && m_lastFrame >= 0 && (!m_isFile || m_lastFrame < m_range[1] * actFrameRate())) // continue from actual position m_startTime -= double(m_lastFrame) / actFrameRate(); - else + else { m_startTime -= m_range[0]; + // start from begining, stop cache just in case + stopCache(); + } } // position pointer in file, position in second -bool VideoFFmpeg::grabFrame(long position) +AVFrame *VideoFFmpeg::grabFrame(long position) { AVPacket packet; int frameFinished; int posFound = 1; bool frameLoaded = false; long long targetTs = 0; + CacheFrame *frame; - // first check if the position that we are looking for is in the preseek range - // if so, just read the frame until we get there - if (position > m_curPosition + 1 - && m_preseek - && position - (m_curPosition + 1) < m_preseek) + if (m_cacheStarted) { - while(av_read_frame(m_formatCtx, &packet)>=0) - { - if (packet.stream_index == m_videoStream) + // when cache is active, we must not read the file directly + do { + pthread_mutex_lock(&m_cacheMutex); + frame = (CacheFrame *)m_frameCacheBase.first; + pthread_mutex_unlock(&m_cacheMutex); + // no need to remove the frame from the queue: the cache thread does not touch the head, only the tail + if (frame == NULL) { - avcodec_decode_video( - m_codecCtx, - m_frame, &frameFinished, - packet.data, packet.size); - if (frameFinished) - m_curPosition++; + // no frame in cache, in case of file it is an abnormal situation + if (m_isFile) + { + // go back to no threaded reading + stopCache(); + break; + } + return NULL; } - av_free_packet(&packet); - if (position == m_curPosition+1) - break; - } - } - // if the position is not in preseek, do a direct jump - if (position != m_curPosition + 1) - { - double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base); - long long pos = (long long) - ((long long) (position - m_preseek) * AV_TIME_BASE / m_baseFrameRate); - long long startTs = m_formatCtx->streams[m_videoStream]->start_time; - - if (pos < 0) - pos = 0; - - if (startTs != AV_NOPTS_VALUE) - pos += (long long)(startTs * AV_TIME_BASE * timeBase); - - if (position <= m_curPosition || !m_eof) - { - // no need to seek past the end of the file - if (av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD) >= 0) + if (frame->framePosition == -1) { - // current position is now lost, guess a value. - // It's not important because it will be set at this end of this function - m_curPosition = position - m_preseek - 1; + // this frame mark the end of the file (only used for file) + // leave in cache to make sure we don't miss it + m_eof = true; + return NULL; + } + // for streaming, always return the next frame, + // that's what grabFrame does in non cache mode anyway. + if (!m_isFile || frame->framePosition == position) + { + return frame->frame; + } + // this frame is not useful, release it + pthread_mutex_lock(&m_cacheMutex); + BLI_remlink(&m_frameCacheBase, frame); + BLI_addtail(&m_frameCacheFree, frame); + pthread_mutex_unlock(&m_cacheMutex); + } while (true); + } + // come here when there is no cache or cache has been stopped + // locate the frame, by seeking if necessary (seeking is only possible for files) + if (m_isFile) + { + // first check if the position that we are looking for is in the preseek range + // if so, just read the frame until we get there + if (position > m_curPosition + 1 + && m_preseek + && position - (m_curPosition + 1) < m_preseek) + { + while(av_read_frame(m_formatCtx, &packet)>=0) + { + if (packet.stream_index == m_videoStream) + { + avcodec_decode_video( + m_codecCtx, + m_frame, &frameFinished, + packet.data, packet.size); + if (frameFinished) + m_curPosition++; + } + av_free_packet(&packet); + if (position == m_curPosition+1) + break; } } - // this is the timestamp of the frame we're looking for - targetTs = (long long)(((double) position) / m_baseFrameRate / timeBase); - if (startTs != AV_NOPTS_VALUE) - targetTs += startTs; + // if the position is not in preseek, do a direct jump + if (position != m_curPosition + 1) + { + double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base); + long long pos = (long long) + ((long long) (position - m_preseek) * AV_TIME_BASE / m_baseFrameRate); + long long startTs = m_formatCtx->streams[m_videoStream]->start_time; - posFound = 0; - avcodec_flush_buffers(m_codecCtx); + if (pos < 0) + pos = 0; + + if (startTs != AV_NOPTS_VALUE) + pos += (long long)(startTs * AV_TIME_BASE * timeBase); + + if (position <= m_curPosition || !m_eof) + { + // no need to seek past the end of the file + if (av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD) >= 0) + { + // current position is now lost, guess a value. + // It's not important because it will be set at this end of this function + m_curPosition = position - m_preseek - 1; + } + } + // this is the timestamp of the frame we're looking for + targetTs = (long long)(((double) position) / m_baseFrameRate / timeBase); + if (startTs != AV_NOPTS_VALUE) + targetTs += startTs; + + posFound = 0; + avcodec_flush_buffers(m_codecCtx); + } + } else if (m_isThreaded) + { + // cache is not started but threading is possible + // better not read the stream => make take some time, better start caching + if (startCache()) + return NULL; + // Abnormal!!! could not start cache, fall back on direct read + m_isThreaded = false; } + // find the correct frame, in case of streaming and no cache, it means just + // return the next frame. This is not quite correct, may need more work while(av_read_frame(m_formatCtx, &packet)>=0) { if(packet.stream_index == m_videoStream) @@ -632,10 +980,22 @@ bool VideoFFmpeg::grabFrame(long position) } av_free_packet(&packet); } - m_eof = !frameLoaded; + m_eof = m_isFile && !frameLoaded; if (frameLoaded) + { m_curPosition = position; - return frameLoaded; + if (m_isThreaded) + { + // normal case for file: first locate, then start cache + if (!startCache()) + { + // Abnormal!! could not start cache, return to non-cache mode + m_isThreaded = false; + } + } + return m_frameRGB; + } + return NULL; } diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index e60f1727aab..51ce2c4eebe 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -24,12 +24,17 @@ http://www.gnu.org/copyleft/lesser.txt. #ifdef WITH_FFMPEG extern "C" { +#include #include #include #include #include +#include "DNA_listBase.h" +#include "BLI_threads.h" +#include "BLI_blenlib.h" } + #if LIBAVFORMAT_VERSION_INT < (49 << 16) #define FFMPEG_OLD_FRAME_RATE 1 #else @@ -54,6 +59,8 @@ static inline AVCodecContext* get_codec_from_stream(AVStream* stream) #include "VideoBase.h" +#define CACHE_FRAME_SIZE 5 +#define CACHE_PACKET_SIZE 30 // type VideoFFmpeg declaration class VideoFFmpeg : public VideoBase @@ -91,7 +98,6 @@ public: char *getImageName(void) { return (m_isImage) ? m_imageName.Ptr() : NULL; } protected: - // format and codec information AVCodec *m_codec; AVFormatContext *m_formatCtx; @@ -138,6 +144,9 @@ protected: /// is file an image? bool m_isImage; + /// is image loading done in a separate thread? + bool m_isThreaded; + /// keep last image name STR_String m_imageName; @@ -157,10 +166,37 @@ protected: int openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams); /// check if a frame is available and load it in pFrame, return true if a frame could be retrieved - bool grabFrame(long frame); + AVFrame* grabFrame(long frame); - /// return the frame in RGB24 format, the image data is found in AVFrame.data[0] - AVFrame* getFrame(void) { return m_frameRGB; } + /// in case of caching, put the frame back in free queue + void releaseFrame(AVFrame* frame); + + /// start thread to load the video file/capture/stream + bool startCache(); + void stopCache(); + +private: + typedef struct { + Link link; + long framePosition; + AVFrame *frame; + } CacheFrame; + typedef struct { + Link link; + AVPacket packet; + } CachePacket; + + bool m_stopThread; + bool m_cacheStarted; + ListBase m_thread; + ListBase m_frameCacheBase; // list of frames that are ready + ListBase m_frameCacheFree; // list of frames that are unused + ListBase m_packetCacheBase; // list of packets that are ready for decoding + ListBase m_packetCacheFree; // list of packets that are unused + pthread_mutex_t m_cacheMutex; + + AVFrame *allocFrameRGB(); + static void *cacheThread(void *); }; inline VideoFFmpeg * getFFmpeg (PyImage * self) From 51b3bba1c01bbb89586b44c21501bbe4749b03ad Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 5 Mar 2009 15:35:15 +0000 Subject: [PATCH 238/252] Update MSVC9 project file for VideoTexture --- projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj b/projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj index 4a3b4b865fc..232001c1012 100644 --- a/projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj +++ b/projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj @@ -4,6 +4,7 @@ Version="9,00" Name="TEX_Video" ProjectGUID="{670EC17A-0548-4BBF-A27B-636C7C188139}" + RootNamespace="TEX_Video" Keyword="Win32Proj" TargetFrameworkVersion="131072" > @@ -41,7 +42,7 @@ Date: Fri, 6 Mar 2009 15:46:13 +0000 Subject: [PATCH 239/252] Addes jpeg2000 support to cmake. I also did some small tweaks. removed ifdef's for pluginapi didn't need them there. Fixed it so the filesel shows jp2 as image files. (I'm going to do makefiles next) Kent --- CMakeLists.txt | 5 +++- blenderplayer/CMakeLists.txt | 1 + extern/CMakeLists.txt | 5 +++- extern/libopenjpeg/CMakeLists.txt | 32 ++++++++++++++++++++++++ source/blender/blenkernel/CMakeLists.txt | 4 +++ source/blender/blenpluginapi/iff.h | 6 ++--- source/blender/imbuf/CMakeLists.txt | 5 ++++ source/blender/src/CMakeLists.txt | 4 +++ source/blender/src/filesel.c | 6 +++++ source/creator/CMakeLists.txt | 1 + 10 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 extern/libopenjpeg/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b96ca585a6..0b7f3999e82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,7 @@ OPTION(WITH_QUICKTIME "Enable Quicktime Support" OFF) OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON) OPTION(WITH_DDS "Enable DDS Support" ON) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) -OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) +OPTION(WITH_OPENJPEG "Enable OpenJpeg Support (http://www.openjpeg.org/)" 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 (Unix only)" OFF) @@ -431,6 +431,9 @@ SET(FTGL ${CMAKE_SOURCE_DIR}/extern/bFTGL) SET(FTGL_INC ${FTGL}/include) SET(FTGL_LIB extern_ftgl) +set(OPENJPEG ${CMAKE_SOURCE_DIR}/extern/libopenjpeg) +set(OPENJPEG_INC ${OPENJPEG}) +set(OPENJPEG_LIb extern_libopenjpeg) #----------------------------------------------------------------------------- # Blender WebPlugin diff --git a/blenderplayer/CMakeLists.txt b/blenderplayer/CMakeLists.txt index f02650f7ea0..b9ac3c7a8c6 100644 --- a/blenderplayer/CMakeLists.txt +++ b/blenderplayer/CMakeLists.txt @@ -104,6 +104,7 @@ IF(UNIX) bf_blenlib bf_cineon bf_openexr + extern_libopenjpeg bf_dds bf_ftfont extern_ftgl diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index ee5cab31e09..b81efb52de9 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -29,7 +29,7 @@ IF(WITH_GAMEENGINE) ENDIF(WITH_GAMEENGINE) IF(WITH_BULLET) - SUBDIRS(bullet2) + SUBDIRS(bullet2) ENDIF(WITH_BULLET) IF(WITH_INTERNATIONAL) @@ -46,3 +46,6 @@ ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") SUBDIRS(glew) +IF(WITH_OPENJPEG) + SUBDIRS(libopenjpeg) +ENDIF(WITH_OPENJPEG) diff --git a/extern/libopenjpeg/CMakeLists.txt b/extern/libopenjpeg/CMakeLists.txt new file mode 100644 index 00000000000..c179d5328b9 --- /dev/null +++ b/extern/libopenjpeg/CMakeLists.txt @@ -0,0 +1,32 @@ +# $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 ***** + +SET(INC . src ${FREETYPE_INC}) + +FILE(GLOB SRC *.c except t1_generate_luts.c) +ADD_DEFINITIONS(-DWITH_OPENJPEG) +BLENDERLIB(extern_libopenjpeg "${SRC}" "${INC}") +#, libtype=['international','player'], priority=[5, 210]) diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 04ca5c79a11..27be1b45779 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -47,6 +47,10 @@ IF(WITH_OPENEXR) ADD_DEFINITIONS(-DWITH_OPENEXR) ENDIF(WITH_OPENEXR) +IF(WITH_OPENJPEG) + ADD_DEFINITIONS(-DWITH_OPENJPEG) +ENDIF(WITH_OPENJPEG) + IF(WITH_DDS) ADD_DEFINITIONS(-DWITH_DDS) ENDIF(WITH_DDS) diff --git a/source/blender/blenpluginapi/iff.h b/source/blender/blenpluginapi/iff.h index e7f328d870f..9378cdc9134 100644 --- a/source/blender/blenpluginapi/iff.h +++ b/source/blender/blenpluginapi/iff.h @@ -45,6 +45,8 @@ #define IB_zbuf (1 << 13) #define IB_rgba (1 << 14) +#define JP2 (1 << 18) + #define AMI (1 << 31) #define PNG (1 << 30) #define Anim (1 << 29) @@ -56,10 +58,6 @@ #endif #define RADHDR (1<<24) -#ifdef WITH_OPENJPEG -#define JP2 (1 << 18) -#endif - #define RAWTGA (TGA | 1) #define JPG_STD (JPG | (0 << 8)) diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index 2d41a6d73e6..9894aa8136e 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -33,6 +33,7 @@ SET(INC ${PNG_INC} ${TIFF_INC} ${ZLIB_INC} + ${OPENJPEG_INC} ) IF(WITH_VERSE) @@ -44,6 +45,10 @@ IF(WITH_OPENEXR) ADD_DEFINITIONS(-DWITH_OPENEXR) ENDIF(WITH_OPENEXR) +IF(WITH_OPENJPEG) + ADD_DEFINITIONS(-DWITH_OPENJPEG) +ENDIF(WITH_OPENJPEG) + IF(WITH_QUICKTIME) SET(INC ${INC} ${QUICKTIME_INC}) ADD_DEFINITIONS(-DWITH_QUICKTIME) diff --git a/source/blender/src/CMakeLists.txt b/source/blender/src/CMakeLists.txt index e2757dbc75d..dc2928cd17b 100644 --- a/source/blender/src/CMakeLists.txt +++ b/source/blender/src/CMakeLists.txt @@ -50,6 +50,10 @@ IF(WITH_OPENEXR) ADD_DEFINITIONS(-DWITH_OPENEXR) ENDIF(WITH_OPENEXR) +IF(WITH_OPENJPEG) + ADD_DEFINITIONS(-DWITH_OPENJPEG) +ENDIF(WITH_OPENJPEG) + IF(WITH_QUICKTIME) SET(INC ${INC} ${QUICKTIME_INC}) ADD_DEFINITIONS(-DWITH_QUICKTIME) diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index ee1fc523395..9800c80b57d 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -380,6 +380,9 @@ void test_flags_file(SpaceFile *sfile) } else if (G.have_quicktime){ if( BLI_testextensie(file->relname, ".jpg") || BLI_testextensie(file->relname, ".jpeg") +#ifdef WITH_OPENJPEG + || BLI_testextensie(file->relname, ".jp2") +#endif || BLI_testextensie(file->relname, ".hdr") || BLI_testextensie(file->relname, ".exr") || BLI_testextensie(file->relname, ".tga") @@ -414,6 +417,9 @@ void test_flags_file(SpaceFile *sfile) } } else { // no quicktime if(BLI_testextensie(file->relname, ".jpg") +#ifdef WITH_OPENJPEG + || BLI_testextensie(file->relname, ".jp2") +#endif || BLI_testextensie(file->relname, ".hdr") || BLI_testextensie(file->relname, ".exr") || BLI_testextensie(file->relname, ".tga") diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index ee6f19e457d..8e2a906614d 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -267,6 +267,7 @@ IF(UNIX) bf_quicktime extern_binreloc extern_glew + extern_libopenjpeg bf_videotex ) From e4ce0d629e021bcc1b910a1f49c251a17501cff6 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 8 Mar 2009 17:23:36 +0000 Subject: [PATCH 240/252] BGE patch: undo patch about removing blenderplayer console in Windows: it interferes with scripts that write to the console. Back to previous state: console cannot be disabled in Windows. --- source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 87b6b2450f7..afee60c3192 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -645,7 +645,7 @@ int main(int argc, char** argv) #ifdef NDEBUG if (closeConsole) { - ::FreeConsole(); // Close a console window + //::FreeConsole(); // Close a console window } #endif // NDEBUG #endif // WIN32 From abb338ddf9dea9a26ca1092b3f7fda86b32bbd16 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 9 Mar 2009 04:21:28 +0000 Subject: [PATCH 241/252] upgrade to latest Bullet trunk, fix related to vehicle anti-roll, added constraint visualization. This commit doesn't add new functionality, but more updates are planned before Blender 2.49 release. --- .../btSequentialImpulseConstraintSolver.cpp | 36 +++---- .../btSequentialImpulseConstraintSolver.h | 5 +- .../ConstraintSolver/btSolverBody.h | 6 +- .../ConstraintSolver/btTypedConstraint.h | 1 - .../Dynamics/btActionInterface.h | 39 +++++++ .../Dynamics/btContinuousDynamicsWorld.cpp | 3 +- .../Dynamics/btDiscreteDynamicsWorld.cpp | 102 ++++++------------ .../Dynamics/btDiscreteDynamicsWorld.h | 39 +++---- .../BulletDynamics/Dynamics/btDynamicsWorld.h | 23 ++-- .../BulletDynamics/Dynamics/btRigidBody.cpp | 3 +- .../src/BulletDynamics/Dynamics/btRigidBody.h | 36 +++++-- .../Vehicle/btRaycastVehicle.cpp | 39 ++++++- .../BulletDynamics/Vehicle/btRaycastVehicle.h | 47 +++++--- .../bullet2/src/LinearMath/btConvexHull.cpp | 8 +- .../Converter/KX_BlenderSceneConverter.cpp | 2 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 2 + 16 files changed, 227 insertions(+), 164 deletions(-) create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btActionInterface.h diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 6928bdb966b..685a812d427 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -76,8 +76,8 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD( __m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp); deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) ); c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) ); - __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,_mm_set1_ps(body1.m_invMass)); - __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,_mm_set1_ps(body2.m_invMass)); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.m_invMass.mVec128); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.m_invMass.mVec128); __m128 impulseMagnitude = deltaImpulse; body1.m_deltaLinearVelocity.mVec128 = _mm_add_ps(body1.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); body1.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body1.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); @@ -114,9 +114,7 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD( { c.m_appliedImpulse = sum; } - if (body1.m_invMass) body1.applyImpulse(c.m_contactNormal*body1.m_invMass,c.m_angularComponentA,deltaImpulse); - if (body2.m_invMass) body2.applyImpulse(-c.m_contactNormal*body2.m_invMass,c.m_angularComponentB,deltaImpulse); } @@ -138,8 +136,8 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD( __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); - __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,_mm_set1_ps(body1.m_invMass)); - __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,_mm_set1_ps(body2.m_invMass)); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.m_invMass.mVec128); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.m_invMass.mVec128); __m128 impulseMagnitude = deltaImpulse; body1.m_deltaLinearVelocity.mVec128 = _mm_add_ps(body1.m_deltaLinearVelocity.mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); body1.m_deltaAngularVelocity.mVec128 = _mm_add_ps(body1.m_deltaAngularVelocity.mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); @@ -169,10 +167,8 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD( { c.m_appliedImpulse = sum; } - if (body1.m_invMass) - body1.applyImpulse(c.m_contactNormal*body1.m_invMass,c.m_angularComponentA,deltaImpulse); - if (body2.m_invMass) - body2.applyImpulse(-c.m_contactNormal*body2.m_invMass,c.m_angularComponentB,deltaImpulse); + body1.applyImpulse(c.m_contactNormal*body1.m_invMass,c.m_angularComponentA,deltaImpulse); + body2.applyImpulse(-c.m_contactNormal*body2.m_invMass,c.m_angularComponentB,deltaImpulse); } @@ -224,14 +220,14 @@ void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBod if (rb) { - solverBody->m_invMass = rb->getInvMass(); + solverBody->m_invMass = btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor(); solverBody->m_originalBody = rb; solverBody->m_angularFactor = rb->getAngularFactor(); } else { - solverBody->m_invMass = 0.f; + solverBody->m_invMass.setValue(0,0,0); solverBody->m_originalBody = 0; - solverBody->m_angularFactor = 1.f; + solverBody->m_angularFactor.setValue(1,1,1); } } @@ -394,6 +390,10 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m solverBodyIdB = getOrInitSolverBody(*colObj1); } + ///avoid collision response between two static objects + if (!solverBodyIdA && !solverBodyIdB) + return; + btVector3 rel_pos1; btVector3 rel_pos2; btScalar relaxation; @@ -490,13 +490,13 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m ///warm starting (or zero if disabled) - if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + if (0)//infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) { solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; if (rb0) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].applyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].applyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); if (rb1) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass(),-solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse); + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse); } else { solverConstraint.m_appliedImpulse = 0.f; @@ -583,9 +583,9 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m { frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; if (rb0) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].applyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].applyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); if (rb1) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass(),-frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse); + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].applyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse); } else { frictionConstraint1.m_appliedImpulse = 0.f; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index 467e37bb91f..90e7fc8354d 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -24,10 +24,7 @@ class btIDebugDraw; -///The btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses -///The approach is the 3D version of Erin Catto's GDC 2006 tutorial. See http://www.gphysics.com -///Although Sequential Impulse is more intuitive, it is mathematically equivalent to Projected Successive Overrelaxation (iterative LCP) -///Applies impulses for combined restitution and penetration recovery and to simulate friction +///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method. class btSequentialImpulseConstraintSolver : public btConstraintSolver { protected: diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h index 98c9876ae46..6b728959162 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -110,8 +110,8 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody BT_DECLARE_ALIGNED_ALLOCATOR(); btVector3 m_deltaLinearVelocity; btVector3 m_deltaAngularVelocity; - btScalar m_angularFactor; - btScalar m_invMass; + btVector3 m_angularFactor; + btVector3 m_invMass; btScalar m_friction; btRigidBody* m_originalBody; btVector3 m_pushVelocity; @@ -162,7 +162,7 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody void writebackVelocity(btScalar timeStep=0) { - if (m_invMass) + if (m_originalBody) { m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+m_deltaLinearVelocity); m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index 78a770231b3..14cbe831b40 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -30,7 +30,6 @@ enum btTypedConstraintType HINGE_CONSTRAINT_TYPE, CONETWIST_CONSTRAINT_TYPE, D6_CONSTRAINT_TYPE, - VEHICLE_CONSTRAINT_TYPE, SLIDER_CONSTRAINT_TYPE }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btActionInterface.h b/extern/bullet2/src/BulletDynamics/Dynamics/btActionInterface.h new file mode 100644 index 00000000000..8348795ef70 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btActionInterface.h @@ -0,0 +1,39 @@ +/* +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_ACTION_INTERFACE_H +#define _BT_ACTION_INTERFACE_H + +class btIDebugDraw; +class btCollisionWorld; + +#include "LinearMath/btScalar.h" + +///Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWorld +class btActionInterface +{ + public: + + virtual ~btActionInterface() + { + } + + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep)=0; + + virtual void debugDraw(btIDebugDraw* debugDrawer) = 0; + +}; + +#endif //_BT_ACTION_INTERFACE_H \ No newline at end of file diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp index 19443adc723..fa0d63d74a1 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp @@ -90,8 +90,7 @@ void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) integrateTransforms(timeStep * toi); ///update vehicle simulation - updateVehicles(timeStep); - + updateActions(timeStep); updateActivationState( timeStep ); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index ec803df06f7..ea2e0ad2a2b 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -51,17 +51,7 @@ subject to the following restrictions: #include "LinearMath/btIDebugDraw.h" - -//vehicle -#include "BulletDynamics/Vehicle/btRaycastVehicle.h" -#include "BulletDynamics/Vehicle/btVehicleRaycaster.h" -#include "BulletDynamics/Vehicle/btWheelInfo.h" -#ifdef USE_CHARACTER -//character -#include "BulletDynamics/Character/btCharacterControllerInterface.h" -#endif //USE_CHARACTER - -#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/Dynamics/btActionInterface.h" #include "LinearMath/btQuickprof.h" #include "LinearMath/btMotionState.h" @@ -214,32 +204,11 @@ void btDiscreteDynamicsWorld::debugDrawWorld() } - for ( i=0;im_vehicles.size();i++) + if (getDebugDrawer() && getDebugDrawer()->getDebugMode()) { - for (int v=0;vgetNumWheels();v++) + for (i=0;igetWheelInfo(v).m_raycastInfo.m_isInContact) - { - wheelColor.setValue(0,0,255); - } else - { - wheelColor.setValue(255,0,255); - } - - btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); - - btVector3 axle = btVector3( - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[0][m_vehicles[i]->getRightAxis()], - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[1][m_vehicles[i]->getRightAxis()], - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[2][m_vehicles[i]->getRightAxis()]); - - - //m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_wheelAxleWS - //debug wheels (cylinders) - m_debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); - m_debugDrawer->drawLine(wheelPosWS,m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); - + m_actions[i]->debugDraw(m_debugDrawer); } } } @@ -311,7 +280,7 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() synchronizeSingleMotionState(body); } } - +/* if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) { for ( int i=0;im_vehicles.size();i++) @@ -323,6 +292,8 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() } } } + */ + } @@ -428,10 +399,8 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) integrateTransforms(timeStep); ///update vehicle simulation - updateVehicles(timeStep); + updateActions(timeStep); - updateCharacters(timeStep); - updateActivationState( timeStep ); if(0 != m_internalTickCallback) { @@ -495,31 +464,15 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short } -void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) +void btDiscreteDynamicsWorld::updateActions(btScalar timeStep) { - BT_PROFILE("updateVehicles"); + BT_PROFILE("updateActions"); - for ( int i=0;iupdateVehicle( timeStep); + m_actions[i]->updateAction( this, timeStep); } } - -void btDiscreteDynamicsWorld::updateCharacters(btScalar timeStep) -{ -#ifdef USE_CHARACTER - BT_PROFILE("updateCharacters"); - - for ( int i=0;ipreStep (this); - character->playerStep (this,timeStep); - } -#endif //USE_CHARACTER -} - void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) @@ -576,28 +529,35 @@ void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint) constraint->getRigidBodyB().removeConstraintRef(constraint); } -void btDiscreteDynamicsWorld::addVehicle(btRaycastVehicle* vehicle) +void btDiscreteDynamicsWorld::addAction(btActionInterface* action) { - m_vehicles.push_back(vehicle); + m_actions.push_back(action); } -void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) +void btDiscreteDynamicsWorld::removeAction(btActionInterface* action) { - m_vehicles.remove(vehicle); + m_actions.remove(action); } -void btDiscreteDynamicsWorld::addCharacter(btCharacterControllerInterface* character) + +void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle) { -#ifdef USE_CHARACTER - m_characters.push_back(character); -#endif //USE_CHARACTER + addAction(vehicle); } -void btDiscreteDynamicsWorld::removeCharacter(btCharacterControllerInterface* character) +void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle) { -#ifdef USE_CHARACTER - m_characters.remove(character); -#endif //USE_CHARACTER + removeAction(vehicle); +} + +void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character) +{ + addAction(character); +} + +void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character) +{ + removeAction(character); } diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index 34d4e6b353f..4662cf5052a 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -23,10 +23,8 @@ class btOverlappingPairCache; class btConstraintSolver; class btSimulationIslandManager; class btTypedConstraint; +class btActionInterface; - -class btRaycastVehicle; -class btCharacterControllerInterface; class btIDebugDraw; #include "LinearMath/btAlignedObjectArray.h" @@ -52,12 +50,8 @@ protected: bool m_ownsIslandManager; bool m_ownsConstraintSolver; + btAlignedObjectArray m_actions; - btAlignedObjectArray m_vehicles; - - btAlignedObjectArray m_characters; - - int m_profileTimings; virtual void predictUnconstraintMotion(btScalar timeStep); @@ -70,9 +64,7 @@ protected: void updateActivationState(btScalar timeStep); - void updateVehicles(btScalar timeStep); - - void updateCharacters(btScalar timeStep); + void updateActions(btScalar timeStep); void startProfiling(btScalar timeStep); @@ -105,15 +97,10 @@ public: virtual void removeConstraint(btTypedConstraint* constraint); - virtual void addVehicle(btRaycastVehicle* vehicle); + virtual void addAction(btActionInterface*); - virtual void removeVehicle(btRaycastVehicle* vehicle); + virtual void removeAction(btActionInterface*); - virtual void addCharacter(btCharacterControllerInterface* character); - - virtual void removeCharacter(btCharacterControllerInterface* character); - - btSimulationIslandManager* getSimulationIslandManager() { return m_islandManager; @@ -130,6 +117,7 @@ public: } virtual void setGravity(const btVector3& gravity); + virtual btVector3 getGravity () const; virtual void addRigidBody(btRigidBody* body); @@ -171,6 +159,21 @@ public: (void) numTasks; } + ///obsolete, use updateActions instead + virtual void updateVehicles(btScalar timeStep) + { + updateActions(timeStep); + } + + ///obsolete, use addAction instead + virtual void addVehicle(btActionInterface* vehicle); + ///obsolete, use removeAction instead + virtual void removeVehicle(btActionInterface* vehicle); + ///obsolete, use addAction instead + virtual void addCharacter(btActionInterface* character); + ///obsolete, use removeAction instead + virtual void removeCharacter(btActionInterface* character); + }; #endif //BT_DISCRETE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 2d90e212f7a..ecf7a2f0c64 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -20,10 +20,10 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" class btTypedConstraint; -class btRaycastVehicle; +class btActionInterface; class btConstraintSolver; class btDynamicsWorld; -class btCharacterControllerInterface; + /// Type for the callback for each tick typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep); @@ -72,14 +72,9 @@ public: virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;} - virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} - - virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} - - virtual void addCharacter(btCharacterControllerInterface* character) {(void)character;} - - virtual void removeCharacter(btCharacterControllerInterface* character) {(void)character;} + virtual void addAction(btActionInterface* action) = 0; + virtual void removeAction(btActionInterface* action) = 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 @@ -129,6 +124,16 @@ public: } + ///obsolete, use addAction instead. + virtual void addVehicle(btActionInterface* vehicle) {(void)vehicle;} + ///obsolete, use removeAction instead + virtual void removeVehicle(btActionInterface* vehicle) {(void)vehicle;} + ///obsolete, use addAction instead. + virtual void addCharacter(btActionInterface* character) {(void)character;} + ///obsolete, use removeAction instead + virtual void removeCharacter(btActionInterface* character) {(void)character;} + + }; #endif //BT_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp index a2b8a7dade4..a4d8e1d77f6 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -44,7 +44,8 @@ void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& 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_angularFactor.setValue(1,1,1); + m_linearFactor.setValue(1,1,1); m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h index ec570cab875..da1fcb78611 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h @@ -45,7 +45,8 @@ class btRigidBody : public btCollisionObject btVector3 m_linearVelocity; btVector3 m_angularVelocity; btScalar m_inverseMass; - btScalar m_angularFactor; + btVector3 m_angularFactor; + btVector3 m_linearFactor; btVector3 m_gravity; btVector3 m_gravity_acceleration; @@ -219,6 +220,14 @@ public: void setMassProps(btScalar mass, const btVector3& inertia); + const btVector3& getLinearFactor() const + { + return m_linearFactor; + } + void setLinearFactor(const btVector3& linearFactor) + { + m_linearFactor = linearFactor; + } btScalar getInvMass() const { return m_inverseMass; } const btMatrix3x3& getInvInertiaTensorWorld() const { return m_invInertiaTensorWorld; @@ -230,7 +239,7 @@ public: void applyCentralForce(const btVector3& force) { - m_totalForce += force; + m_totalForce += force*m_linearFactor; } const btVector3& getTotalForce() @@ -261,23 +270,23 @@ public: void applyTorque(const btVector3& torque) { - m_totalTorque += torque; + m_totalTorque += torque*m_angularFactor; } void applyForce(const btVector3& force, const btVector3& rel_pos) { applyCentralForce(force); - applyTorque(rel_pos.cross(force)*m_angularFactor); + applyTorque(rel_pos.cross(force*m_linearFactor)); } void applyCentralImpulse(const btVector3& impulse) { - m_linearVelocity += impulse * m_inverseMass; + m_linearVelocity += impulse *m_linearFactor * m_inverseMass; } void applyTorqueImpulse(const btVector3& torque) { - m_angularVelocity += m_invInertiaTensorWorld * torque; + m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor; } void applyImpulse(const btVector3& impulse, const btVector3& rel_pos) @@ -287,7 +296,7 @@ public: applyCentralImpulse(impulse); if (m_angularFactor) { - applyTorqueImpulse(rel_pos.cross(impulse)*m_angularFactor); + applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor)); } } } @@ -297,10 +306,10 @@ public: { if (m_inverseMass != btScalar(0.)) { - m_linearVelocity += linearComponent*impulseMagnitude; + m_linearVelocity += linearComponent*m_linearFactor*impulseMagnitude; if (m_angularFactor) { - m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; + m_angularVelocity += angularComponent*m_angularFactor*impulseMagnitude; } } } @@ -450,11 +459,16 @@ public: int m_contactSolverType; int m_frictionSolverType; - void setAngularFactor(btScalar angFac) + void setAngularFactor(const btVector3& angFac) { m_angularFactor = angFac; } - btScalar getAngularFactor() const + + void setAngularFactor(btScalar angFac) + { + m_angularFactor.setValue(angFac,angFac,angFac); + } + const btVector3& getAngularFactor() const { return m_angularFactor; } diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp index 4982e673053..031fcb5b447 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -19,15 +19,13 @@ #include "btVehicleRaycaster.h" #include "btWheelInfo.h" #include "LinearMath/btMinMax.h" - - +#include "LinearMath/btIDebugDraw.h" #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; @@ -691,7 +689,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; - rel_pos[m_indexForwardAxis] *= wheelInfo.m_rollInfluence; + rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence; m_chassisBody->applyImpulse(sideImp,rel_pos); //apply friction impulse on the ground @@ -704,6 +702,36 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) } + +void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer) +{ + + for (int v=0;vgetNumWheels();v++) + { + btVector3 wheelColor(0,255,255); + if (getWheelInfo(v).m_raycastInfo.m_isInContact) + { + wheelColor.setValue(0,0,255); + } else + { + wheelColor.setValue(255,0,255); + } + + btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin(); + + btVector3 axle = btVector3( + getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()], + getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()], + getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]); + + //debug wheels (cylinders) + debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); + debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); + + } +} + + void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) { // RayResultCallback& resultCallback; @@ -727,3 +755,4 @@ void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& } return 0; } + diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h index bfe0d7df2fb..d5a299c606f 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -17,11 +17,12 @@ class btDynamicsWorld; #include "LinearMath/btAlignedObjectArray.h" #include "btWheelInfo.h" +#include "BulletDynamics/Dynamics/btActionInterface.h" class btVehicleTuning; ///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. -class btRaycastVehicle : public btTypedConstraint +class btRaycastVehicle : public btActionInterface { btAlignedObjectArray m_forwardWS; @@ -29,6 +30,11 @@ class btRaycastVehicle : public btTypedConstraint btAlignedObjectArray m_forwardImpulse; btAlignedObjectArray m_sideImpulse; + int m_userConstraintType; + + int m_userConstraintId; + + public: class btVehicleTuning { @@ -73,13 +79,24 @@ public: virtual ~btRaycastVehicle() ; - + + ///btActionInterface interface + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step) + { + updateVehicle(step); + } + + + ///btActionInterface interface + void debugDraw(btIDebugDraw* debugDrawer); + const btTransform& getChassisWorldTransform() const; btScalar rayCast(btWheelInfo& wheel); virtual void updateVehicle(btScalar step); - + + void resetSuspension(); btScalar getSteeringValue(int wheel) const; @@ -175,26 +192,24 @@ public: m_indexForwardAxis = forwardIndex; } - virtual void buildJacobian() + int getUserConstraintType() const { - //not yet + return m_userConstraintType ; } - virtual void getInfo1 (btConstraintInfo1* info) + void setUserConstraintType(int userConstraintType) { - info->m_numConstraintRows = 0; - info->nub = 0; + m_userConstraintType = userConstraintType; + }; + + void setUserConstraintId(int uid) + { + m_userConstraintId = uid; } - virtual void getInfo2 (btConstraintInfo2* info) + int getUserConstraintId() const { - btAssert(0); - } - - virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) - { - (void)timeStep; - //not yet + return m_userConstraintId; } diff --git a/extern/bullet2/src/LinearMath/btConvexHull.cpp b/extern/bullet2/src/LinearMath/btConvexHull.cpp index 16ababca522..419c752a1d9 100644 --- a/extern/bullet2/src/LinearMath/btConvexHull.cpp +++ b/extern/bullet2/src/LinearMath/btConvexHull.cpp @@ -262,8 +262,8 @@ int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray &al 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)); + btScalar s = btSin(SIMD_RADS_PER_DEG*(x)); + btScalar c = btCos(SIMD_RADS_PER_DEG*(x)); int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); if(ma==m && mb==m) { @@ -275,8 +275,8 @@ int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray &al 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)); + btScalar s = btSin(SIMD_RADS_PER_DEG*(xx)); + btScalar c = btCos(SIMD_RADS_PER_DEG*(xx)); int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); if(mc==m && md==m) { diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 7eec93dc402..97a0819147c 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -321,7 +321,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/ int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0); if (visualizePhysics) - ccdPhysEnv->setDebugMode(btIDebugDraw::DBG_DrawWireframe|btIDebugDraw::DBG_DrawAabb|btIDebugDraw::DBG_DrawContactPoints|btIDebugDraw::DBG_DrawText); + ccdPhysEnv->setDebugMode(btIDebugDraw::DBG_DrawWireframe|btIDebugDraw::DBG_DrawAabb|btIDebugDraw::DBG_DrawContactPoints|btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_DrawConstraintLimits|btIDebugDraw::DBG_DrawConstraints); //todo: get a button in blender ? //disable / enable debug drawing (contact points, aabb's etc) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 6504f77ec53..8f540417aae 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -337,6 +337,7 @@ m_ownDispatcher(NULL) // m_collisionConfiguration = new btDefaultCollisionConfiguration(); m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); + //m_collisionConfiguration->setConvexConvexMultipointIterations(); if (!dispatcher) { @@ -356,6 +357,7 @@ m_ownDispatcher(NULL) setSolverType(1);//issues with quickstep and memory allocations // m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + //m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.01f; //m_dynamicsWorld->getSolverInfo().m_solverMode= SOLVER_USE_WARMSTARTING + SOLVER_USE_2_FRICTION_DIRECTIONS + SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING; m_debugDrawer = 0; From 6e85d00055d414e6be34f4738790851a63223ab7 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 9 Mar 2009 05:01:16 +0000 Subject: [PATCH 242/252] Fix: The debug lines of Physics Debug Visualization were drawn incorrectly when using overlay scenes (it was using the wrong camera) --- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 5 +++++ .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 8 +++++--- .../Physics/Bullet/CcdPhysicsEnvironment.h | 2 ++ .../Physics/common/PHY_IPhysicsEnvironment.h | 2 ++ source/gameengine/Rasterizer/RAS_IRasterizer.h | 2 ++ .../RAS_OpenGLRasterizer.cpp | 16 +++++++++++++--- .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h | 2 ++ 7 files changed, 31 insertions(+), 6 deletions(-) diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 87f348799df..97b4213b8bd 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1112,6 +1112,11 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); + if (scene->GetPhysicsEnvironment()) + scene->GetPhysicsEnvironment()->debugDrawWorld(); + + m_rasterizer->FlushDebugLines(); + PostRenderFrame(); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 8f540417aae..dd21e58bd68 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -563,6 +563,11 @@ void CcdPhysicsEnvironment::beginFrame() } +void CcdPhysicsEnvironment::debugDrawWorld() +{ + if (m_dynamicsWorld->getDebugDrawer() && m_dynamicsWorld->getDebugDrawer()->getDebugMode() >0) + m_dynamicsWorld->debugDrawWorld(); +} bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) { @@ -599,9 +604,6 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) veh->SyncWheels(); } - if (m_dynamicsWorld->getDebugDrawer() && m_dynamicsWorld->getDebugDrawer()->getDebugMode() >0) - m_dynamicsWorld->debugDrawWorld(); - CallbackTriggers(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 4b28d3fddfc..2f1f0bb254b 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -110,6 +110,8 @@ protected: virtual void endFrame() {}; /// Perform an integration step of duration 'timeStep'. virtual bool proceedDeltaTime(double curTime,float timeStep); + + virtual void debugDrawWorld(); // virtual bool proceedDeltaTimeOneStep(float timeStep); virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep){}; diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 0e9c571924c..226ba3a7e74 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -90,6 +90,8 @@ class PHY_IPhysicsEnvironment virtual void endFrame() = 0; /// Perform an integration step of duration 'timeStep'. virtual bool proceedDeltaTime(double curTime,float timeStep)=0; + ///draw debug lines (make sure to call this during the render phase, otherwise lines are not drawn properly) + virtual void debugDrawWorld(){} virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)=0; //returns 0.f if no fixed timestep is used virtual float getFixedTimeStep()=0; diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index d529ca8973a..83adcfd8321 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -361,6 +361,8 @@ public: virtual void SetPolygonOffset(float mult, float add) = 0; virtual void DrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)=0; + virtual void FlushDebugLines()=0; + virtual void SetTexCoordNum(int num) = 0; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 08c600e7682..d4d1b73c772 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -327,13 +327,12 @@ void RAS_OpenGLRasterizer::ClearCachingInfo(void) m_materialCachingInfo = 0; } - -void RAS_OpenGLRasterizer::EndFrame() +void RAS_OpenGLRasterizer::FlushDebugLines() { +//DrawDebugLines glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); - //DrawDebugLines glBegin(GL_LINES); for (unsigned int i=0;iEndFrame(); } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index c72d4880437..83a9f759a8b 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -240,6 +240,8 @@ public: virtual void SetPolygonOffset(float mult, float add); + virtual void FlushDebugLines(); + virtual void DrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color) { OglDebugLine line; From 06d455f4280815c9197f8d9cb6c0cadcdfc5e838 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 9 Mar 2009 07:12:16 +0000 Subject: [PATCH 243/252] Add support to lock individual axis during rigid body simulation, for translation and rotation. This makes it easier to do 1D or 2D physics (tetris, blockout) todo: create some example/demo.blend. --- source/blender/makesdna/DNA_object_types.h | 6 ++ source/blender/src/buttons_logic.c | 70 ++++++++++++++++++- .../Converter/BL_BlenderDataConversion.cpp | 6 ++ .../Ketsji/KX_ConvertPhysicsObject.h | 8 +++ .../Ketsji/KX_ConvertPhysicsObjects.cpp | 20 +++++- 5 files changed, 105 insertions(+), 5 deletions(-) diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index b885bbf084e..b17896aec70 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -440,6 +440,12 @@ extern Object workob; /* ob->gameflag2 */ #define OB_NEVER_DO_ACTIVITY_CULLING 1 +#define OB_LOCK_RIGID_BODY_X_AXIS 4 +#define OB_LOCK_RIGID_BODY_Y_AXIS 8 +#define OB_LOCK_RIGID_BODY_Z_AXIS 16 +#define OB_LOCK_RIGID_BODY_X_ROT_AXIS 32 +#define OB_LOCK_RIGID_BODY_Y_ROT_AXIS 64 +#define OB_LOCK_RIGID_BODY_Z_ROT_AXIS 128 #define OB_LIFE (OB_PROP|OB_DYNAMIC|OB_ACTOR|OB_MAINACTOR|OB_CHILD) diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 775175ba332..10718c74a4b 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -3058,12 +3058,14 @@ static uiBlock *advanced_bullet_menu(void *arg_ob) block= uiNewBlock(&curarea->uiblocks, "advanced_bullet_options", UI_EMBOSS, UI_HELV, curarea->win); /* use this for a fake extra empy space around the buttons */ - uiDefBut(block, LABEL, 0, "", -10, -10, 380, 60, NULL, 0, 0, 0, 0, ""); + if (ob->gameflag & OB_SOFT_BODY) { + uiDefBut(block, LABEL, 0, "", -10, -10, 380, 60, NULL, 0, 0, 0, 0, ""); if (ob->bsoft) { + uiBlockBeginAlign(block); uiDefButBitI(block, TOG, OB_BSB_COL_CL_RS, 0, "Cluster Collision RS", @@ -3106,16 +3108,78 @@ static uiBlock *advanced_bullet_menu(void *arg_ob) xco = 0; + if (ob->gameflag & OB_DYNAMIC) { + + yco = 100; + uiDefBut(block, LABEL, 0, "", -10, -10, 380, 120, NULL, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); if (ob->margin < 0.001f) ob->margin = 0.06f; uiDefButF(block, NUM, 0, "Margin", - xco, yco, 170, 19, &ob->margin, 0.001, 1.0, 1, 0, + xco, yco, 180, 19, &ob->margin, 0.001, 1.0, 1, 0, "Collision margin"); + yco -= 20; + + uiDefButBitI(block, TOG, OB_LOCK_RIGID_BODY_X_AXIS, 0, "Lock X Axis", + xco, yco, 180, 19, &ob->gameflag2, 0, 0, 0, 0, + "Disable simulation of linear motion along the X axis"); + uiDefButBitI(block, TOG, OB_LOCK_RIGID_BODY_X_ROT_AXIS, 0, "Lock X Rot Xxis", + xco+=180, yco, 180, 19, &ob->gameflag2, 0, 0, 0, 0, + "Disable simulation of angular motion along the X axis"); + yco -= 20; + xco=0; + uiDefButBitI(block, TOG, OB_LOCK_RIGID_BODY_Y_AXIS, 0, "Lock Y Axis", + xco, yco, 180, 19, &ob->gameflag2, 0, 0, 0, 0, + "Disable simulation of linear motion along the Y axis"); + uiDefButBitI(block, TOG, OB_LOCK_RIGID_BODY_Y_ROT_AXIS, 0, "Lock Y Rot Axis", + xco+=180, yco, 180, 19, &ob->gameflag2, 0, 0, 0, 0, + "Disable simulation of angular motion along the Y axis"); + + yco -= 20; + xco=0; + uiDefButBitI(block, TOG, OB_LOCK_RIGID_BODY_Z_AXIS, 0, "Lock Z Axis", + xco, yco, 180, 19, &ob->gameflag2, 0, 0, 0, 0, + "Disable simulation of linear motion along the Z axis"); + uiDefButBitI(block, TOG, OB_LOCK_RIGID_BODY_Z_ROT_AXIS, 0, "Lock Z Rot Axis", + xco+=180, yco, 180, 19, &ob->gameflag2, 0, 0, 0, 0, + "Disable simulation of angular motion along the Z axis"); + + /* + uiDefButBitI(block, TOG, OB_BSB_COL_CL_RS, 0, "Cluster Collision RS", + xco, yco, 180, 19, &ob->bsoft->collisionflags, 0, 0, 0, 0, + "Enable cluster collision between soft and rigid body"); + uiDefButBitI(block, TOG, OB_BSB_COL_CL_SS, 0, "Cluster Collision SS", + xco+=180, yco, 180, 19, &ob->bsoft->collisionflags, 0, 0, 0, 0, + "Enable cluster collision between soft and soft body"); + yco -= 20; + xco = 0; + uiDefButI(block, NUM, 0, "Cluster Iter.", + xco, yco, 180, 19, &ob->bsoft->numclusteriterations, 1.0, 128., + 0, 0, "Specify the number of cluster iterations"); + uiDefButI(block, NUM, 0, "Position Iter.", + xco+=180, yco, 180, 19, &ob->bsoft->piterations, 0, 10, + 0, 0, "Position solver iterations"); + #define OB_LOCK_RIGID_BODY_X_AXIS 4 + #define OB_LOCK_RIGID_BODY_Y_AXIS 8 + #define OB_LOCK_RIGID_BODY_Z_AXIS 16 + #define OB_LOCK_RIGID_BODY_X_ROT_AXIS 32 + #define OB_LOCK_RIGID_BODY_Y_ROT_AXIS 64 + #define OB_LOCK_RIGID_BODY_Z_ROT_AXIS 128 + */ + + uiBlockEndAlign(block); + + + + + } else { + + uiDefBut(block, LABEL, 0, "", -10, -10, 380, 60, NULL, 0, 0, 0, 0, ""); uiDefButF(block, NUM, 0, "Margin", - xco, yco, 170, 19, &ob->margin, 0.0, 1.0, 1, 0, + xco, yco, 180, 19, &ob->margin, 0.0, 1.0, 1, 0, "Collision margin"); } yco -= 20; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 3a0302562e6..d74243b0eb0 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1315,6 +1315,12 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, CreateMaterialFromBlenderObject(blenderobject, kxscene); KX_ObjectProperties objprop; + objprop.m_lockXaxis = (blenderobject->gameflag2 & OB_LOCK_RIGID_BODY_X_AXIS) !=0; + objprop.m_lockYaxis = (blenderobject->gameflag2 & OB_LOCK_RIGID_BODY_Y_AXIS) !=0; + objprop.m_lockZaxis = (blenderobject->gameflag2 & OB_LOCK_RIGID_BODY_Z_AXIS) !=0; + objprop.m_lockXRotaxis = (blenderobject->gameflag2 & OB_LOCK_RIGID_BODY_X_ROT_AXIS) !=0; + objprop.m_lockYRotaxis = (blenderobject->gameflag2 & OB_LOCK_RIGID_BODY_Y_ROT_AXIS) !=0; + objprop.m_lockZRotaxis = (blenderobject->gameflag2 & OB_LOCK_RIGID_BODY_Z_ROT_AXIS) !=0; objprop.m_isCompoundChild = isCompoundChild; objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index edacf38ab43..3534500e619 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -127,6 +127,14 @@ struct KX_ObjectProperties ///////////////////////// + bool m_lockXaxis; + bool m_lockYaxis; + bool m_lockZaxis; + bool m_lockXRotaxis; + bool m_lockYRotaxis; + bool m_lockZRotaxis; + + ///////////////////////// double m_margin; KX_BoundBoxClass m_boundclass; union { diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 46e46b014b5..602486e0017 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -1101,8 +1101,24 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, { btRigidBody* rbody = physicscontroller->GetRigidBody(); - if (rbody && objprop->m_disableSleeping) - rbody->setActivationState(DISABLE_DEACTIVATION); + if (rbody) + { + btVector3 linearFactor( + objprop->m_lockXaxis? 0 : 1, + objprop->m_lockYaxis? 0 : 1, + objprop->m_lockZaxis? 0 : 1); + btVector3 angularFactor( + objprop->m_lockXRotaxis? 0 : 1, + objprop->m_lockYRotaxis? 0 : 1, + objprop->m_lockZRotaxis? 0 : 1); + rbody->setLinearFactor(linearFactor); + rbody->setAngularFactor(angularFactor); + + if (rbody && objprop->m_disableSleeping) + { + rbody->setActivationState(DISABLE_DEACTIVATION); + } + } } CcdPhysicsController* parentCtrl = objprop->m_dynamic_parent ? (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController() : 0; From 4a089890df818636be28a3f494c5851c2c0b1efd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 10 Mar 2009 06:58:42 +0000 Subject: [PATCH 244/252] [#18388] PLY Import fails if line ending is not \n bugfix, read the header as ascii text - open(filename, 'rU'), only the body as binary. --- release/scripts/ply_import.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/release/scripts/ply_import.py b/release/scripts/ply_import.py index 302e21a0a43..43129ec01e9 100644 --- a/release/scripts/ply_import.py +++ b/release/scripts/ply_import.py @@ -160,13 +160,16 @@ def read(filename): obj_spec = object_spec() try: - file = open(filename, 'rb') + file = open(filename, 'rU') # Only for parsing the header, not binary data signature = file.readline() - if (signature != 'ply\n'): + + if not signature.startswith('ply'): print 'Signature line was invalid' return None + while 1: tokens = re.split(r'[ \n]+', file.readline()) + if (len(tokens) == 0): continue if (tokens[0] == 'end_header'): @@ -197,14 +200,22 @@ def read(filename): obj_spec.specs[-1].properties.append(property_spec(tokens[4], type_specs[tokens[2]], type_specs[tokens[3]])) else: obj_spec.specs[-1].properties.append(property_spec(tokens[2], None, type_specs[tokens[1]])) + + if format != 'ascii': + file.close() # was ascii, now binary + file = open(filename, 'rb') + + # skip the header... + while not file.readline().startswith('end_header'): + pass + obj = obj_spec.load(format_specs[format], file) - + except IOError, (errno, strerror): try: file.close() except: pass return None - try: file.close() except: pass From d17ca2179d7a2dc4e77dd427fdfb416929a454c7 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Tue, 10 Mar 2009 16:04:29 +0000 Subject: [PATCH 245/252] Addes libopenjpeg (jpeg2000) support to the Makefiles Kent --- extern/Makefile | 4 +++ extern/libopenjpeg/Makefile | 43 +++++++++++++++++++++++ source/Makefile | 4 +++ source/blender/blenkernel/intern/Makefile | 4 +++ source/blender/imbuf/intern/Makefile | 4 +++ source/blender/src/Makefile | 4 +++ source/creator/Makefile | 3 ++ source/nan_definitions.mk | 1 + 8 files changed, 67 insertions(+) create mode 100644 extern/libopenjpeg/Makefile diff --git a/extern/Makefile b/extern/Makefile index 51213698ebb..38bec4b73dd 100644 --- a/extern/Makefile +++ b/extern/Makefile @@ -57,6 +57,10 @@ ifeq ($(WITH_BINRELOC), true) DIRS += binreloc endif +ifeq ($(WITH_OPENJPEG), true) + DIRS += libopenjpeg +endif + TARGET = solid all:: diff --git a/extern/libopenjpeg/Makefile b/extern/libopenjpeg/Makefile new file mode 100644 index 00000000000..15d9d9c7c01 --- /dev/null +++ b/extern/libopenjpeg/Makefile @@ -0,0 +1,43 @@ +# +# $Id: Makefile 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) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL LICENSE BLOCK ***** +# +# + +LIBNAME = openjpeg +DIR = $(OCGDIR)/extern/$(LIBNAME) + +CCFLAGS += $(LEVEL_1_CPP_WARNINGS) + +TCSRCS = $(wildcard *.c) +CSRCS = $(filter-out t1_generate_luts.c,$(TCSRCS)) + +include nan_compile.mk +CPPFLAGS += -I. + +install: all debug + diff --git a/source/Makefile b/source/Makefile index e9671cdae35..fae14ba6c97 100644 --- a/source/Makefile +++ b/source/Makefile @@ -171,6 +171,10 @@ ifeq ($(WITH_OPENEXR), true) COMLIB += $(OCGDIR)/blender/imbuf/openexr/$(DEBUG_DIR)libopenexr.a endif +ifeq ($(WITH_OPENJPEG), true) + COMLIB += $(OCGDIR)/extern/openjpeg/$(DEBUG_DIR)libopenjpeg.a +endif + COMLIB += $(OCGDIR)/blender/imbuf/cineon/$(DEBUG_DIR)libcineon.a ifeq ($(WITH_DDS), true) diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 8921ea5d3b7..226e416dad7 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -108,6 +108,10 @@ ifeq ($(WITH_DDS), true) CPPFLAGS += -DWITH_DDS endif +ifeq ($(WITH_OPENJPEG), true) + CPPFLAGS += -DWITH_OPENJPEG +endif + ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -I../../quicktime CPPFLAGS += -DWITH_QUICKTIME diff --git a/source/blender/imbuf/intern/Makefile b/source/blender/imbuf/intern/Makefile index 8294931b60f..427052cbdc3 100644 --- a/source/blender/imbuf/intern/Makefile +++ b/source/blender/imbuf/intern/Makefile @@ -48,6 +48,10 @@ ifeq ($(WITH_DDS), true) CPPFLAGS += -DWITH_DDS endif +ifeq ($(WITH_OPENJPEG), true) + CFLAGS += -DWITH_OPENJPEG -I../../../../extern/libopenjpeg +endif + CFLAGS += $(LEVEL_1_C_WARNINGS) CPPFLAGS += -I$(NAN_JPEG)/include diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile index 46e916b0437..43d72a84c48 100644 --- a/source/blender/src/Makefile +++ b/source/blender/src/Makefile @@ -127,6 +127,10 @@ ifeq ($(WITH_DDS),true) CPPFLAGS += -DWITH_DDS endif +ifeq ($(WITH_OPENJPEG),true) + CPPFLAGS += -DWITH_OPENJPEG +endif + ifeq ($(INTERNATIONAL), true) CPPFLAGS += -DINTERNATIONAL endif diff --git a/source/creator/Makefile b/source/creator/Makefile index 9273d943883..97bfbeb5eb0 100644 --- a/source/creator/Makefile +++ b/source/creator/Makefile @@ -58,6 +58,9 @@ CPPFLAGS += -I$(NAN_GLEW)/include ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -I$(NAN_QUICKTIME)/include -DWITH_QUICKTIME endif +ifeq ($(WITH_OPENJPEG), true) + CPPFLAGS += -DWITH_OPENJPEG +endif ifeq ($(WITH_BINRELOC), true) CPPFLAGS += -I$(NANBLENDERHOME)/extern/binreloc/include -DWITH_BINRELOC diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 3961e153cea..764ecf3d556 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -115,6 +115,7 @@ endif export WITH_OPENEXR ?= true export WITH_DDS ?= true + export WITH_OPENJPEG ?= true ifeq ($(OS),windows) export NAN_WINTAB ?= $(LCGDIR)/wintab From 943d85131af972fb5828626b139f3d8bcc448774 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Tue, 10 Mar 2009 16:06:59 +0000 Subject: [PATCH 246/252] remove decimation and opennl libs from gameengine. Kent --- source/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/Makefile b/source/Makefile index fae14ba6c97..8811ab86911 100644 --- a/source/Makefile +++ b/source/Makefile @@ -92,7 +92,6 @@ GRPLIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a # to properly resolve circular dependencies. ugly, but it works... # the repeat entries could probably be trimmed down. COMLIB = $(OCGDIR)/blender/blenkernel/$(DEBUG_DIR)libblenkernel.a -COMLIB += $(NAN_DECIMATION)/lib/libdecimation.a COMLIB += $(OCGDIR)/blender/blenloader/$(DEBUG_DIR)libblenloader.a COMLIB += $(OCGDIR)/blender/blenpluginapi/$(DEBUG_DIR)libblenpluginapi.a COMLIB += $(OCGDIR)/blender/nodes_shd/$(DEBUG_DIR)libnodes_shd.a @@ -102,7 +101,6 @@ 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 @@ -235,6 +233,7 @@ ifeq ($(WITH_OPENEXR), true) endif PULIB = $(NAN_MOTO)/lib/libmoto.a +PULIB += $(NAN_DECIMATION)/lib/libdecimation.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 From 0ac3e7016048a7e66285b3539c6e86cf83a4cb06 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Wed, 11 Mar 2009 02:58:18 +0000 Subject: [PATCH 247/252] removed extra space in text. Kent --- source/blender/src/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 302bdf00e99..0ce1512e2de 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -2030,7 +2030,7 @@ void initlocalview() locallay= free_localbit(); if(locallay==0) { - error("Sorry, no more than 8 localviews"); + error("Sorry, no more than 8 localviews"); ok= 0; } else { From a37cec2802d96306426f41c64f6ed69ab3680355 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 11 Mar 2009 22:11:52 +0000 Subject: [PATCH 248/252] BGE patch 18368: Modulus (ie %) expression controller in BGE. Implement a cache for the expression for better performance. --- source/gameengine/Expressions/FloatValue.cpp | 6 ++++ source/gameengine/Expressions/InputParser.cpp | 5 +++ source/gameengine/Expressions/InputParser.h | 1 + source/gameengine/Expressions/IntValue.cpp | 6 ++++ source/gameengine/Expressions/Value.cpp | 9 ++++- source/gameengine/Expressions/Value.h | 1 + .../GameLogic/SCA_ExpressionController.cpp | 35 ++++++++++++++----- .../GameLogic/SCA_ExpressionController.h | 6 ++++ source/gameengine/GameLogic/SCA_ILogicBrick.h | 1 + source/gameengine/GameLogic/SCA_IObject.cpp | 4 ++- source/gameengine/GameLogic/SCA_ISensor.h | 5 --- .../gameengine/GameLogic/SCA_PropertySensor.h | 4 +++ 12 files changed, 68 insertions(+), 15 deletions(-) diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp index 93f102d04a6..460eaa73f35 100644 --- a/source/gameengine/Expressions/FloatValue.cpp +++ b/source/gameengine/Expressions/FloatValue.cpp @@ -127,6 +127,9 @@ ret: a new object containing the result of applying operator op to val and { switch (op) { + case VALUE_MOD_OPERATOR: + ret = new CFloatValue(fmod(((CIntValue *) val)->GetInt(), m_float)); + break; case VALUE_ADD_OPERATOR: ret = new CFloatValue(((CIntValue *) val)->GetInt() + m_float); break; @@ -171,6 +174,9 @@ ret: a new object containing the result of applying operator op to val and { switch (op) { + case VALUE_MOD_OPERATOR: + ret = new CFloatValue(fmod(((CFloatValue *) val)->GetFloat(), m_float)); + break; case VALUE_ADD_OPERATOR: ret = new CFloatValue(((CFloatValue *) val)->GetFloat() + m_float); break; diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index e016fb8d007..94663c4a365 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -175,6 +175,9 @@ void CParser::NextSym() case ',': sym = commasym; NextCh(); break; + case '%' : + sym = opsym; opkind = OPmodulus; NextCh(); + break; case '+' : sym = opsym; opkind = OPplus; NextCh(); break; @@ -370,6 +373,7 @@ int CParser::Priority(int optorkind) { case OPunequal: return 3; case OPplus: case OPminus: return 4; + case OPmodulus: case OPtimes: case OPdivide: return 5; } @@ -390,6 +394,7 @@ CExpression *CParser::Ex(int i) { NextSym(); e2 = Ex(i + 1); switch(opkind2) { + case OPmodulus: e1 = new COperator2Expr(VALUE_MOD_OPERATOR,e1, e2); break; case OPplus: e1 = new COperator2Expr(VALUE_ADD_OPERATOR,e1, e2); break; case OPminus: e1 = new COperator2Expr(VALUE_SUB_OPERATOR,e1, e2); break; case OPtimes: e1 = new COperator2Expr(VALUE_MUL_OPERATOR,e1, e2); break; diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h index 4caa47cbb0c..f51c473ba18 100644 --- a/source/gameengine/Expressions/InputParser.h +++ b/source/gameengine/Expressions/InputParser.h @@ -49,6 +49,7 @@ private: }; // all kinds of symbols enum optype { + OPmodulus, OPplus, OPminus, OPtimes, diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp index fbf4f4f59e0..fb586cb4979 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/IntValue.cpp @@ -125,6 +125,9 @@ this object case VALUE_INT_TYPE: { switch (op) { + case VALUE_MOD_OPERATOR: + ret = new CIntValue (((CIntValue *) val)->GetInt() % m_int); + break; case VALUE_ADD_OPERATOR: ret = new CIntValue (((CIntValue *) val)->GetInt() + m_int); break; @@ -181,6 +184,9 @@ this object case VALUE_FLOAT_TYPE: { switch (op) { + case VALUE_MOD_OPERATOR: + ret = new CFloatValue(fmod(((CFloatValue *) val)->GetFloat(), m_int)); + break; case VALUE_ADD_OPERATOR: ret = new CFloatValue (((CFloatValue *) val)->GetFloat() + m_int); break; diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index d29e3961c65..ebb12636ac2 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -52,6 +52,10 @@ PyObject* cvalue_div(PyObject*v, PyObject*w) { return ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w); } +PyObject* cvalue_mod(PyObject*v, PyObject*w) +{ + return ((CValue*)v)->Calc(VALUE_MOD_OPERATOR,(CValue*)w); +} PyObject* cvalue_neg(PyObject*v) { return ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v); @@ -112,7 +116,7 @@ static PyNumberMethods cvalue_as_number = { (binaryfunc)cvalue_sub, /*nb_subtract*/ (binaryfunc)cvalue_mul, /*nb_multiply*/ (binaryfunc)cvalue_div, /*nb_divide*/ - 0,//(binaryfunc)cvalue_remainder, /*nb_remainder*/ + (binaryfunc)cvalue_mod, /*nb_remainder*/ 0,//(binaryfunc)cvalue_divmod, /*nb_divmod*/ 0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/ (unaryfunc)cvalue_neg, /*nb_negative*/ @@ -257,6 +261,9 @@ STR_String CValue::op2str (VALUE_OPERATOR op) STR_String opmsg; switch (op) { + case VALUE_MOD_OPERATOR: + opmsg = " % "; + break; case VALUE_ADD_OPERATOR: opmsg = " + "; break; diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 854334b892b..caf1064dc32 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -75,6 +75,7 @@ enum VALUE_OPERATOR { + VALUE_MOD_OPERATOR, // % VALUE_ADD_OPERATOR, // + VALUE_SUB_OPERATOR, // - VALUE_MUL_OPERATOR, // * diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp index e9a543c9f31..8ed46beb7f3 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp +++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp @@ -49,7 +49,8 @@ SCA_ExpressionController::SCA_ExpressionController(SCA_IObject* gameobj, const STR_String& exprtext, PyTypeObject* T) :SCA_IController(gameobj,T), - m_exprText(exprtext) + m_exprText(exprtext), + m_exprCache(NULL) { } @@ -57,6 +58,8 @@ SCA_ExpressionController::SCA_ExpressionController(SCA_IObject* gameobj, SCA_ExpressionController::~SCA_ExpressionController() { + if (m_exprCache) + m_exprCache->Release(); } @@ -65,6 +68,7 @@ CValue* SCA_ExpressionController::GetReplica() { SCA_ExpressionController* replica = new SCA_ExpressionController(*this); replica->m_exprText = m_exprText; + replica->m_exprCache = NULL; // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -72,18 +76,32 @@ CValue* SCA_ExpressionController::GetReplica() } +// Forced deletion of precalculated expression to break reference loop +// Use this function when you know that you won't use the sensor anymore +void SCA_ExpressionController::Delete() +{ + if (m_exprCache) + { + m_exprCache->Release(); + m_exprCache = NULL; + } + Release(); +} + void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr) { bool expressionresult = false; - - CParser parser; - parser.SetContext(this->AddRef()); - CExpression* expr = parser.ProcessText(m_exprText); - if (expr) + if (!m_exprCache) { - CValue* value = expr->Calculate(); + CParser parser; + parser.SetContext(this->AddRef()); + m_exprCache = parser.ProcessText(m_exprText); + } + if (m_exprCache) + { + CValue* value = m_exprCache->Calculate(); if (value) { if (value->IsError()) @@ -97,7 +115,8 @@ void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr) value->Release(); } - expr->Release(); + //m_exprCache->Release(); + //m_exprCache = NULL; } /* diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h index 20e1eb77771..79c26eea1e7 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.h +++ b/source/gameengine/GameLogic/SCA_ExpressionController.h @@ -38,6 +38,7 @@ class SCA_ExpressionController : public SCA_IController { // Py_Header; STR_String m_exprText; + CExpression* m_exprCache; public: SCA_ExpressionController(SCA_IObject* gameobj, @@ -48,6 +49,11 @@ public: virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); virtual CValue* FindIdentifier(const STR_String& identifiername); + /** + * used to release the expression cache + * so that self references are removed before the controller itself is released + */ + virtual void Delete(); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index cde1353275b..70d49941613 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -62,6 +62,7 @@ public: SCA_IObject* GetParent(); virtual void ReParent(SCA_IObject* parent); virtual void Relink(GEN_Map *obj_map); + virtual void Delete() { Release(); } // act as a BoolValue (with value IsPositiveTrigger) virtual CValue* Calc(VALUE_OPERATOR op, CValue *val); diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index d8f5f3eede5..debd62d44e6 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -59,7 +59,9 @@ SCA_IObject::~SCA_IObject() SCA_ControllerList::iterator itc; for (itc = m_controllers.begin(); !(itc == m_controllers.end()); ++itc) { - ((CValue*)(*itc))->Release(); + //Use Delete for controller to ensure proper cleaning (expression controller) + (*itc)->Delete(); + //((CValue*)(*itc))->Release(); } SCA_ActuatorList::iterator ita; for (ita = m_registeredActuators.begin(); !(ita==m_registeredActuators.end()); ++ita) diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 5ae7ced2a2a..23f2c76c19f 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -105,11 +105,6 @@ public: bool negmode, int freq); - /** Release sensor - * For property sensor, it is used to release the pre-calculated expression - * so that self references are removed before the sensor itself is released - */ - virtual void Delete() { Release(); } /** Set inversion of pulses on or off. */ void SetInvert(bool inv); /** set the level detection on or off */ diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index 933de49de18..2594e3fca9d 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -70,6 +70,10 @@ public: KX_PROPSENSOR_TYPE checktype, PyTypeObject* T=&Type ); + /** + * For property sensor, it is used to release the pre-calculated expression + * so that self references are removed before the sensor itself is released + */ virtual void Delete(); virtual ~SCA_PropertySensor(); virtual CValue* GetReplica(); From 39acb4efa4c3f35806f5dc37124ff1028eb18215 Mon Sep 17 00:00:00 2001 From: Stefan Gartner Date: Fri, 13 Mar 2009 10:22:49 +0000 Subject: [PATCH 249/252] Makefiles: fix definitions of NAN_OPENEXR_* variables on linux, patch provided by GSR --- source/nan_definitions.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 764ecf3d556..cc7561ff9b1 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -140,9 +140,9 @@ endif else ifeq ($(OS),linux) ifeq ($(WITH_OPENEXR), true) - NAN_OPENEXR?=$(shell pkg-config --variable=prefix OpenEXR ) - NAN_OPENEXR_INC?=$(shell pkg-config --cflags OpenEXR ) - NAN_OPENEXR_LIBS?=$(addprefix ${NAN_OPENEXR}/lib/lib,$(addsuffix .a,$(shell pkg-config --libs-only-l OpenEXR | sed -s "s/-l//g" ))) + export NAN_OPENEXR?=$(shell pkg-config --variable=prefix OpenEXR ) + export NAN_OPENEXR_INC?=$(shell pkg-config --cflags OpenEXR ) + export NAN_OPENEXR_LIBS?=$(addprefix ${NAN_OPENEXR}/lib/lib,$(addsuffix .a,$(shell pkg-config --libs-only-l OpenEXR | sed -s "s/-l//g" ))) endif else ifeq ($(OS), solaris) From e0b629fe71fa184a0cdd08ab4e7f6ddfce654623 Mon Sep 17 00:00:00 2001 From: Remigiusz Fiedler Date: Fri, 13 Mar 2009 23:35:15 +0000 Subject: [PATCH 250/252] update v1.12 - 2009.03.14 by migius d3 removed all set()functions (problem with osx/python<2.4 reported by Blinkozo) d3 code-cleaning d2 temp patch for noname BLOCKS (*X,*U,*D) --- release/scripts/import_dxf.py | 408 +++++++++------------------------- 1 file changed, 109 insertions(+), 299 deletions(-) diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py index 6a1981bb262..c3203891c60 100644 --- a/release/scripts/import_dxf.py +++ b/release/scripts/import_dxf.py @@ -7,7 +7,7 @@ Group: 'Import' Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).' """ __author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)' -__version__ = '1.12 - 2008.11.16 by migius' +__version__ = '1.12 - 2009.03.14 by migius' __url__ = ["http://blenderartists.org/forum/showthread.php?t=84319", "http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"] __email__ = ["migius(at)4d-vectors.de","Kitsune_e(at)yahoo.com"] @@ -15,7 +15,7 @@ __bpydoc__ = """\ This script imports objects from DXF (2d/3d) into Blender. This script imports 2d and 3d geometery from DXF files. -Supported DXF format versions: from (r2.5) r12 up to 2008. +Supported DXF format versions: from (r2.5) r12 up to r2008. Enhanced features are: - configurable object filtering and geometry manipulation, - configurable material pre-processing, @@ -32,7 +32,7 @@ MINSERT (=array of blocks), CIRCLE, ARC, 3DFACE, -2d-POLYLINE (=plane, incl. arc, variable-width, curve, spline), +2d-POLYLINE (=in plane, incl. arc, variable-width, curve, spline), 3d-POLYLINE (=non-plane), 3d-POLYMESH, 3d-POLYFACE, @@ -57,7 +57,7 @@ Supported layout modes: "model space" is default, "paper space" as option (= "layout views") -Supported scene definition objescts produced with AVE_RENDER: +Supported scene definition objects produced with AVE_RENDER: scene: selection of lights assigned to the camera, lights: DIRECT, OVERHEAD, SH_SPOT, (wip v1.13 import of AVE_RENDER material definitions) @@ -88,7 +88,7 @@ in creating new objects in scene database - probably a database management probl """ History: - v1.0 - 2007/2008 by migius + v1.0 - 2007/2008/2009 by migius planned tasks: -- (to see more, search for "--todo--" in script code) -- command-line-mode/batch-mode @@ -111,6 +111,11 @@ History: -- support ortho mode for VIEWs and VPORTs as cameras + v1.12 - 2009.03.14 by migius + d3 removed all set()functions (problem with osx/python<2.4 reported by Blinkozo) + d3 code-cleaning + v1.12 - 2009.01.14 by migius + d2 temp patch for noname BLOCKS (*X,*U,*D) v1.12 - 2008.11.16 by migius d1 remove try_finally: cause not supported in python <2.5 d1 add Bezier curves bevel radius support (default 1.0) @@ -309,9 +314,17 @@ from dxfReader import readDXF #from dxfReader import get_name, get_layer from dxfReader import Object as dxfObject from dxfColorMap import color_map - from math import * +# osx-patch by Blinkozo +#todo: avoid additional modules, prefer Blender-build-in test routines +#import platform +#if platform.python_version() < '2.4': +# from sets import Set as set +#from sys import version_info +#ver = '%s.%s' % version_info[0:2] +# end osx-patch + try: import os if os.name != 'mac': @@ -950,7 +963,7 @@ class Point: #----------------------------------------------------------------- if thic < settings.var['dist_min']: thic = settings.var['dist_min'] if points_as in [1,3,4,5]: - if True: # points_as in [1,5]: # as 'empty' + if points_as in [1,5]: # as 'empty' c = 'Empty' elif points_as == 3: # as 'thin sphere' res = settings.var['thin_res'] @@ -1276,66 +1289,6 @@ class Polyline: #-------------------------------------------------------------- pline = Curve.New(obname) # create new curve data #pline.setResolu(24) #--todo----- - if False: #old self.spline: # NURBSplines-----OK----- - #print 'deb:polyline2dCurve.draw self.spline!' #--------------- - weight1 = 0.5 - weight2 = 1.0 - if self.curvQuadrati: - # Bezier-curve form simulated in NURBS-curve - # generate middlepoints except start/end-segments --- - #print 'deb:polyline2dCurve.draw extraQBspline!' #--------------- - temp_points = [] - point = d_points[0].loc - point.append(weight1) - temp_points.append(point) - for i in xrange(1,len(d_points)-2): - point1 = d_points[i].loc - point2 = d_points[i+1].loc - mpoint = list((Mathutils.Vector(point1) + Mathutils.Vector(point2)) * 0.5) - mpoint.append(weight2) - point1.append(weight1) - temp_points.append(point1) - temp_points.append(mpoint) - point2.append(weight1) - temp_points.append(point2) - point = d_points[-1].loc - point.append(weight1) - temp_points.append(point) - d_points = temp_points - else: - temp_points = [] - for d in d_points: - d = d.loc - d.append(weight1) - temp_points.append(d) - d_points = temp_points - - if not self.closed: - # generate extended startpoint and endpoint------ - point1 = Mathutils.Vector(d_points[0][:3]) - point2 = Mathutils.Vector(d_points[1][:3]) - startpoint = list(point1 - point2 + point1) - startpoint.append(weight1) - point1 = Mathutils.Vector(d_points[-1][:3]) - point2 = Mathutils.Vector(d_points[-2][:3]) - endpoint = list(point1 - point2 + point1) - endpoint.append(weight1) - temp_points = [] - temp_points.append(startpoint) - temp_points.extend(d_points) - d_points = temp_points - d_points.append(endpoint) - - point = d_points[0] - curve = pline.appendNurb(point) - curve.setType(4) #NURBS curve - for point in d_points[1:]: - curve.append(point) - if self.closed: - curve.flagU = 1 # Set curve cyclic=close - else: - curve.flagU = 0 # Set curve not cyclic=open - if self.spline: # NURBSplines-----OK----- #print 'deb:polyline2dCurve.draw self.spline!' #--------------- nurbs_points = [] @@ -1358,21 +1311,6 @@ class Polyline: #-------------------------------------------------------------- except AttributeError: pass #print 'deb: dir(curve):', dir(curve) #---------------- - elif False: #orig self.curved: #--Bezier-curves---OK------- - #print 'deb:polyline2dCurve.draw self.curved!' #--------------- - curve = pline.appendNurb(BezTriple.New(d_points[0])) - for p in d_points[1:]: - curve.append(BezTriple.New(p)) - for point in curve: - point.handleTypes = [AUTO, AUTO] - point.radius = 1.0 - if self.closed: - curve.flagU = 1 # Set curve cyclic=close - else: - curve.flagU = 0 # Set curve not cyclic=open - curve[0].handleTypes = [FREE, ALIGN] #remi--todo----- - curve[-1].handleTypes = [ALIGN, FREE] #remi--todo----- - elif self.curved: #--SPLINE as Bezier-curves---wip------ #print 'deb:polyline2dCurve.draw self.curved!' #--------------- begtangent, endtangent = None, None @@ -1424,68 +1362,48 @@ class Polyline: #-------------------------------------------------------------- for i in xrange(len(d_points)): point1 = d_points[i] #point2 = d_points[i+1] - if False: #-----outdated!- standard calculation ---------------------------------- - if point1.bulge and (i < len(d_points)-2 or self.closed): - verts, center = calcBulge(point1, point2, arc_res, triples=False) - if i == 0: curve = pline.appendNurb(BezTriple.New(verts[0])) - else: curve.append(BezTriple.New(verts[0])) - curve[-1].handleTypes = [VECT, VECT] #--todo--calculation of bezier-tangents + #----- optimised Bezier-Handles calculation -------------------------------- + #print 'deb:drawPlineCurve: i:', i #--------- + if point1.bulge and not (i == len(d_points)-1 and point1.bulge and not self.closed): + if i == len(d_points)-1: point2 = d_points[0] + else: point2 = d_points[i+1] + + + # calculate additional points for bulge + VectorTriples = calcBulge(point1, point2, arc_res, triples=True) + + if prevHandleType == FREE: + #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #--------- + VectorTriples[0][:3] = prevHandleVect + #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #--------- + + if i == 0: curve = pline.appendNurb(BezTriple.New(VectorTriples[0])) + else: curve.append(BezTriple.New(VectorTriples[0])) + curve[-1].handleTypes = [prevHandleType, FREE] + curve[-1].radius = 1.0 + + for p in VectorTriples[1:-1]: + curve.append(BezTriple.New(p)) + curve[-1].handleTypes = [FREE, FREE] + curve[-1].radius = 1.0 + + prevHandleVect = VectorTriples[-1][:3] + prevHandleType = FREE + #print 'deb:drawPlineCurve: prevHandleVect:', prevHandleVect #--------- + else: + #print 'deb:drawPlineCurve: else' #---------- + if prevHandleType == FREE: + VectorTriples = prevHandleVect + list(point1) + list(point1) + #print 'deb:drawPlineCurve: VectorTriples:', VectorTriples #--------- + curve.append(BezTriple.New(VectorTriples)) + curve[-1].handleTypes = [FREE, VECT] + prevHandleType = VECT curve[-1].radius = 1.0 - for p in verts[1:]: - curve.append(BezTriple.New(p)) - curve[-1].handleTypes = [AUTO, AUTO] - curve[-1].radius = 1.0 else: if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc)) else: curve.append(BezTriple.New(point1.loc)) - curve[-1].handleTypes = [VECT, VECT] #--todo--calculation of bezier-tangents + curve[-1].handleTypes = [VECT, VECT] curve[-1].radius = 1.0 - - elif True: #----- optimised Bezier-Handles calculation -------------------------------- - #print 'deb:drawPlineCurve: i:', i #--------- - if point1.bulge and not (i == len(d_points)-1 and point1.bulge and not self.closed): - if i == len(d_points)-1: point2 = d_points[0] - else: point2 = d_points[i+1] - - - # calculate additional points for bulge - VectorTriples = calcBulge(point1, point2, arc_res, triples=True) - - if prevHandleType == FREE: - #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #--------- - VectorTriples[0][:3] = prevHandleVect - #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #--------- - - if i == 0: curve = pline.appendNurb(BezTriple.New(VectorTriples[0])) - else: curve.append(BezTriple.New(VectorTriples[0])) - curve[-1].handleTypes = [prevHandleType, FREE] - curve[-1].radius = 1.0 - - for p in VectorTriples[1:-1]: - curve.append(BezTriple.New(p)) - curve[-1].handleTypes = [FREE, FREE] - curve[-1].radius = 1.0 - - prevHandleVect = VectorTriples[-1][:3] - prevHandleType = FREE - #print 'deb:drawPlineCurve: prevHandleVect:', prevHandleVect #--------- - else: - #print 'deb:drawPlineCurve: else' #---------- - if prevHandleType == FREE: - VectorTriples = prevHandleVect + list(point1) + list(point1) - #print 'deb:drawPlineCurve: VectorTriples:', VectorTriples #--------- - curve.append(BezTriple.New(VectorTriples)) - curve[-1].handleTypes = [FREE, VECT] - prevHandleType = VECT - curve[-1].radius = 1.0 - else: - if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc)) - else: curve.append(BezTriple.New(point1.loc)) - curve[-1].handleTypes = [VECT, VECT] - curve[-1].radius = 1.0 - - - #print 'deb:drawPlineCurve: curve[-1].vec[0]', curve[-1].vec[0] #---------- if self.closed: @@ -1584,23 +1502,6 @@ class Polyline: #-------------------------------------------------------------- d_points = self.doubles_out(settings, d_points) #print 'deb:drawPolyCurve d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ - """# routine to sort out of "double.vertices" ------------------------------------ - minimal_dist = settings.var['dist_min'] * 0.1 - temp_points = [] - for i in xrange(len(d_points)-1): - point = d_points[i] - point2 = d_points[i+1] - #print 'deb:double.vertex p1,p2', point, point2 #------------------------ - delta = Mathutils.Vector(point2.loc) - Mathutils.Vector(point.loc) - if delta.length > minimal_dist: - temp_points.append(point) - #else: print 'deb:drawPoly2d double.vertex sort out!' #------------------------ - temp_points.append(d_points[-1]) #------ incl. last vertex ------------- - #if self.closed: temp_points.append(d_points[1]) #------ loop start vertex ------------- - d_points = temp_points #-----vertex.list without "double.vertices" - #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ - """ - #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ if len(d_points) < 2: #if too few vertex, then return #print 'deb:drawPoly2d corrupted Vertices' #--------- @@ -1796,29 +1697,6 @@ class Polyline: #-------------------------------------------------------------- # clean corner intersection pointsLc.append(cornerpointL) pointsRc.append(cornerpointR) - elif False: # the standard no-intersection - # --todo-- not optimal, because produces X-face - pointsLc.extend((pointsLe[i],pointsLs[i+1])) - pointsRc.extend((pointsRe[i],pointsRs[i+1])) - elif False: # --todo-- the optimised non-intersection - if (cornerpointL - vecL1).length < (cornerpointR - vecR1).length: - left_angle = True - else: - left_angle = False - limit_dist = settings.var['dist_min'] - if left_angle: # if left turning angle - #print 'deb:drawPoly2d it is left turning angle' #------------- - # to avoid triangelface/doubleVertex - delta1 = (cornerpointL - vecL1).normalize() * limit_dist - delta4 = (cornerpointL - vecL4).normalize() * limit_dist - pointsLc.extend((cornerpointL - delta1, cornerpointL - delta4)) - pointsRc.extend((pointsRe[i],pointsRs[i+1])) - else: # if right turning angle - #print 'deb:drawPoly2d right turning angle' #------------- - delta1 = (cornerpointR - vecR1).normalize() * limit_dist - delta4 = (cornerpointR - vecR4).normalize() * limit_dist - pointsRc.extend((cornerpointR - delta1, cornerpointR - delta4)) - pointsLc.extend((pointsLe[i],pointsLs[i+1])) else: pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1])) pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1])) @@ -1855,14 +1733,10 @@ class Polyline: #-------------------------------------------------------------- vecR3, vecR4 = pointsRs[i+1], pointsRe[i+1] if bulg_points[i] != None: #compute left- and right-cornerpoints - if True: - cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4) - cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4) - pointsLc.append(cornerpointL[0]) - pointsRc.append(cornerpointR[0]) - else: - pointVec = Mathutils.Vector(point[i]) - + cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4) + cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4) + pointsLc.append(cornerpointL[0]) + pointsRc.append(cornerpointR[0]) else: # IF non-bulg pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1])) pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1])) @@ -1924,21 +1798,20 @@ class Polyline: #-------------------------------------------------------------- for v in f_right: vg_right.extend(v) for v in f_top: vg_top.extend(v) for v in f_bottom: vg_bottom.extend(v) - me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace) - me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace) - me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) - me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) + me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) + me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) + me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) + me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) if not self.closed: me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- #if self.spline or self.curved: - if True: - smooth_len = len(f_left) + len(f_right) - for i in xrange(smooth_len): - me.faces[i].smooth = True - #me.Modes(AUTOSMOOTH) + smooth_len = len(f_left) + len(f_right) + for i in xrange(smooth_len): + me.faces[i].smooth = True + #me.Modes(AUTOSMOOTH) # 2.level:IF width, but no-thickness --------------------- else: @@ -1977,10 +1850,9 @@ class Polyline: #-------------------------------------------------------------- if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- #if self.spline or self.curved: - if True: - for i in xrange(len(faces)): - me.faces[i].smooth = True - #me.Modes(AUTOSMOOTH) + for i in xrange(len(faces)): + me.faces[i].smooth = True + #me.Modes(AUTOSMOOTH) # 1.level:IF no-width and no-thickness --------------------- else: @@ -2684,38 +2556,17 @@ class Circle: #---------------------------------------------------------------- cyl_rad = 0.5 * settings.var['width_min'] if settings.var['lines_as'] == 5: # draw CIRCLE as curve ------------- - if True: # universal version - arc_res = settings.var['curve_arc'] - #arc_res = 3 - start, end = 0.0, 360.0 - VectorTriples = calcArc(None, radius, start, end, arc_res, True) - c = Curve.New(obname) # create new curve data - curve = c.appendNurb(BezTriple.New(VectorTriples[0])) - for p in VectorTriples[1:-1]: - curve.append(BezTriple.New(p)) - for point in curve: - point.handleTypes = [FREE, FREE] - point.radius = 1.0 - else: # standard version - c = Curve.New(obname) # create new curve data - p1 = (0, -radius, 0) - p2 = (radius, 0, 0) - p3 = (0, radius, 0) - p4 = (-radius, 0, 0) - - p1 = BezTriple.New(p1) - p2 = BezTriple.New(p2) - p3 = BezTriple.New(p3) - p4 = BezTriple.New(p4) - - curve = c.appendNurb(p1) - curve.append(p2) - curve.append(p3) - curve.append(p4) - for point in curve: - point.handleTypes = [AUTO, AUTO] - point.radius = 1.0 - + arc_res = settings.var['curve_arc'] + #arc_res = 3 + start, end = 0.0, 360.0 + VectorTriples = calcArc(None, radius, start, end, arc_res, True) + c = Curve.New(obname) # create new curve data + curve = c.appendNurb(BezTriple.New(VectorTriples[0])) + for p in VectorTriples[1:-1]: + curve.append(BezTriple.New(p)) + for point in curve: + point.handleTypes = [FREE, FREE] + point.radius = 1.0 curve.flagU = 1 # 1 sets the curve cyclic=closed if settings.var['fill_on']: c.setFlag(6) # 2+4 set top and button caps @@ -2737,24 +2588,6 @@ class Circle: #---------------------------------------------------------------- ob.SizeZ *= abs(thic) return ob - elif False: # create a new mesh_object with buildin_circle_primitive - verts_num = settings.var['arc_res'] * sqrt(radius / settings.var['arc_rad']) - if verts_num > 100: verts_num = 100 # Blender accepts only values [3:500] - if verts_num < 4: verts_num = 4 # Blender accepts only values [3:500] - if thic != 0: - loc2 = thic * 0.5 #-----blenderAPI draw Cylinder with 2*thickness - self.loc[2] += loc2 #---new location for the basis of cylinder - #print 'deb:circleDraw:self.loc2:', self.loc #----------------------- - c = Mesh.Primitives.Cylinder(int(verts_num), radius*2, abs(thic)) - else: - c = Mesh.Primitives.Circle(int(verts_num), radius*2) - - #c.update() - ob = SCENE.objects.new(c, obname) # create a new circle_mesh_object - ob.loc = tuple(self.loc) - transform(self.extrusion, 0, ob) - return ob - else: # draw CIRCLE as mesh ----------------------------------------------- if M_OBJ: obname, me, ob = makeNewObject() else: @@ -2810,12 +2643,13 @@ class Circle: #---------------------------------------------------------------- replace = Blender.Mesh.AssignModes.REPLACE #or .AssignModes.ADD vg_band, vg_top, vg_bottom = [], [], [] for v in f_band: vg_band.extend(v) - me.addVertGroup('side.band') ; me.assignVertsToGroup('side.band', list(set(vg_band)), 1.0, replace) + me.addVertGroup('side.band') ; me.assignVertsToGroup('side.band', vg_band, 1.0, replace) + if settings.var['fill_on']: for v in f_top: vg_top.extend(v) for v in f_bottom: vg_bottom.extend(v) - me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) - me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) + me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) + me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) else: # if thic == 0 if settings.var['fill_on']: @@ -2992,10 +2826,10 @@ class Arc: #----------------------------------------------------------------- for v in f_right: vg_right.extend(v) for v in f_top: vg_top.extend(v) for v in f_bottom: vg_bottom.extend(v) - me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace) - me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace) - me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) - me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) + me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) + me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) + me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) + me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) @@ -3247,8 +3081,6 @@ class Insert: #---------------------------------------------------------------- if a_data.key == 'SCENE': # define set of lights as blender group scene_lights = 1 - elif False: # define set of lights as blender group - scene_lights = 1 return elif name == 'ave_global': if settings.var['lights_on']: #if lights support activated @@ -3409,35 +3241,12 @@ class Ellipse: #--------------------------------------------------------------- obname = obname[:MAX_NAMELENGTH] center = self.loc - if True: - start = degrees(self.start_angle) - end = degrees(self.end_angle) - if abs(end - 360.0) < 0.00001: end = 360.0 - ellipse_closed = False - if end - start == 360.0: ellipse_closed = True + start = degrees(self.start_angle) + end = degrees(self.end_angle) + if abs(end - 360.0) < 0.00001: end = 360.0 + ellipse_closed = False + if end - start == 360.0: ellipse_closed = True - else: # bug in AutoCAD_2002 dxf-exporter into r12 for ELLIPSE->POLYLINE_ARC - #print 'deb:calcEllipse---------:\n start=%s\n end=%s' %(self.start_angle, self.end_angle) #--------- - if self.start_angle > pi+pi: self.start_angle %= pi+pi - if self.end_angle > pi+pi: self.end_angle %= pi+pi - if abs(self.end_angle - pi - pi) < 0.00001: self.end_angle = pi + pi - ellipse_closed = False - if abs(self.end_angle - self.start_angle) == pi + pi: ellipse_closed = True - test = self.start_angle % pi - if test < 0.001 or pi - test < 0.001: start = self.start_angle - else: - start = atan(tan(self.start_angle) * self.ratio) - if start < 0.0: start += pi - if self.start_angle > pi: start += pi - test = self.end_angle % pi - if test < 0.001 or pi - test < 0.001: end = self.end_angle - else: - end = atan(tan(self.end_angle) * self.ratio) - if end < 0.0: end += pi - if self.end_angle > pi: end += pi - start = degrees(start) - end = degrees(end) - # rotation = Angle between major and WORLDX # doesnt work, couse produces always positive value: rotation = Mathutils.AngleBetweenVecs(major, WORLDX) if self.major[0] == 0: @@ -3512,8 +3321,6 @@ class Ellipse: #--------------------------------------------------------------- verts = calcArc(None, radius, start, end, arc_res, False) #verts = [list(point) for point in verts] - if False: #--todo--: if ellipse_closed: - verts = verts[:-1] #list without last point/edge (cause closed curve) len1 = len(verts) #print 'deb:len1:', len1 #----------------------- if width != 0: @@ -3563,10 +3370,10 @@ class Ellipse: #--------------------------------------------------------------- for v in f_right: vg_right.extend(v) for v in f_top: vg_top.extend(v) for v in f_bottom: vg_bottom.extend(v) - me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace) - me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace) - me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) - me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) + me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) + me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) + me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) + me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) @@ -4378,8 +4185,9 @@ def analyzeDXF(dxfFile): #--------------------------------------- for item2 in drawing.entities.data: if type(item2) != list and item2.type == 'insert': - if not layersmap or (layersmap and not layersmap[item2.layer][1]): #if insert_layer is not frozen - blocksmap[item2.name][0] = True # marked as world used BLOCK + if item2.name in blocksmap.keys(): + if not layersmap or (layersmap and not layersmap[item2.layer][1]): #if insert_layer is not frozen + blocksmap[item2.name][0] = True # marked as world used BLOCK key_list = blocksmap.keys() key_list.reverse() @@ -4789,10 +4597,12 @@ def drawer(_type, entities, settings, block_def): #---------------------------- group = getGroup('l:%s' % layernamesmap[entity.layer]) if _type == 'insert': #---- INSERT and MINSERT=array -------------------- - if not settings.var['block_nn'] and entity.name.startswith('*X'): #---- support for noname BLOCKs - #print 'deb:drawer entity.name:', entity.name #------------ - continue - elif settings.var['blockFilter_on'] and not settings.accepted_block(entity.name): + if not settings.var['block_nn']: #----turn off support for noname BLOCKs + prefix = entity.name[:2] + if prefix in ('*X', '*U', '*D'): + #print 'deb:drawer entity.name:', entity.name #------------ + continue + if settings.var['blockFilter_on'] and not settings.accepted_block(entity.name): continue #print 'deb:insert entity.loc:', entity.loc #---------------- From 1e1b88c118d6e6b2df3f6240547acc92e2d08e15 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 15 Mar 2009 23:40:59 +0000 Subject: [PATCH 251/252] BGE * getting state of RMB was impossible due to wrong check. --- source/gameengine/GameLogic/SCA_MouseSensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 36e4a5f2c30..57535b29f32 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -282,7 +282,7 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, int button = PyInt_AsLong(value); if ((button < SCA_IInputDevice::KX_LEFTMOUSE) - || (button > SCA_IInputDevice::KX_MIDDLEMOUSE)){ + || (button > SCA_IInputDevice::KX_RIGHTMOUSE)){ PyErr_SetString(PyExc_ValueError, "invalid button specified!"); return NULL; } From 28f6d223d079b1e5cb67e3fc22fb7f818deb8dcb Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Mon, 16 Mar 2009 17:02:19 +0000 Subject: [PATCH 252/252] This is patch: [#17974] two small fix for blender 2.48 (memory leak and uninitalized vars) Submitted By: Pavel Nemec (nemecp) (changes delete to [] and sets to vars to NULL) Kent --- intern/opennl/superlu/get_perm_c.c | 4 ++++ source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/intern/opennl/superlu/get_perm_c.c b/intern/opennl/superlu/get_perm_c.c index e255b4a76bd..4c0ee95c4c6 100644 --- a/intern/opennl/superlu/get_perm_c.c +++ b/intern/opennl/superlu/get_perm_c.c @@ -366,6 +366,10 @@ get_perm_c(int ispec, SuperMatrix *A, int *perm_c) int *b_rowind, *dhead, *qsize, *llist, *marker; double t, SuperLU_timer_(); + /* make gcc happy */ + b_rowind=NULL; + b_colptr=NULL; + m = A->nrow; n = A->ncol; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index afee60c3192..018c966ac69 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -246,7 +246,7 @@ static void get_filename(int argc, char **argv, char *filename) if (BLI_exists(gamefile)) BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE); - delete gamefile; + delete [] gamefile; } #else