From 129fb516f43126497bbc7cc96a032b51196b5b2d Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 12 Jan 2013 11:59:22 +0000 Subject: Security fix: "Pack Blender Libraries" now first does a check if the .blend files are all used with relative paths. This to prevent bad things happen on unpacking. --- source/blender/blenkernel/intern/packedFile.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 9f77094994d..9fab052f80c 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -553,7 +553,7 @@ int unpackLibraries(Main *bmain, ReportList *reports) if (newname != NULL) { ret_value = RET_OK; - printf("Saved .blend library: %s\n", newname); + printf("Unpacked .blend library: %s\n", newname); freePackedFile(lib->packedfile); lib->packedfile = NULL; @@ -570,6 +570,16 @@ void packLibraries(Main *bmain, ReportList *reports) { Library *lib; + /* test for relativenss */ + for (lib = bmain->library.first; lib; lib = lib->id.next) + if (0 == BLI_path_is_rel(lib->name)) + break; + + if (lib) { + BKE_reportf(reports, RPT_ERROR, "Cannot pack absolute file: '%s'", lib->name); + return; + } + for (lib = bmain->library.first; lib; lib = lib->id.next) if (lib->packedfile == NULL) lib->packedfile = newPackedFile(reports, lib->name, bmain->name); -- cgit v1.2.3 From aab01c86cf56f5d21d2503f7e854bb19b07ca2c6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 12 Jan 2013 12:51:10 +0000 Subject: Patch #33837: ffmpeg1.1 and libav9.1 compatibility update Patch makes it possible to compile blender with recent ffmpeg and libav libraries, mainly by getting rid of deprecated API. Original patch by Campbell Barton with own modifications to support compilation with older ffmpeg versions. This patch could break compatibility of FFV1 videos playing back in older players, mainly because of alpha support changes. Preserving compatibility with such players became a headache and think it's high time to get rid of workarounds here. --- source/blender/blenkernel/intern/writeffmpeg.c | 51 +++++++++++--------------- 1 file changed, 22 insertions(+), 29 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index cf2a165c2b2..7e51025883d 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -373,7 +373,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) { char name[128]; char *param; - const AVOption *rv = NULL; + int fail = TRUE; PRINT("FFMPEG expert option: %s: ", prop->name); @@ -388,30 +388,30 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) switch (prop->type) { case IDP_STRING: PRINT("%s.\n", IDP_String(prop)); - av_set_string3(c, prop->name, IDP_String(prop), 1, &rv); + fail = av_opt_set(c, prop->name, IDP_String(prop), 0); break; case IDP_FLOAT: PRINT("%g.\n", IDP_Float(prop)); - rv = av_set_double(c, prop->name, IDP_Float(prop)); + fail = av_opt_set_double(c, prop->name, IDP_Float(prop), 0); break; case IDP_INT: PRINT("%d.\n", IDP_Int(prop)); if (param) { if (IDP_Int(prop)) { - av_set_string3(c, name, param, 1, &rv); + fail = av_opt_set(c, name, param, 0); } else { return; } } else { - rv = av_set_int(c, prop->name, IDP_Int(prop)); + fail = av_opt_set_int(c, prop->name, IDP_Int(prop), 0); } break; } - if (!rv) { + if (fail) { PRINT("ffmpeg-option not supported: %s! Skipping.\n", prop->name); } } @@ -464,8 +464,9 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex error[0] = '\0'; - st = av_new_stream(of, 0); + st = avformat_new_stream(of, NULL); if (!st) return NULL; + st->id = 0; /* Set up the codec context */ @@ -541,16 +542,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex } if (codec_id == CODEC_ID_FFV1) { -#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED - if (rd->im_format.planes == R_IMF_PLANES_RGBA) { - c->pix_fmt = PIX_FMT_RGB32; - } - else { - c->pix_fmt = PIX_FMT_BGR0; - } -#else c->pix_fmt = PIX_FMT_RGB32; -#endif } if (codec_id == CODEC_ID_QTRLE) { @@ -582,7 +574,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex set_ffmpeg_properties(rd, c, "video"); - if (avcodec_open(c, codec) < 0) { + if (avcodec_open2(c, codec, NULL) < 0) { BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; } @@ -619,8 +611,9 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex error[0] = '\0'; - st = av_new_stream(of, 1); + st = avformat_new_stream(of, NULL); if (!st) return NULL; + st->id = 1; c = st->codec; c->codec_id = codec_id; @@ -642,7 +635,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex set_ffmpeg_properties(rd, c, "audio"); - if (avcodec_open(c, codec) < 0) { + if (avcodec_open2(c, codec, NULL) < 0) { //XXX error("Couldn't initialize audio codec"); BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; @@ -1151,7 +1144,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in val.i = 0; - avcodec_get_context_defaults(&c); + avcodec_get_context_defaults3(&c, NULL); o = c.av_class->option + opt_index; parent = c.av_class->option + parent_index; @@ -1182,23 +1175,23 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in } switch (o->type) { - case FF_OPT_TYPE_INT: - case FF_OPT_TYPE_INT64: + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_INT64: val.i = FFMPEG_DEF_OPT_VAL_INT(o); idp_type = IDP_INT; break; - case FF_OPT_TYPE_DOUBLE: - case FF_OPT_TYPE_FLOAT: + case AV_OPT_TYPE_DOUBLE: + case AV_OPT_TYPE_FLOAT: val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o); idp_type = IDP_FLOAT; break; - case FF_OPT_TYPE_STRING: + case AV_OPT_TYPE_STRING: val.string.str = (char *)" "; val.string.len = 80; /* val.str = (char *)" ";*/ idp_type = IDP_STRING; break; - case FF_OPT_TYPE_CONST: + case AV_OPT_TYPE_CONST: val.i = 1; idp_type = IDP_INT; break; @@ -1238,7 +1231,7 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char char *param; IDProperty *prop = NULL; - avcodec_get_context_defaults(&c); + avcodec_get_context_defaults3(&c, NULL); strncpy(name_, str, sizeof(name_)); @@ -1259,10 +1252,10 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char if (!o) { return 0; } - if (param && o->type == FF_OPT_TYPE_CONST) { + if (param && o->type == AV_OPT_TYPE_CONST) { return 0; } - if (param && o->type != FF_OPT_TYPE_CONST && o->unit) { + if (param && o->type != AV_OPT_TYPE_CONST && o->unit) { p = my_av_find_opt(&c, param, o->unit, 0, 0); if (p) { prop = BKE_ffmpeg_property_add(rd, (char *) type, p - c.av_class->option, o - c.av_class->option); -- cgit v1.2.3 From c93e127e7a2040f74655937fedb5a9d439c03aa9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 12 Jan 2013 14:28:23 +0000 Subject: code cleanup: style and replace (float)sin, (float)cos with sinf, cosf --- source/blender/blenkernel/intern/curve.c | 2 +- source/blender/blenkernel/intern/font.c | 6 +++--- source/blender/blenkernel/intern/mesh.c | 6 +++--- source/blender/blenkernel/intern/tracking.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index fe8bd0cc5a4..a9c4a7dcdc2 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1746,7 +1746,7 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si else t02 = (saacos(t02)) / 2.0f; - t02 = (float)sin(t02); + t02 = sinf(t02); if (t02 == 0.0f) t02 = 1.0f; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index d4634748c71..3e1e55132d8 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -962,9 +962,9 @@ makebreak: float si, co; ct = chartransdata + cu->pos; - si = (float)sin(ct->rot); - co = (float)cos(ct->rot); - + si = sinf(ct->rot); + co = cosf(ct->rot); + f = cu->editfont->textcurs[0]; f[0] = cu->fsize * (-0.1f * co + ct->xof); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index dec7556392f..267cf1738b0 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1360,7 +1360,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, int i; for (i = 0; i < 3; i++, mloopuv++) { - mloopuv->uv[0] = (mloop[i].v - startvert)/(float)(dl->nr - 1); + mloopuv->uv[0] = (mloop[i].v - startvert) / (float)(dl->nr - 1); mloopuv->uv[1] = 0.0f; } } @@ -1430,8 +1430,8 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, /* find uv based on vertex index into grid array */ int v = mloop[i].v - startvert; - mloopuv->uv[0] = (v / dl->nr)/(float)orco_sizev; - mloopuv->uv[1] = (v % dl->nr)/(float)orco_sizeu; + mloopuv->uv[0] = (v / dl->nr) / (float)orco_sizev; + mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu; /* cyclic correction */ if ((i == 0 || i == 1) && mloopuv->uv[1] == 0.0f) diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 801fecc9f7c..3c5d94a21e4 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1660,7 +1660,7 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea /* real sampling requires libmv, but areas are supposing pattern would be * sampled if search area does exists, so we'll need to create empty * pattern area here to prevent adding NULL-checks all over just to deal - * with situation when lubmv is disabled + * with situation when libmv is disabled */ (void) frame_width; -- cgit v1.2.3 From fa759d8ffdd6c2a66270e8e85a53f608f4cd7ad0 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 12 Jan 2013 17:07:49 +0000 Subject: Mac HiDPI ("retina") handling: OK - so you have this nice crisp screen, and still you want to add extra monitors to the laptop! That means Blender should switch back and forth to HiDPI modes, when you move a window to another monitor. This code makes the pixelsize scale factor a window property, and handles an event when a window moves to another monitor. It then changes the native pixelsize nicely and refreshes entire UI. You can also have one Blender window on high, and other on low resolution. Stretching a Blender window from 1 monitor to the other works too, but that is Apple magic handling it. --- source/blender/blenkernel/intern/blender.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 11ae242023c..fb2d1a3aaf7 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -426,6 +426,9 @@ void BKE_userdef_free(void) /* handle changes in settings that need recalc */ void BKE_userdef_state(void) { + /* prevent accidents */ + if (U.pixelsize == 0) U.pixelsize = 1; + BLF_default_dpi(U.pixelsize * U.dpi); U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72; -- cgit v1.2.3 From 9c003a36d6e1fb6a42d7abba45d5c6740a912250 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 12 Jan 2013 17:12:48 +0000 Subject: patch from Harley Acheson to remove multiple inline defines. --- source/blender/blenkernel/BKE_colortools.h | 8 -------- source/blender/blenkernel/intern/CCGSubSurf.c | 26 ++++++++++---------------- source/blender/blenkernel/intern/colortools.c | 2 +- 3 files changed, 11 insertions(+), 25 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 96e05aa87b9..e0b7e68bafc 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -42,14 +42,6 @@ struct Histogram; struct ImBuf; struct rctf; -#if defined _MSC_VER -# define DO_INLINE __inline -#elif defined(__sun) || defined(__sun__) -# define DO_INLINE -#else -# define DO_INLINE static inline -#endif - void curvemapping_set_defaults(struct CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy); struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); void curvemapping_free_data(struct CurveMapping *cumap); diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index cc20470b4d5..bbda6f8a292 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -16,12 +16,6 @@ #include "BLI_utildefines.h" /* for BLI_assert */ -#ifdef _MSC_VER -# define CCG_INLINE __inline -#else -# define CCG_INLINE inline -#endif - /* used for normalize_v3 in BLI_math_vector * float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */ #define EPSILON (1.0e-35f) @@ -305,7 +299,7 @@ struct CCGVert { // byte *userData; }; -static CCG_INLINE byte *VERT_getLevelData(CCGVert *v) +BLI_INLINE byte *VERT_getLevelData(CCGVert *v) { return (byte *)(&(v)[1]); } @@ -324,7 +318,7 @@ struct CCGEdge { // byte *userData; }; -static CCG_INLINE byte *EDGE_getLevelData(CCGEdge *e) +BLI_INLINE byte *EDGE_getLevelData(CCGEdge *e) { return (byte *)(&(e)[1]); } @@ -342,17 +336,17 @@ struct CCGFace { // byte *userData; }; -static CCG_INLINE CCGVert **FACE_getVerts(CCGFace *f) +BLI_INLINE CCGVert **FACE_getVerts(CCGFace *f) { return (CCGVert **)(&f[1]); } -static CCG_INLINE CCGEdge **FACE_getEdges(CCGFace *f) +BLI_INLINE CCGEdge **FACE_getEdges(CCGFace *f) { return (CCGEdge **)(&(FACE_getVerts(f)[f->numVerts])); } -static CCG_INLINE byte *FACE_getCenterData(CCGFace *f) +BLI_INLINE byte *FACE_getCenterData(CCGFace *f) { return (byte *)(&(FACE_getEdges(f)[(f)->numVerts])); } @@ -698,28 +692,28 @@ static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int return f; } -static CCG_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) +BLI_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize)); return &gridBase[dataSize * x * spacing]; } -static CCG_INLINE void *_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset) +BLI_INLINE void *_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize)); return &gridBase[dataSize * x * spacing + normalDataOffset]; } -static CCG_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) +BLI_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize)); return &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing)]; } -static CCG_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) +BLI_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); @@ -742,7 +736,7 @@ static int _face_getEdgeIndex(CCGFace *f, CCGEdge *e) return i; return -1; } -static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize) +BLI_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 529fe07cab3..d08c16eac9e 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -895,7 +895,7 @@ void curvemapping_table_RGBA(const CurveMapping *cumap, float **array, int *size #define INV_255 (1.f / 255.f) -DO_INLINE int get_bin_float(float f) +BLI_INLINE int get_bin_float(float f) { int bin = (int)((f * 255.0f) + 0.5f); /* 0.5 to prevent quantisation differences */ -- cgit v1.2.3 From ef5a41a89d121ae4048cc4010487e77b969f66b1 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 13 Jan 2013 12:25:56 +0000 Subject: Three fixes; - Previous commit had a line of code of WIP project in it... tss - Packed Library data was not freed - Removed recent (post 2.65a) code to exclude packed data from Undo system. It's internal data thats part of file spec, errors happen for example on restoring quit.blend or temp saves. --- source/blender/blenkernel/intern/library.c | 60 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 1e6f429aa9c..42f658afa93 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -47,6 +47,7 @@ #include "DNA_brush_types.h" #include "DNA_camera_types.h" #include "DNA_group_types.h" +#include "DNA_gpencil_types.h" #include "DNA_ipo_types.h" #include "DNA_key_types.h" #include "DNA_lamp_types.h" @@ -54,6 +55,8 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" +#include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "DNA_nla_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" @@ -64,51 +67,49 @@ #include "DNA_vfont_types.h" #include "DNA_windowmanager_types.h" #include "DNA_world_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_movieclip_types.h" -#include "DNA_mask_types.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" #include "BLI_utildefines.h" #include "BKE_bpath.h" +#include "BKE_action.h" #include "BKE_animsys.h" +#include "BKE_armature.h" +#include "BKE_brush.h" #include "BKE_camera.h" #include "BKE_context.h" -#include "BKE_lamp.h" -#include "BKE_library.h" -#include "BKE_main.h" -#include "BKE_global.h" -#include "BKE_sound.h" -#include "BKE_object.h" -#include "BKE_screen.h" -#include "BKE_mesh.h" -#include "BKE_material.h" #include "BKE_curve.h" -#include "BKE_mball.h" -#include "BKE_text.h" -#include "BKE_texture.h" -#include "BKE_scene.h" +#include "BKE_fcurve.h" +#include "BKE_font.h" +#include "BKE_global.h" +#include "BKE_group.h" +#include "BKE_gpencil.h" +#include "BKE_idprop.h" #include "BKE_icons.h" #include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_key.h" -#include "BKE_world.h" -#include "BKE_font.h" -#include "BKE_group.h" +#include "BKE_lamp.h" #include "BKE_lattice.h" -#include "BKE_armature.h" -#include "BKE_action.h" +#include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_material.h" +#include "BKE_main.h" +#include "BKE_mball.h" +#include "BKE_movieclip.h" +#include "BKE_mask.h" #include "BKE_node.h" -#include "BKE_brush.h" -#include "BKE_idprop.h" +#include "BKE_object.h" #include "BKE_particle.h" -#include "BKE_gpencil.h" -#include "BKE_fcurve.h" +#include "BKE_packedFile.h" #include "BKE_speaker.h" -#include "BKE_movieclip.h" -#include "BKE_mask.h" +#include "BKE_sound.h" +#include "BKE_screen.h" +#include "BKE_scene.h" +#include "BKE_text.h" +#include "BKE_texture.h" +#include "BKE_world.h" #include "RNA_access.h" @@ -771,9 +772,10 @@ void *BKE_libblock_copy(ID *id) return idn; } -static void BKE_library_free(Library *UNUSED(lib)) +static void BKE_library_free(Library *lib) { - /* no freeing needed for libraries yet */ + if (lib->packedfile) + freePackedFile(lib->packedfile); } static void (*free_windowmanager_cb)(bContext *, wmWindowManager *) = NULL; -- cgit v1.2.3 From ba78e3e312fbef1b1d9e4b5432ec5d6e700717f0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 Jan 2013 12:02:10 +0000 Subject: no need to call BLI_countlist on idproperty groups when comparing. --- source/blender/blenkernel/intern/idprop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 3be47668fb5..9086ef49e4d 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -663,7 +663,7 @@ int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_s { IDProperty *link1, *link2; - if (is_strict && BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group)) + if (is_strict && prop1->len != prop2->len) return 0; for (link1 = prop1->data.group.first; link1; link1 = link1->next) { -- cgit v1.2.3 From b27854bd47104300a484e3b06185b2cb1fa0b774 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 14 Jan 2013 16:42:43 +0000 Subject: use booleans for bmesh api. --- source/blender/blenkernel/BKE_tessmesh.h | 2 +- source/blender/blenkernel/intern/editderivedmesh.c | 2 +- source/blender/blenkernel/intern/mesh.c | 2 +- source/blender/blenkernel/intern/pbvh_bmesh.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h index 9462822e25f..b3e6ab37273 100644 --- a/source/blender/blenkernel/BKE_tessmesh.h +++ b/source/blender/blenkernel/BKE_tessmesh.h @@ -83,7 +83,7 @@ typedef struct BMEditMesh { } BMEditMesh; void BMEdit_RecalcTessellation(BMEditMesh *em); -BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate); +BMEditMesh *BMEdit_Create(BMesh *bm, const bool do_tessellate); BMEditMesh *BMEdit_Copy(BMEditMesh *em); BMEditMesh *BMEdit_FromObject(struct Object *ob); void BMEdit_Free(BMEditMesh *em); diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 91577320a9c..0197cc3fa77 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -69,7 +69,7 @@ extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ -BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate) +BMEditMesh *BMEdit_Create(BMesh *bm, const bool do_tessellate) { BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 267cf1738b0..79cbd2ef886 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -533,7 +533,7 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob) bm = BM_mesh_create(&bm_mesh_allocsize_default); - BM_mesh_bm_from_me(bm, me, TRUE, ob->shapenr); + BM_mesh_bm_from_me(bm, me, true, ob->shapenr); return bm; } diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 791288a4dda..bb22175e2ad 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -295,7 +295,7 @@ static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, BMVert *v1, /* Note: passing NULL for the 'example' parameter, profiling shows * a small performance bump */ - f = BM_face_create_quad_tri(bvh->bm, v1, v2, v3, NULL, NULL, TRUE); + f = BM_face_create_quad_tri(bvh->bm, v1, v2, v3, NULL, NULL, true); if (!BLI_ghash_haskey(bvh->bm_face_to_node, f)) { BLI_ghash_insert(bvh->nodes[node_index].bm_faces, f, NULL); -- cgit v1.2.3 From eaa9258449e4667b9a2a9764b7c8b9d64c7ff9ea Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 15 Jan 2013 12:16:44 +0000 Subject: Code cleanup: remove some remaining code from the old compositor. --- source/blender/blenkernel/BKE_node.h | 2 -- source/blender/blenkernel/intern/node.c | 3 --- 2 files changed, 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 0a2f757b38e..16d7ba8b090 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -737,8 +737,6 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria /* API */ struct CompBuf; -struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree, int use_tree_data); -void ntreeCompositEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); void ntreeCompositTagRender(struct Scene *sce); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 84e280034ed..c73bd5ef8fd 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1035,9 +1035,6 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) */ if (ntree->execdata) { switch (ntree->type) { - case NTREE_COMPOSIT: - ntreeCompositEndExecTree(ntree->execdata, 1); - break; case NTREE_SHADER: ntreeShaderEndExecTree(ntree->execdata, 1); break; -- cgit v1.2.3 From 73c7c10c6e876bb6679fb8ba8ecbb82b4751fb7d Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 15 Jan 2013 15:42:12 +0000 Subject: Bug fix #33748 Old fixes, since 2009 and before! Related to Curve object editmode: - normals are not being drawn for hidden curves anymore - even worse: Blender also didn't hide the extrusions or bevels for hidden curves - outside edit mode, it shows all (as for all other modes) - (de)select-all now works when 1st (or any) handle was hidden. --- source/blender/blenkernel/intern/curve.c | 9 +++++++-- source/blender/blenkernel/intern/displist.c | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index a9c4a7dcdc2..a6e68b9b2d5 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -2220,6 +2220,7 @@ void BKE_curve_bevelList_make(Object *ob) struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu = 0, len = 0; int do_tilt, do_radius, do_weight; + int is_editmode = 0; /* this function needs an object, because of tflag and upflag */ cu = ob->data; @@ -2233,12 +2234,17 @@ void BKE_curve_bevelList_make(Object *ob) if (cu->editnurb && ob->type != OB_FONT) { ListBase *nurbs = BKE_curve_editNurbs_get(cu); nu = nurbs->first; + is_editmode = 1; } else { nu = cu->nurb.first; } - while (nu) { + for (; nu; nu = nu->next) { + + if (nu->hide && is_editmode) + continue; + /* check if we will calculate tilt data */ do_tilt = CU_DO_TILT(cu, nu); do_radius = CU_DO_RADIUS(cu, nu); /* normal display uses the radius, better just to calculate them */ @@ -2384,7 +2390,6 @@ void BKE_curve_bevelList_make(Object *ob) } } } - nu = nu->next; } /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 643c7b1d972..23b0d3e6e22 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -309,10 +309,11 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, i BPoint *bp; float *data; int a, len, resolu; + const int editmode = (!forRender && (cu->editnurb || cu->editfont)); nu = nubase->first; while (nu) { - if (nu->hide == 0) { + if (nu->hide == 0 || editmode == 0) { if (forRender && cu->resolu_ren != 0) resolu = cu->resolu_ren; else -- cgit v1.2.3 From fe83dc68828b70b0f7feeb82f341c505ac6d7c73 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Jan 2013 04:43:37 +0000 Subject: dont add identifiers starting with digits to autocomplete --- source/blender/blenkernel/BKE_text.h | 1 + source/blender/blenkernel/intern/text.c | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 1e3dd426efa..be30eba0559 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -105,6 +105,7 @@ int text_check_bracket(const char ch); int text_check_delim(const char ch); int text_check_digit(const char ch); int text_check_identifier(const char ch); +int text_check_identifier_nodigit(const char ch); int text_check_whitespace(const char ch); int text_find_identifier_start(const char *str, int i); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index c337e339ebf..a0f611a5a7b 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2930,6 +2930,16 @@ int text_check_identifier(const char ch) return 0; } +int text_check_identifier_nodigit(const char ch) +{ + if (ch <= '9') return 0; + if (ch < 'A') return 0; + if (ch <= 'Z' || ch == '_') return 1; + if (ch < 'a') return 0; + if (ch <= 'z') return 1; + return 0; +} + int text_check_whitespace(const char ch) { if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') -- cgit v1.2.3 From 1d4524220869e99a0785c47f68f907056304cde5 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 16 Jan 2013 14:36:13 +0000 Subject: Get rid of the BRUSH_FIXED_TEX flag, use mapping modes instead. Version patched all previous texture paint brushes to use tiled mapping since mappping is now shared between 2d and 3d painting. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/intern/brush.c | 1 - source/blender/blenkernel/intern/texture.c | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 9c6d26c08bc..2d596faabce 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 265 -#define BLENDER_SUBVERSION 8 +#define BLENDER_SUBVERSION 9 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index aeb0407b37f..e8275471b09 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -259,7 +259,6 @@ void BKE_brush_debug_print_state(Brush *br) BR_TEST_FLAG(BRUSH_SIZE_PRESSURE); BR_TEST_FLAG(BRUSH_JITTER_PRESSURE); BR_TEST_FLAG(BRUSH_SPACING_PRESSURE); - BR_TEST_FLAG(BRUSH_FIXED_TEX); BR_TEST_FLAG(BRUSH_RAKE); BR_TEST_FLAG(BRUSH_ANCHORED); BR_TEST_FLAG(BRUSH_DIR_IN); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index fbaf6f70fbc..2e909f11eaa 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -615,6 +615,7 @@ void default_mtex(MTex *mtex) mtex->gravityfac = 1.0f; mtex->fieldfac = 1.0f; mtex->normapspace = MTEX_NSPACE_TANGENT; + mtex->brush_map_mode = MTEX_MAP_MODE_TILED; } -- cgit v1.2.3 From b01233b07fbf06ba5139d4565c6148f65ab921e9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 16 Jan 2013 17:07:25 +0000 Subject: Movies support for Cycles This adds support of movie textures for Cycles rendering. Uses the same builtin images routines as packed/generated images, but with some extra non-rna hookups from blender_session side. Basically, it's not so clear how to give access to video frames via C++ RNA -- it'll require exposing ImBuf to API, doing some threading locks and so. Ended up adding two more functions which are actually bad level call, but don't consider it's so much bad -- we have few bad calls already, which are actually related. Changed a bit how builtin images names are passing to image manager. Now it's not just an ID datablock name, but also a frame number concatenated via '@' character, which makes itpossible to easily know frame number to be used for movie images, without adding extra descriptors to image manager. Decoding of builtin name is a bit slower now, but it should be still nothing in comparison with rendering complexity. Also exposed image user's frame_current to python API, which is needed to get absolute frame number of movie from node's image user. P.S. Generated/packed images are also using bad level call but only does it to make things more clear here. Either all images are using C++ RNA here or no images does. That's the most clear for now. --- source/blender/blenkernel/BKE_image.h | 4 +++ source/blender/blenkernel/intern/image.c | 54 ++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 499609932d1..597f2f25575 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -219,6 +219,10 @@ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int height, int width); void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int height, int width); +/* Cycles hookup */ +unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame); +float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 21417386d65..5124406b641 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3199,3 +3199,57 @@ void BKE_image_get_aspect(Image *image, float *aspx, float *aspy) else *aspy = 1.0f; } + +unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame) +{ + ImageUser iuser = {0}; + void *lock; + ImBuf *ibuf; + unsigned char *pixels = NULL; + + iuser.framenr = frame; + iuser.ok = TRUE; + + ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + + if (ibuf) { + pixels = (unsigned char *) ibuf->rect; + + if (pixels) + pixels = MEM_dupallocN(pixels); + + BKE_image_release_ibuf(image, ibuf, lock); + } + + if (!pixels) + return NULL; + + return pixels; +} + +float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame) +{ + ImageUser iuser = {0}; + void *lock; + ImBuf *ibuf; + float *pixels = NULL; + + iuser.framenr = frame; + iuser.ok = TRUE; + + ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + + if (ibuf) { + pixels = ibuf->rect_float; + + if (pixels) + pixels = MEM_dupallocN(pixels); + + BKE_image_release_ibuf(image, ibuf, lock); + } + + if (!pixels) + return NULL; + + return pixels; +} -- cgit v1.2.3 From 5ddc7d64a85d6e01e7eae1ed904bda635478a24e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Jan 2013 21:09:54 +0000 Subject: optimize bmesh operations that use triangle BMFace's (dyn-topo and mesh conversion). --- source/blender/blenkernel/intern/pbvh_bmesh.c | 85 ++++++++++++++++++--------- 1 file changed, 58 insertions(+), 27 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index bb22175e2ad..639a7e3691f 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -53,7 +53,8 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) GHASH_ITER (gh_iter, n->bm_faces) { BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - BMIter bm_iter; + BMLoop *l_iter; + BMLoop *l_first; BMVert *v; void *node_val = SET_INT_IN_POINTER(node_index); @@ -61,7 +62,9 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) BLI_ghash_insert(bvh->bm_face_to_node, f, node_val); /* Update vertices */ - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + v = l_iter->v; if (!BLI_ghash_haskey(n->bm_unique_verts, v)) { if (BLI_ghash_haskey(bvh->bm_vert_to_node, v)) { if (!BLI_ghash_haskey(n->bm_other_verts, v)) @@ -74,7 +77,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) } /* Update node bounding box */ BB_expand(&n->vb, v->co); - } + } while ((l_iter = l_iter->next) != l_first); } BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] && @@ -233,15 +236,16 @@ static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) prim_bbc = BLI_ghash_ptr_new("prim_bbc"); GHASH_ITER (gh_iter, bvh->nodes[node_index].bm_faces) { - BMIter bm_iter; - BMVert *v; BMFace *f = BLI_ghashIterator_getKey(&gh_iter); BBC *bbc = MEM_callocN(sizeof(BBC), "BBC"); + BMLoop *l_iter; + BMLoop *l_first; BB_reset((BB *)bbc); - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { - BB_expand((BB *)bbc, v->co); - } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BB_expand((BB *)bbc, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); BBC_update_centroid(bbc); BLI_ghash_insert(prim_bbc, f, bbc); @@ -394,14 +398,18 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v) static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) { PBVHNode *f_node; - BMIter bm_iter; BMVert *v; + BMLoop *l_iter; + BMLoop *l_first; + f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); /* Check if any of this face's vertices need to be removed * from the node */ - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + v = l_iter->v; if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) { if (BLI_ghash_lookup(f_node->bm_unique_verts, v)) { /* Find a different node that uses 'v' */ @@ -419,7 +427,7 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL); } } - } + } while ((l_iter = l_iter->next) != l_first); /* Remove face from node and top level */ BLI_ghash_remove(f_node->bm_faces, f, NULL, NULL); @@ -436,18 +444,21 @@ static BMVert *bm_triangle_other_vert_find(BMFace *triangle, const BMVert *v1, BLI_assert(v1 != v2); if (triangle->len == 3) { - BMIter iter; + BMLoop *l_iter; + BMLoop *l_first; BMVert *v, *other = NULL; - int found_v1 = FALSE, found_v2 = FALSE; + bool found_v1 = false, found_v2 = false; - BM_ITER_ELEM (v, &iter, triangle, BM_VERTS_OF_FACE) { + l_iter = l_first = BM_FACE_FIRST_LOOP(triangle); + do { + v = l_iter->v; if (v == v1) - found_v1 = TRUE; + found_v1 = true; else if (v == v2) - found_v2 = TRUE; + found_v2 = true; else other = v; - } + } while ((l_iter = l_iter->next) != l_first); if (found_v1 && found_v2) return other; @@ -508,7 +519,9 @@ static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) float c[3]; /* Get closest point in triangle to sphere center */ - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + BM_face_as_array_vert_tri(f, v); + closest_on_tri_to_point_v3(c, q->center, v[0]->co, v[1]->co, v[2]->co); /* Check if triangle intersects the sphere */ @@ -810,7 +823,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, int ni; /* Get vertices, replace use of v2 with v1 */ - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + BM_face_as_array_vert_tri(f, v); for (i = 0; i < 3; i++) { if (v[i] == v2) v[i] = v1; @@ -845,7 +859,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, BMVert *v[3]; int j; - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v, 3); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v, 3); + BM_face_as_array_vert_tri(f_del, v); /* Check if any of the face's vertices are now unused, if so remove them from the PBVH */ @@ -965,12 +980,13 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], if (f->len == 3) { BMVert *v[3]; - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + BM_face_as_array_vert_tri(f, v); hit |= ray_face_intersection(ray_start, ray_normal, - v[0]->co, - v[1]->co, - v[2]->co, - NULL, dist); + v[0]->co, + v[1]->co, + v[2]->co, + NULL, dist); } } } @@ -1083,6 +1099,17 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, return modified; } +BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3]) +{ + BMLoop *l = BM_FACE_FIRST_LOOP(f); + + BLI_assert(f->len == 3); + + r_index[0] = BM_elem_index_get(l->v); l = l->next; + r_index[1] = BM_elem_index_get(l->v); l = l->next; + r_index[2] = BM_elem_index_get(l->v); +} + /* In order to perform operations on the original node coordinates * (such as raycast), store the node's triangles and vertices.*/ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) @@ -1120,15 +1147,19 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) /* Copy the triangles */ i = 0; GHASH_ITER (gh_iter, node->bm_faces) { - BMIter bm_iter; BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + +#if 0 + BMIter bm_iter; BMVert *v; int j = 0; - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { node->bm_ortri[i][j] = BM_elem_index_get(v); j++; } +#else + bm_face_as_array_index_tri(f, node->bm_ortri[i]); +#endif i++; } node->bm_tot_ortri = i; -- cgit v1.2.3 From 458533628596497c8f15175812932ebf986f5d0f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Jan 2013 22:56:08 +0000 Subject: speed-up dyn-topo by storing the edge-loops rather then edge-faces. - no need for bm_triangle_other_vert_find(), the other vert is known relative to the loop. - no need for bm_face_edge_backwards(), the verts are in order in the loop. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 116 ++++++++------------------ 1 file changed, 33 insertions(+), 83 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 639a7e3691f..46324b4207b 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -437,60 +437,10 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) BM_log_face_removed(bvh->bm_log, f); } -static BMVert *bm_triangle_other_vert_find(BMFace *triangle, const BMVert *v1, - const BMVert *v2) -{ - BLI_assert(triangle->len == 3); - BLI_assert(v1 != v2); - - if (triangle->len == 3) { - BMLoop *l_iter; - BMLoop *l_first; - BMVert *v, *other = NULL; - bool found_v1 = false, found_v2 = false; - - l_iter = l_first = BM_FACE_FIRST_LOOP(triangle); - do { - v = l_iter->v; - if (v == v1) - found_v1 = true; - else if (v == v2) - found_v2 = true; - else - other = v; - } while ((l_iter = l_iter->next) != l_first); - - if (found_v1 && found_v2) - return other; - } - - BLI_assert(0); - return NULL; -} - -static void pbvh_bmesh_edge_faces(BLI_Buffer *buf, BMEdge *e) +static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e) { BLI_buffer_resize(buf, BM_edge_face_count(e)); - BM_iter_as_array(NULL, BM_FACES_OF_EDGE, e, buf->data, buf->count); -} - -/* TODO: maybe a better way to do this, if not then this should go to - * bmesh_queries */ -static int bm_face_edge_backwards(BMFace *f, BMEdge *e) -{ - BMIter bm_iter; - BMLoop *l, *l1 = NULL, *l2 = NULL; - - BM_ITER_ELEM (l, &bm_iter, f, BM_LOOPS_OF_FACE) { - if (l->v == e->v1) - l1 = l; - else if (l->v == e->v2) - l2 = l; - } - - BLI_assert(l1 && l2); - BLI_assert(l1->next == l2 || l2->next == l1); - return l2->next == l1; + BM_iter_as_array(NULL, BM_LOOPS_OF_EDGE, e, buf->data, buf->count); } static void pbvh_bmesh_node_drop_orig(PBVHNode *node) @@ -668,25 +618,26 @@ static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, /*************************** Topology update **************************/ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, - BMEdge *e, BLI_Buffer *edge_faces) + BMEdge *e, BLI_Buffer *edge_loops) { BMVert *v_new; float mid[3]; int i, node_index; /* Get all faces adjacent to the edge */ - pbvh_bmesh_edge_faces(edge_faces, e); + pbvh_bmesh_edge_loops(edge_loops, e); /* Create a new vertex in current node at the edge's midpoint */ mid_v3_v3v3(mid, e->v1->co, e->v2->co); node_index = GET_INT_FROM_POINTER(BLI_ghash_lookup(bvh->bm_vert_to_node, - e->v1)); + e->v1)); v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1); /* For each face, add two new triangles and delete the original */ - for (i = 0; i < edge_faces->count; i++) { - BMFace *f_adj = BLI_buffer_at(edge_faces, BMFace *, i); + for (i = 0; i < edge_loops->count; i++) { + BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i); + BMFace *f_adj = l_adj->f; BMFace *f_new; BMVert *opp, *v1, *v2; void *nip; @@ -700,15 +651,13 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers; /* Find the vertex not in the edge */ - opp = bm_triangle_other_vert_find(f_adj, e->v1, e->v2); + opp = l_adj->prev->v; /* Get e->v1 and e->v2 in the order they appear in the * existing face so that the new faces' winding orders * match */ - v1 = e->v1; - v2 = e->v2; - if (bm_face_edge_backwards(f_adj, e)) - SWAP(BMVert *, v1, v2); + v1 = l_adj->v; + v2 = l_adj->next->v; if (ni != node_index && i == 0) pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new); @@ -744,8 +693,8 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, } static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q, - BLI_mempool *pool, - BLI_Buffer *edge_faces) + BLI_mempool *pool, + BLI_Buffer *edge_loops) { int any_subdivided = FALSE; @@ -777,30 +726,31 @@ static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q, any_subdivided = TRUE; - pbvh_bmesh_split_edge(bvh, q, pool, e, edge_faces); + pbvh_bmesh_split_edge(bvh, q, pool, e, edge_loops); } return any_subdivided; } static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, - BMVert *v2, GHash *deleted_verts, - BLI_Buffer *edge_faces, - BLI_Buffer *deleted_faces) + BMVert *v2, GHash *deleted_verts, + BLI_Buffer *edge_loops, + BLI_Buffer *deleted_faces) { BMIter bm_iter; BMFace *f; int i; /* Get all faces adjacent to the edge */ - pbvh_bmesh_edge_faces(edge_faces, e); + pbvh_bmesh_edge_loops(edge_loops, e); /* Remove the merge vertex from the PBVH */ pbvh_bmesh_vert_remove(bvh, v2); /* Remove all faces adjacent to the edge */ - for (i = 0; i < edge_faces->count; i++) { - BMFace *f_adj = BLI_buffer_at(edge_faces, BMFace *, i); + for (i = 0; i < edge_loops->count; i++) { + BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i); + BMFace *f_adj = l_adj->f; pbvh_bmesh_face_remove(bvh, f_adj); BM_face_kill(bvh->bm, f_adj); @@ -899,9 +849,9 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, } static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q, - BLI_mempool *pool, - BLI_Buffer *edge_faces, - BLI_Buffer *deleted_faces) + BLI_mempool *pool, + BLI_Buffer *edge_loops, + BLI_Buffer *deleted_faces) { float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; GHash *deleted_verts; @@ -943,8 +893,8 @@ static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q, any_collapsed = TRUE; pbvh_bmesh_collapse_edge(bvh, e, v1, v2, - deleted_verts, edge_faces, - deleted_faces); + deleted_verts, edge_loops, + deleted_faces); } BLI_ghash_free(deleted_verts, NULL, NULL); @@ -1056,7 +1006,7 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading, int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, const float center[3], float radius) { - BLI_buffer_declare_static(BMFace *, edge_faces, BLI_BUFFER_NOP, 8); + BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 8); BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32); int modified = FALSE; @@ -1065,10 +1015,10 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, if (mode & PBVH_Collapse) { EdgeQueue q; BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, - 128, 128, 0); + 128, 128, 0); short_edge_queue_create(&q, queue_pool, bvh, center, radius); - pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_faces, - &deleted_faces); + pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_loops, + &deleted_faces); BLI_heap_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); } @@ -1076,9 +1026,9 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, if (mode & PBVH_Subdivide) { EdgeQueue q; BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, - 128, 128, 0); + 128, 128, 0); long_edge_queue_create(&q, queue_pool, bvh, center, radius); - pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_faces); + pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_loops); BLI_heap_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); } @@ -1093,7 +1043,7 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, node->flag &= ~PBVH_UpdateTopology; } } - BLI_buffer_free(&edge_faces); + BLI_buffer_free(&edge_loops); BLI_buffer_free(&deleted_faces); return modified; -- cgit v1.2.3 From ba5e6380bea30c4194479adfec18debfa32fc018 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Jan 2013 23:10:32 +0000 Subject: code cleanup: rename BMVert *v[3]; --> 'v_tri', since 'v' is normally for single verts. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 61 ++++++++++++++------------- 1 file changed, 31 insertions(+), 30 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 46324b4207b..e864cc085b6 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -290,9 +290,9 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index, return v; } -static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, BMVert *v1, - BMVert *v2, BMVert *v3, - const BMFace *UNUSED(example)) +static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, + BMVert *v1, BMVert *v2, BMVert *v3, + const BMFace *UNUSED(example)) { BMFace *f; void *val = SET_INT_IN_POINTER(node_index); @@ -465,14 +465,14 @@ typedef struct { static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) { - BMVert *v[3]; + BMVert *v_tri[3]; float c[3]; /* Get closest point in triangle to sphere center */ - // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); - BM_face_as_array_vert_tri(f, v); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3); + BM_face_as_array_vert_tri(f, v_tri); - closest_on_tri_to_point_v3(c, q->center, v[0]->co, v[1]->co, v[2]->co); + closest_on_tri_to_point_v3(c, q->center, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co); /* Check if triangle intersects the sphere */ return ((len_squared_v3v3(q->center, c) <= q->radius_squared)); @@ -767,31 +767,32 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, * really buy anything. */ deleted_faces->count = 0; BM_ITER_ELEM (f, &bm_iter, v2, BM_FACES_OF_VERT) { - BMVert *v[3]; + BMVert *v_tri[3]; BMFace *existing_face; PBVHNode *n; int ni; /* Get vertices, replace use of v2 with v1 */ - // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); - BM_face_as_array_vert_tri(f, v); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3); + BM_face_as_array_vert_tri(f, v_tri); for (i = 0; i < 3; i++) { - if (v[i] == v2) - v[i] = v1; + if (v_tri[i] == v2) { + v_tri[i] = v1; + } } /* Check if a face using these vertices already exists. If so, * skip adding this face and mark the existing one for * deletion as well. Prevents extraneous "flaps" from being * created. */ - if (BM_face_exists(v, 3, &existing_face)) { + if (BM_face_exists(v_tri, 3, &existing_face)) { BLI_assert(existing_face); BLI_buffer_append(deleted_faces, BMFace *, existing_face); } else { n = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); ni = n - bvh->nodes; - pbvh_bmesh_face_create(bvh, ni, v[0], v[1], v[2], f); + pbvh_bmesh_face_create(bvh, ni, v_tri[0], v_tri[1], v_tri[2], f); /* Ensure that v1 is in the new face's node */ if (!BLI_ghash_haskey(n->bm_unique_verts, v1) && @@ -806,21 +807,21 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, /* Delete the tagged faces */ for (i = 0; i < deleted_faces->count; i++) { BMFace *f_del = BLI_buffer_at(deleted_faces, BMFace *, i); - BMVert *v[3]; + BMVert *v_tri[3]; int j; - // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v, 3); - BM_face_as_array_vert_tri(f_del, v); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v_tri, 3); + BM_face_as_array_vert_tri(f_del, v_tri); /* Check if any of the face's vertices are now unused, if so remove them from the PBVH */ for (j = 0; j < 3; j++) { - if (v[j] != v2 && BM_vert_face_count(v[j]) == 0) { - BLI_ghash_insert(deleted_verts, v[j], NULL); - pbvh_bmesh_vert_remove(bvh, v[j]); + if (v_tri[j] != v2 && BM_vert_face_count(v_tri[j]) == 0) { + BLI_ghash_insert(deleted_verts, v_tri[j], NULL); + pbvh_bmesh_vert_remove(bvh, v_tri[j]); } else { - v[j] = NULL; + v_tri[j] = NULL; } } @@ -830,9 +831,9 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, /* Delete unused vertices */ for (j = 0; j < 3; j++) { - if (v[j]) { - BM_log_vert_removed(bvh->bm, bvh->bm_log, v[j]); - BM_vert_kill(bvh->bm, v[j]); + if (v_tri[j]) { + BM_log_vert_removed(bvh->bm, bvh->bm_log, v_tri[j]); + BM_vert_kill(bvh->bm, v_tri[j]); } } } @@ -928,14 +929,14 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], BLI_assert(f->len == 3); if (f->len == 3) { - BMVert *v[3]; + BMVert *v_tri[3]; - // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); - BM_face_as_array_vert_tri(f, v); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3); + BM_face_as_array_vert_tri(f, v_tri); hit |= ray_face_intersection(ray_start, ray_normal, - v[0]->co, - v[1]->co, - v[2]->co, + v_tri[0]->co, + v_tri[1]->co, + v_tri[2]->co, NULL, dist); } } -- cgit v1.2.3 From d6c4d2a4155e8293894d9dfaf51c7e4e08a7c6d5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Jan 2013 23:12:43 +0000 Subject: fix bug in dyntopo - check to remove pbvh vert was always false. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index e864cc085b6..ce6f3ddb9b3 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -816,7 +816,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, /* Check if any of the face's vertices are now unused, if so remove them from the PBVH */ for (j = 0; j < 3; j++) { - if (v_tri[j] != v2 && BM_vert_face_count(v_tri[j]) == 0) { + if (v_tri[j] != v2 && BM_vert_face_count(v_tri[j]) == 1) { BLI_ghash_insert(deleted_verts, v_tri[j], NULL); pbvh_bmesh_vert_remove(bvh, v_tri[j]); } -- cgit v1.2.3 From 93b58752d2795f870ddd2078db21c6cbe38e5b70 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Jan 2013 23:20:09 +0000 Subject: minor speedup for dyntopo edge queue - replace iterator with while loop. --- source/blender/blenkernel/intern/pbvh_bmesh.c | 40 +++++++++++++-------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index ce6f3ddb9b3..7ffadde2f08 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -505,36 +505,34 @@ static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool, edge_queue_insert(q, pool, e, len_sq); } -static int long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, - BMFace *f) +static void long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, + BMFace *f) { - BMIter bm_iter; - BMEdge *e; - if (edge_queue_tri_in_sphere(q, f)) { + BMLoop *l_iter; + BMLoop *l_first; + /* Check each edge of the face */ - BM_ITER_ELEM (e, &bm_iter, f, BM_EDGES_OF_FACE) { - long_edge_queue_edge_add(q, pool, e); - } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + long_edge_queue_edge_add(q, pool, l_iter->e); + } while ((l_iter = l_iter->next) != l_first); } - - return TRUE; } -static int short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, - BMFace *f) +static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, + BMFace *f) { - BMIter bm_iter; - BMEdge *e; - if (edge_queue_tri_in_sphere(q, f)) { + BMLoop *l_iter; + BMLoop *l_first; + /* Check each edge of the face */ - BM_ITER_ELEM (e, &bm_iter, f, BM_EDGES_OF_FACE) { - short_edge_queue_edge_add(q, pool, e); - } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + short_edge_queue_edge_add(q, pool, l_iter->e); + } while ((l_iter = l_iter->next) != l_first); } - - return TRUE; } /* Create a priority queue containing vertex pairs connected by a long @@ -814,7 +812,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, BM_face_as_array_vert_tri(f_del, v_tri); /* Check if any of the face's vertices are now unused, if so - remove them from the PBVH */ + * remove them from the PBVH */ for (j = 0; j < 3; j++) { if (v_tri[j] != v2 && BM_vert_face_count(v_tri[j]) == 1) { BLI_ghash_insert(deleted_verts, v_tri[j], NULL); -- cgit v1.2.3 From 146d1b9cab47378734dcc61562336f4582d68b0b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 Jan 2013 08:46:46 +0000 Subject: minor changes to view3d - BKE_camera_params_from_object now sets the lens to 35 if the object isnt a camera/lamp, without this the view3d lens would be used in camera view. - running smooth-view multiple times now stores the initial user view rather then over-writing from the current state each time re-smoothview runs. - redraw panels after smoothview finishes. --- source/blender/blenkernel/intern/camera.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 57c88919021..d1842b99831 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -237,6 +237,9 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob) params->clipsta = la->clipsta; params->clipend = la->clipend; } + else { + params->lens = 35.0f; + } } void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView3D *rv3d) -- cgit v1.2.3 From ee0eb394c9c4cbe9466ac76a35431288e4f80aa9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 18 Jan 2013 06:26:06 +0000 Subject: use openmp sections for felling origindex arrays --- source/blender/blenkernel/BKE_DerivedMesh.h | 2 ++ source/blender/blenkernel/intern/DerivedMesh.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index f06547fe2e3..64fb49c4d66 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -95,6 +95,8 @@ struct BMEditMesh; struct ListBase; struct PBVH; +#define DM_OMP_LIMIT 0 /* setting zero so we can catch bugs in OpenMP/BMesh */ + /* number of sub-elements each mesh element has (for interpolation) */ #define SUB_ELEMS_VERT 0 #define SUB_ELEMS_EDGE 2 diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index dde1d5870ca..b3d95629143 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1584,9 +1584,15 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); - range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); - range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); +#pragma omp parallel sections if (dm->numVertData + dm->numEdgeData + dm->numPolyData >= DM_OMP_LIMIT) + { +#pragma omp section + { range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); } +#pragma omp section + { range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); } +#pragma omp section + { range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); } + } } } -- cgit v1.2.3 From 9660ba6c2b1093470d189947286adda483b8faff Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 18 Jan 2013 09:36:17 +0000 Subject: Fix #33910: Wipe effect starts and stops to early with blur enabled. Made small tweaks which now limits blur width in a way it can not be wider than distance between frame boundary and wipe effect center. It eliminates weirdeness of how blur appears/disappears in cases effect fac is close to 0/1. Could be tweaked further but will require effect rewrite it seems. --- source/blender/blenkernel/intern/seqeffects.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index c64609c8e70..c0e85352217 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -1317,7 +1317,8 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f switch (wipe->wipetype) { case DO_SINGLE_WIPE: - width = wipezone->width; + width = min_ii(wipezone->width, facf0 * yo); + width = min_ii(width, yo - facf0 * yo); if (angle == 0.0f) { b1 = posy; -- cgit v1.2.3 From a8abc11e42fefd8e6192e3a9bcc185b6428d36f4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 19 Jan 2013 00:17:10 +0000 Subject: dyntopo optimization - fast path for edges with 2 faces using it, was counting the edge-faces then using an iterator, instead use BM_edge_loop_pair() --- source/blender/blenkernel/intern/pbvh_bmesh.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 7ffadde2f08..7b6ad622deb 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -439,8 +439,18 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e) { - BLI_buffer_resize(buf, BM_edge_face_count(e)); - BM_iter_as_array(NULL, BM_LOOPS_OF_EDGE, e, buf->data, buf->count); + /* fast-path for most common case where an edge has 2 faces, + * no need to iterate twice. + * This assumes that the buffer */ + BMLoop **data = buf->data; + BLI_assert(buf->alloc_count >= 2); + if (LIKELY(BM_edge_loop_pair(e, &data[0], &data[1]))) { + buf->count = 2; + } + else { + BLI_buffer_resize(buf, BM_edge_face_count(e)); + BM_iter_as_array(NULL, BM_LOOPS_OF_EDGE, e, buf->data, buf->count); + } } static void pbvh_bmesh_node_drop_orig(PBVHNode *node) @@ -1003,9 +1013,10 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading, /* Collapse short edges, subdivide long edges */ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, - const float center[3], float radius) + const float center[3], float radius) { - BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 8); + /* 2 is enough for edge faces - manifold edge */ + BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 2); BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32); int modified = FALSE; -- cgit v1.2.3 From f45d8827bafe6b9eaf9de42f4054e9d84a21955d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 19 Jan 2013 02:01:18 +0000 Subject: CDDM_merge_verts() was building an index array for all loops and not using it. also use malloc over calloc since the values are filled in right after. --- source/blender/blenkernel/intern/cdderivedmesh.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 85dd4c67fdf..87826dafe31 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2285,6 +2285,7 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) { +// #define USE_LOOPS CDDerivedMesh *cddm = (CDDerivedMesh *)dm; CDDerivedMesh *cddm2 = NULL; MVert *mv, *mvert = NULL; @@ -2296,7 +2297,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) MLoop *ml, *mloop = NULL; BLI_array_declare(mloop); EdgeHash *ehash = BLI_edgehash_new(); - int *newv = NULL, *newe = NULL, *newl = NULL; + int *newv = NULL, *newe = NULL; +#ifdef USE_LOOPS + int *newl = NULL; +#endif int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL; BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp); int i, j, c, totloop, totpoly; @@ -2304,10 +2308,11 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) totloop = dm->numLoopData; totpoly = dm->numPolyData; - newv = MEM_callocN(sizeof(int) * dm->numVertData, "newv vtable CDDM_merge_verts"); - newe = MEM_callocN(sizeof(int) * dm->numEdgeData, "newv etable CDDM_merge_verts"); - newl = MEM_callocN(sizeof(int) * totloop, "newv ltable CDDM_merge_verts"); - + newv = MEM_mallocN(sizeof(int) * dm->numVertData, "newv vtable CDDM_merge_verts"); + newe = MEM_mallocN(sizeof(int) * dm->numEdgeData, "newv etable CDDM_merge_verts"); +#ifdef USE_LOOPS + newl = MEM_mallocN(sizeof(int) * totloop, "newv ltable CDDM_merge_verts"); +#endif /* fill newl with destination vertex indices */ mv = cddm->mvert; c = 0; @@ -2317,6 +2322,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) newv[i] = c++; BLI_array_append(mvert, *mv); } + else { + /* dummy value */ + newv[i] = 0; + } } /* now link target vertices to destination indices */ @@ -2385,7 +2394,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) for (j = 0; j < mp->totloop; j++, ml++) { med = cddm->medge + ml->e; if (LIKELY(med->v1 != med->v2)) { +#ifdef USE_LOOPS newl[j + mp->loopstart] = BLI_array_count(mloop); +#endif BLI_array_append(oldl, j + mp->loopstart); BLI_array_append(mloop, *ml); c++; @@ -2451,8 +2462,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) MEM_freeN(newv); if (newe) MEM_freeN(newe); +#ifdef USE_LOOPS if (newl) MEM_freeN(newl); +#endif if (oldv) MEM_freeN(oldv); if (olde) -- cgit v1.2.3 From 5006a39c271ae7025399a1ad28fd8dc19d50f092 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 19 Jan 2013 02:37:04 +0000 Subject: replace calloc with malloc for arrays that are filled in right after. --- source/blender/blenkernel/intern/DerivedMesh.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index b3d95629143..8ca6d045712 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -169,7 +169,7 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm) static MVert *dm_dupVertArray(DerivedMesh *dm) { - MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm), + MVert *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumVerts(dm), "dm_dupVertArray tmp"); if (tmp) dm->copyVertArray(dm, tmp); @@ -179,7 +179,7 @@ static MVert *dm_dupVertArray(DerivedMesh *dm) static MEdge *dm_dupEdgeArray(DerivedMesh *dm) { - MEdge *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumEdges(dm), + MEdge *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumEdges(dm), "dm_dupEdgeArray tmp"); if (tmp) dm->copyEdgeArray(dm, tmp); @@ -189,7 +189,7 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm) static MFace *dm_dupFaceArray(DerivedMesh *dm) { - MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumTessFaces(dm), + MFace *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumTessFaces(dm), "dm_dupFaceArray tmp"); if (tmp) dm->copyTessFaceArray(dm, tmp); @@ -199,7 +199,7 @@ static MFace *dm_dupFaceArray(DerivedMesh *dm) static MLoop *dm_dupLoopArray(DerivedMesh *dm) { - MLoop *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumLoops(dm), + MLoop *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumLoops(dm), "dm_dupLoopArray tmp"); if (tmp) dm->copyLoopArray(dm, tmp); @@ -209,7 +209,7 @@ static MLoop *dm_dupLoopArray(DerivedMesh *dm) static MPoly *dm_dupPolyArray(DerivedMesh *dm) { - MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumPolys(dm), + MPoly *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumPolys(dm), "dm_dupPolyArray tmp"); if (tmp) dm->copyPolyArray(dm, tmp); @@ -574,7 +574,7 @@ void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb) if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) return; if (kb->data) MEM_freeN(kb->data); - kb->data = MEM_callocN(me->key->elemsize * me->totvert, "kb->data"); + kb->data = MEM_mallocN(me->key->elemsize * me->totvert, "kb->data"); kb->totelem = totvert; fp = kb->data; @@ -2359,15 +2359,14 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) return NULL; dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); - vertexcosnos = MEM_callocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map"); if (dm->foreachMappedVert) { + vertexcosnos = MEM_callocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map"); dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos); } else { - DMCoNo *v_co_no = vertexcosnos; + DMCoNo *v_co_no = vertexcosnos = MEM_mallocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map"); int a; - for (a = 0; a < me->totvert; a++, v_co_no++) { dm->getVertCo(dm, a, v_co_no->co); dm->getVertNo(dm, a, v_co_no->no); -- cgit v1.2.3 From 162c3314170167f097e9befb028e71c4fde463fc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 19 Jan 2013 06:12:25 +0000 Subject: style cleanup --- source/blender/blenkernel/BKE_particle.h | 2 +- source/blender/blenkernel/intern/multires.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index f15ad296e4a..3394c4f4ce0 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -306,7 +306,7 @@ int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct Pa void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata); void psys_sph_finalise(struct SPHData *sphdata); -void psys_sph_density(struct BVHTree *tree, struct SPHData* data, float co[3], float vars[2]); +void psys_sph_density(struct BVHTree *tree, struct SPHData *data, float co[3], float vars[2]); /* for anim.c */ void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part, diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index b12463daf72..722e1f2b918 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1559,7 +1559,7 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp) if (S == 1) { (*out)[1] = -(*out)[1]; } else if (S == 2) { SWAP(float, (*out)[0], (*out)[1]); } else if (S == 3) { (*out)[0] = -(*out)[0]; } - else if (S == 0) { SWAP(float, (*out)[0], (*out)[1]); (*out)[0] = -(*out)[0]; (*out)[1] = -(*out)[1]; }; + else if (S == 0) { SWAP(float, (*out)[0], (*out)[1]); (*out)[0] = -(*out)[0]; (*out)[1] = -(*out)[1]; } } } } -- cgit v1.2.3 From 9a50f454697e5dea6e8603aa90fadaa6156657d6 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 19 Jan 2013 16:10:21 +0000 Subject: Skip hidden faces in PBVH BMesh ray intersection test Moved the GPU function gpu_bmesh_face_visible() to BKE_paint and inverted the test to match equivalent tests for other mesh types: paint_is_bmesh_face_hidden(). Changed BKE_pbvh_bmesh_node_save_orig() to not save hidden faces into the triangle array. Modified the non-use-original branch of pbvh_bmesh_node_raycast() to skip hidden faces. Fixes bug #33914: projects.blender.org/tracker/index.php?func=detail&aid=33914&group_id=9&atid=498 --- source/blender/blenkernel/BKE_paint.h | 2 ++ source/blender/blenkernel/intern/paint.c | 18 ++++++++++++++++++ source/blender/blenkernel/intern/pbvh_bmesh.c | 11 ++++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 0a4a7f75e25..078923ee5f9 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -34,6 +34,7 @@ struct bContext; struct BMesh; +struct BMFace; struct Brush; struct MDisps; struct MeshElemMap; @@ -72,6 +73,7 @@ int paint_vertsel_test(struct Object *ob); int paint_is_face_hidden(const struct MFace *f, const struct MVert *mvert); int paint_is_grid_face_hidden(const unsigned int *grid_hidden, int gridsize, int x, int y); +int paint_is_bmesh_face_hidden(struct BMFace *f); /* paint masks */ float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level, diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 5847e7508f0..dc8aed91c00 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -47,6 +47,8 @@ #include "BKE_paint.h" #include "BKE_subsurf.h" +#include "bmesh.h" + #include #include @@ -224,6 +226,22 @@ int paint_is_grid_face_hidden(const unsigned int *grid_hidden, BLI_BITMAP_GET(grid_hidden, (y + 1) * gridsize + x)); } +/* Return TRUE if all vertices in the face are visible, FALSE otherwise */ +int paint_is_bmesh_face_hidden(BMFace *f) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN)) { + return true; + } + } while ((l_iter = l_iter->next) != l_first); + + return false; +} + float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, unsigned x, unsigned y) { diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 7b6ad622deb..f3ac22f0df7 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -28,6 +28,7 @@ #include "BKE_ccg.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" +#include "BKE_paint.h" #include "BKE_pbvh.h" #include "GPU_buffers.h" @@ -936,10 +937,9 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], BMFace *f = BLI_ghashIterator_getKey(&gh_iter); BLI_assert(f->len == 3); - if (f->len == 3) { + if (f->len == 3 && !paint_is_bmesh_face_hidden(f)) { BMVert *v_tri[3]; - // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3); BM_face_as_array_vert_tri(f, v_tri); hit |= ray_face_intersection(ray_start, ray_normal, v_tri[0]->co, @@ -1071,7 +1071,9 @@ BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3]) } /* In order to perform operations on the original node coordinates - * (such as raycast), store the node's triangles and vertices.*/ + * (currently just raycast), store the node's triangles and vertices. + * + * Skips triangles that are hidden. */ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) { GHashIterator gh_iter; @@ -1109,6 +1111,9 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) GHASH_ITER (gh_iter, node->bm_faces) { BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + if (paint_is_bmesh_face_hidden(f)) + continue; + #if 0 BMIter bm_iter; BMVert *v; -- cgit v1.2.3 From 4256ad75666a119bdcea3726c3d524ff92870ae0 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 20 Jan 2013 00:19:57 +0000 Subject: Update object bounding box during sculpt Fixes the sculpt object being incorrectly clipped during drawing due to an out-of-date bounding box making it seem that the object had gone outside the view. Added a BKE_pbvh function to get the top-level bounding box. In sculpt_flush_update(), where the PBVH bounds are updated, the result is copied to the object's bounding box. Fixes bug [#33790] projects.blender.org/tracker/?func=detail&aid=33790&group_id=9&atid=498 --- source/blender/blenkernel/BKE_pbvh.h | 3 +++ source/blender/blenkernel/intern/pbvh.c | 13 +++++++++++++ 2 files changed, 16 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 709db7e4570..99ed978561e 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -113,6 +113,9 @@ typedef enum { PBVHType BKE_pbvh_type(const PBVH *bvh); +/* Get the PBVH root's bounding box */ +void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]); + /* multires hidden data, only valid for type == PBVH_GRIDS */ unsigned int **BKE_pbvh_grid_hidden(const PBVH *bvh); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 2df2dd631d5..f72bcded9ad 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1238,6 +1238,19 @@ PBVHType BKE_pbvh_type(const PBVH *bvh) return bvh->type; } +void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]) +{ + if (bvh->totnode) { + const BB *bb = &bvh->nodes[0].vb; + copy_v3_v3(min, bb->bmin); + copy_v3_v3(max, bb->bmax); + } + else { + zero_v3(min); + zero_v3(max); + } +} + BLI_bitmap *BKE_pbvh_grid_hidden(const PBVH *bvh) { BLI_assert(bvh->type == PBVH_GRIDS); -- cgit v1.2.3 From 4ca7bad74865bdb147cfca5851cac49b11f825c1 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 20 Jan 2013 00:46:33 +0000 Subject: Delete loose edges left behind by sculpting with collapse-short-edges After deleting a face, check for unused edges and delete them. Fixes bug [#33891] projects.blender.org/tracker/?func=detail&aid=33891&group_id=9&atid=498 --- source/blender/blenkernel/intern/pbvh_bmesh.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index f3ac22f0df7..c464de64c6a 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -817,10 +817,13 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, for (i = 0; i < deleted_faces->count; i++) { BMFace *f_del = BLI_buffer_at(deleted_faces, BMFace *, i); BMVert *v_tri[3]; + BMEdge *e_tri[3]; int j; - // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v_tri, 3); + /* Get vertices and edges of face */ BM_face_as_array_vert_tri(f_del, v_tri); + for (j = 0; j < 3; j++) + e_tri[j] = BM_edge_exists(v_tri[j], v_tri[j == 2 ? 0 : j + 1]); /* Check if any of the face's vertices are now unused, if so * remove them from the PBVH */ @@ -838,6 +841,13 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, pbvh_bmesh_face_remove(bvh, f_del); BM_face_kill(bvh->bm, f_del); + /* Check if any of the face's edges are now unused by any + * face, if so delete them */ + for (j = 0; j < 3; j++) { + if (BM_edge_face_count(e_tri[j]) == 0) + BM_edge_kill(bvh->bm, e_tri[j]); + } + /* Delete unused vertices */ for (j = 0; j < 3; j++) { if (v_tri[j]) { -- cgit v1.2.3 From bc44e81dfff0b185e5d6639a9b54499c20c1524a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 20 Jan 2013 08:05:23 +0000 Subject: fix own bug with uninitialized arrays in subdivide (from recent BLI_array.h update) also quiet warning. --- source/blender/blenkernel/intern/cdderivedmesh.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 87826dafe31..662cebd7204 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2303,9 +2303,14 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) #endif int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL; BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp); - int i, j, c, totloop, totpoly; - + int i, j, c, totpoly; +#ifdef USE_LOOPS + int totloop; +#endif + +#ifdef USE_LOOPS totloop = dm->numLoopData; +#endif totpoly = dm->numPolyData; newv = MEM_mallocN(sizeof(int) * dm->numVertData, "newv vtable CDDM_merge_verts"); -- cgit v1.2.3 From f414d2980a70bd544d1ab2a560859a5622cba9e5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 20 Jan 2013 14:50:50 +0000 Subject: code cleanup: remove some paranoid checks which would have crashed anyway earlier on. Also some minor formatting. --- source/blender/blenkernel/intern/CCGSubSurf.c | 21 ++++++++++++++------- source/blender/blenkernel/intern/pointcache.c | 3 ++- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index bbda6f8a292..2079c783898 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -1416,18 +1416,25 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, float no[3]; for (S = 0; S < f->numVerts; S++) { - for (y = 0; y < gridSize - 1; y++) - for (x = 0; x < gridSize - 1; x++) + for (y = 0; y < gridSize - 1; y++) { + for (x = 0; x < gridSize - 1; x++) { NormZero(FACE_getIFNo(f, lvl, S, x, y)); + } + } - if (FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected) - for (x = 0; x < gridSize - 1; x++) + if (FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected) { + for (x = 0; x < gridSize - 1; x++) { NormZero(FACE_getIFNo(f, lvl, S, x, gridSize - 1)); - if (FACE_getEdges(f)[S]->flags & Edge_eEffected) - for (y = 0; y < gridSize - 1; y++) + } + } + if (FACE_getEdges(f)[S]->flags & Edge_eEffected) { + for (y = 0; y < gridSize - 1; y++) { NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, y)); - if (FACE_getVerts(f)[S]->flags & Vert_eEffected) + } + } + if (FACE_getVerts(f)[S]->flags & Vert_eEffected) { NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, gridSize - 1)); + } } for (S = 0; S < f->numVerts; S++) { diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 97948683e22..2f21e588b85 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -308,8 +308,9 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float cf pa->lifetime = times[2]; } - if (boid) + if (boid) { PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); + } /* determine velocity from previous location */ if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { -- cgit v1.2.3 From e6f82619899af71b823e58812b231599d4dd46e2 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Sun, 20 Jan 2013 21:32:14 +0000 Subject: 3D mapping for projective texture painting (only for draw brush). Useful to draw with procedural textures on surface of object. 2D painting will still paint as if tiled. When we unify the paint systems, the texture sampling functions will need to be changed. Sculpt uses a slightly different system that passes both screen and 3d coordinates to the sampling function. This commit however is not too disrupting for that however so it can go in now. --- source/blender/blenkernel/BKE_brush.h | 3 +- source/blender/blenkernel/intern/brush.c | 55 +++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 9 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 248fe9c8968..b19a9c4d4eb 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -67,7 +67,8 @@ float BKE_brush_curve_strength_clamp(struct Brush *br, float p, const float len) float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ /* sampling */ -void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread); +void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float sampleco[3], float rgba[4], const int thread); +void BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread); void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf, int use_color_correction); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index e8275471b09..bb4f073a3d7 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -471,8 +471,46 @@ int BKE_brush_clone_image_delete(Brush *brush) return 0; } -/* Brush Sampling */ -void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread) +/* Brush Sampling for 3d brushes. Currently used for texture painting only, but should be generalized */ +void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco[3], float rgba[4], const int thread) +{ + MTex *mtex = &brush->mtex; + + if (mtex && mtex->tex) { + float co[3], tin, tr, tg, tb, ta; + int hasrgb; + const int radius = BKE_brush_size_get(scene, brush); + + if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { + copy_v3_v3(co, sampleco); + } else { + co[0] = sampleco[0] / radius; + co[1] = sampleco[1] / radius; + co[2] = 0.0f; + } + + hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); + + if (hasrgb) { + rgba[0] = tr; + rgba[1] = tg; + rgba[2] = tb; + rgba[3] = ta; + } + else { + rgba[0] = tin; + rgba[1] = tin; + rgba[2] = tin; + rgba[3] = 1.0f; + } + } + else { + rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f; + } +} + +/* Brush Sampling for 2D brushes. when we unify the brush systems this will be necessarily a separate function */ +void BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread) { MTex *mtex = &brush->mtex; @@ -505,7 +543,8 @@ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], f } } -/* TODO, use define for 'texfall' arg */ +/* TODO, use define for 'texfall' arg + * NOTE: only used for 2d brushes currently! */ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction) { ImBuf *ibuf; @@ -544,10 +583,10 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } else if (texfall == 1) { - BKE_brush_sample_tex(scene, brush, xy, dstf, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, dstf, 0); } else { - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); mul_v3_v3v3(dstf, rgba, brush_rgb); dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } @@ -574,11 +613,11 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dst[3] = FTOCHAR(alpha_f); } else if (texfall == 1) { - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); rgba_float_to_uchar(dst, rgba); } else if (texfall == 2) { - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); mul_v3_v3(rgba, brush->rgb); alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); @@ -587,7 +626,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dst[3] = FTOCHAR(alpha_f); } else { - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); dst[0] = crgb[0]; -- cgit v1.2.3 From 8e934014d7a43acb62f1a2625a6979babfdcabc5 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Mon, 21 Jan 2013 01:01:15 +0000 Subject: Ommit extraneous check for paint tool in 3d mapping case (Only draw tool uses this anyway) and avoid copying of coordinate for 3D case. --- source/blender/blenkernel/intern/brush.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index bb4f073a3d7..6d655f8b495 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -477,19 +477,22 @@ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco MTex *mtex = &brush->mtex; if (mtex && mtex->tex) { - float co[3], tin, tr, tg, tb, ta; + float tin, tr, tg, tb, ta; int hasrgb; const int radius = BKE_brush_size_get(scene, brush); if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { - copy_v3_v3(co, sampleco); - } else { + hasrgb = externtex(mtex, sampleco, &tin, &tr, &tg, &tb, &ta, thread); + } + else { + float co[3]; + co[0] = sampleco[0] / radius; co[1] = sampleco[1] / radius; co[2] = 0.0f; - } - hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); + hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); + } if (hasrgb) { rgba[0] = tr; -- cgit v1.2.3 From 38cee985bb6d6a45fe59cc539dfa9cd6412b6f36 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 Jan 2013 02:30:40 +0000 Subject: code cleanup: style & warnings. --- source/blender/blenkernel/intern/pbvh.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index f72bcded9ad..483dd2570e2 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1399,10 +1399,10 @@ void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data, } int ray_face_intersection(const float ray_start[3], - const float ray_normal[3], - const float *t0, const float *t1, - const float *t2, const float *t3, - float *fdist) + const float ray_normal[3], + const float *t0, const float *t1, + const float *t2, const float *t3, + float *fdist) { float dist; -- cgit v1.2.3 From 86991fbcb0e8a1c65acff5aed85ce55f8b108baa Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 21 Jan 2013 08:49:42 +0000 Subject: Fixed render time regression in Blender Internal It was caused by image threading safe commit and it was noticeable only on really multi-core CPU (like dual-socket Xeon stations), was not visible on core i7 machine. The reason of slowdown was spinlock around image buffer referencing, which lead to lots of cores waiting for single core and using image buffer after it was referenced was not so much longer than doing reference itself. The most clear solution here seemed to be introducing Image Pool which will contain list of loaded and referenced image buffers, so all threads could skip lock if the pool is used for reading only. Lock only needed in cases when buffer for requested image user is missing in the pool. This lock will happen only once per image so overall amount of locks is much less that it was before. To operate with pool: - BKE_image_pool_new() creates new pool - BKE_image_pool_free() destroys pool and dereferences all image buffers which were loaded to it - BKE_image_pool_acquire_ibuf() returns image buffer for given image and user. Pool could be NULL and in this case fallback to BKE_image_acquire_ibuf will happen. This helps to avoid lots to if(poll) checks in image sampling code. - BKE_image_pool_release_ibuf releases image buffer. In fact, it will only do something if pool is NULL, in all other case it'll equal to DoNothing operation. --- source/blender/blenkernel/BKE_image.h | 6 ++ source/blender/blenkernel/BKE_paint.h | 2 + source/blender/blenkernel/intern/dynamicpaint.c | 9 +- source/blender/blenkernel/intern/effect.c | 8 +- source/blender/blenkernel/intern/image.c | 135 ++++++++++++++++++++++++ source/blender/blenkernel/intern/object.c | 4 + source/blender/blenkernel/intern/smoke.c | 2 +- 7 files changed, 158 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 597f2f25575..bfee5e820c3 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -44,6 +44,7 @@ struct anim; struct Scene; struct Object; struct ImageFormatData; +struct ImagePool; struct Main; #define IMA_MAX_SPACE 64 @@ -146,6 +147,11 @@ int BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser); struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r); void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock); +struct ImagePool *BKE_image_pool_new(void); +void BKE_image_pool_free(struct ImagePool *pool); +struct ImBuf *BKE_image_pool_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, struct ImagePool *pool); +void BKE_image_pool_release_ibuf(struct Image *ima, struct ImBuf *ibuf, struct ImagePool *pool); + /* returns a new image or NULL if it can't load */ struct Image *BKE_image_load(const char *filepath); /* returns existing Image when filename/type is same (frame optional) */ diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 078923ee5f9..211b6189fa8 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -47,6 +47,7 @@ struct Paint; struct PBVH; struct Scene; struct StrokeCache; +struct ImagePool; extern const char PAINT_CURSOR_SCULPT[3]; extern const char PAINT_CURSOR_VERTEX_PAINT[3]; @@ -116,6 +117,7 @@ typedef struct SculptSession { /* Used to cache the render of the active texture */ unsigned int texcache_side, *texcache, texcache_actual; + struct ImagePool *tex_pool; /* Layer brush persistence between strokes */ float (*layer_co)[3]; /* Copy of the mesh vertices' locations */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index fff51ab2a59..c92c52a7651 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1483,7 +1483,9 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) /* for vertex surface loop through tfaces and find uv color * that provides highest alpha */ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { - #pragma omp parallel for schedule(static) + struct ImagePool *pool = BKE_image_pool_new(); + + #pragma omp parallel for schedule(static) shared(pool) for (i = 0; i < numOfFaces; i++) { int numOfVert = (mface[i].v4) ? 4 : 3; float uv[3] = {0.0f}; @@ -1496,7 +1498,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) uv[0] = tface[i].uv[j][0] * 2.0f - 1.0f; uv[1] = tface[i].uv[j][1] * 2.0f - 1.0f; - multitex_ext_safe(tex, uv, &texres); + multitex_ext_safe(tex, uv, &texres, pool); if (texres.tin > pPoint[*vert].alpha) { copy_v3_v3(pPoint[*vert].color, &texres.tr); @@ -1504,6 +1506,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) } } } + BKE_image_pool_free(pool); } else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; @@ -1529,7 +1532,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) uv_final[0] = uv_final[0] * 2.0f - 1.0f; uv_final[1] = uv_final[1] * 2.0f - 1.0f; - multitex_ext_safe(tex, uv_final, &texres); + multitex_ext_safe(tex, uv_final, &texres, NULL); /* apply color */ copy_v3_v3(pPoint[i].color, &texres.tr); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 1f6db19ac27..1880cb42f4d 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -769,7 +769,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP mul_m4_v3(eff->ob->imat, tex_co); } - hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result); + hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, NULL); if (hasrgb && mode==PFIELD_TEX_RGB) { force[0] = (0.5f - result->tr) * strength; @@ -780,15 +780,15 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP strength/=nabla; tex_co[0] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, NULL); tex_co[0] -= nabla; tex_co[1] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, NULL); tex_co[1] -= nabla; tex_co[2] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, NULL); if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */ /* generate intensity if texture only has rgb value */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 5124406b641..90158f8cc70 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2811,6 +2811,28 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ return ibuf; } +static void image_get_fame_and_index(Image *ima, ImageUser *iuser, int *frame_r, int *index_r) +{ + int frame = 0, index = 0; + + /* see if we already have an appropriate ibuf, with image source and type */ + if (ima->source == IMA_SRC_MOVIE) { + frame = iuser ? iuser->framenr : ima->lastframe; + } + else if (ima->source == IMA_SRC_SEQUENCE) { + if (ima->type == IMA_TYPE_IMAGE) { + frame = iuser ? iuser->framenr : ima->lastframe; + } + else if (ima->type == IMA_TYPE_MULTILAYER) { + frame = iuser ? iuser->framenr : ima->lastframe; + index = iuser ? iuser->multi_index : IMA_NO_INDEX; + } + } + + *frame_r = frame; + *index_r = index; +} + static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame_r, int *index_r) { ImBuf *ibuf = NULL; @@ -3037,6 +3059,119 @@ int BKE_image_has_ibuf(Image *ima, ImageUser *iuser) return ibuf != NULL; } +/* ******** Pool for image buffers ******** */ + +typedef struct ImagePoolEntry { + struct ImagePoolEntry *next, *prev; + Image *image; + ImBuf *ibuf; + int index; + int frame; +} ImagePoolEntry; + +typedef struct ImagePool { + ListBase image_buffers; +} ImagePool; + +ImagePool *BKE_image_pool_new(void) +{ + ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool"); + + return pool; +} + +void BKE_image_pool_free(ImagePool *pool) +{ + ImagePoolEntry *entry, *next_entry; + + /* use single lock to dereference all the image buffers */ + BLI_spin_lock(&image_spin); + + for (entry = pool->image_buffers.first; entry; entry = next_entry) { + next_entry = entry->next; + + if (entry->ibuf) + IMB_freeImBuf(entry->ibuf); + + MEM_freeN(entry); + } + + BLI_spin_unlock(&image_spin); + + MEM_freeN(pool); +} + +BLI_INLINE ImBuf *image_pool_find_entry(ImagePool *pool, Image *image, int frame, int index, int *found) +{ + ImagePoolEntry *entry; + + *found = FALSE; + + for (entry = pool->image_buffers.first; entry; entry = entry->next) { + if (entry->image == image && entry->frame == frame && entry->index == index) { + *found = TRUE; + return entry->ibuf; + } + } + + return NULL; +} + +ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool) +{ + ImBuf *ibuf; + int index, frame, found; + + if (pool == NULL) { + /* pool could be NULL, in this case use general acquire function */ + return BKE_image_acquire_ibuf(ima, iuser, NULL); + } + + image_get_fame_and_index(ima, iuser, &frame, &index); + + ibuf = image_pool_find_entry(pool, ima, frame, index, &found); + if (found) + return ibuf; + + BLI_spin_lock(&image_spin); + + ibuf = image_pool_find_entry(pool, ima, frame, index, &found); + + /* will also create entry even in cases image buffer failed to load, + * prevents trying to load the same buggy file multiple times + */ + if (!found) { + ImagePoolEntry *entry; + + ibuf = image_acquire_ibuf(ima, iuser, NULL); + + if (ibuf) + IMB_refImBuf(ibuf); + + entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry"); + entry->image = ima; + entry->frame = frame; + entry->index = index; + entry->ibuf = ibuf; + + BLI_addtail(&pool->image_buffers, entry); + } + + BLI_spin_unlock(&image_spin); + + return ibuf; +} + +void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool) +{ + /* if pool wasn't actually used, use general release stuff, + * for pools image buffers will be dereferenced on pool free + */ + if (pool == NULL) { + BKE_image_release_ibuf(ima, ibuf, NULL); + } +} + int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range) { const int len = (iuser->fie_ima * iuser->frames) / 2; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index b2371da0c3c..05031ddc142 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -83,6 +83,7 @@ #include "BKE_fcurve.h" #include "BKE_group.h" #include "BKE_icons.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_lamp.h" #include "BKE_lattice.h" @@ -308,6 +309,9 @@ void free_sculptsession(Object *ob) if (ss->texcache) MEM_freeN(ss->texcache); + if (ss->tex_pool) + BKE_image_pool_free(ss->tex_pool); + if (ss->layer_co) MEM_freeN(ss->layer_co); diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 2563fc268b1..be36e30808d 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1060,7 +1060,7 @@ static void get_texture_value(Tex *texture, float tex_co[3], TexResult *texres) int result_type; /* no node textures for now */ - result_type = multitex_ext_safe(texture, tex_co, texres); + result_type = multitex_ext_safe(texture, tex_co, texres, NULL); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, since this is in the context of modifiers don't use perceptual color conversion. -- cgit v1.2.3 From 88dd983f3cde0ee0cd91b3a9d12430ceff17d842 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 Jan 2013 09:54:33 +0000 Subject: fix regression in own recent commit, vertex flags were left uninitialized. --- source/blender/blenkernel/intern/editderivedmesh.c | 9 ++++---- source/blender/blenkernel/intern/subsurf_ccg.c | 25 ++++++++++++++++------ 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 0197cc3fa77..d41893b4335 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -1410,7 +1410,7 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) normal_float_to_short_v3(vert_r->no, eve->no); vert_r->flag = BM_vert_flag_to_mflag(eve); - if (cd_vert_bweight_offset != -1) vert_r->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); + vert_r->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0; vert_r++; } @@ -1421,7 +1421,7 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) normal_float_to_short_v3(vert_r->no, eve->no); vert_r->flag = BM_vert_flag_to_mflag(eve); - if (cd_vert_bweight_offset != -1) vert_r->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); + vert_r->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0; vert_r++; } @@ -1445,8 +1445,8 @@ static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) edge_r->flag = BM_edge_flag_to_mflag(eed); - if (cd_edge_crease_offset != -1) edge_r->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset); - if (cd_edge_bweight_offset != -1) edge_r->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset); + edge_r->crease = (cd_edge_crease_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset) : 0; + edge_r->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0; edge_r++; } @@ -1469,6 +1469,7 @@ static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r) face_r->mat_nr = (unsigned char) ef->mat_nr; face_r->flag = BM_face_flag_to_mflag(ef); + face_r->edcode = 0; face_r->v1 = BM_elem_index_get(l[0]->v); face_r->v2 = BM_elem_index_get(l[1]->v); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 6d4313d1bc3..d665269c6ca 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1013,7 +1013,11 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) mf->flag = faceFlags[i].flag; mf->mat_nr = faceFlags[i].mat_nr; } - else mf->flag = ME_SMOOTH; + else { + mf->flag = ME_SMOOTH; + } + + mf->edcode = 0; } /* Translate GridHidden into the ME_HIDE flag for MVerts. Assumes @@ -1122,6 +1126,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x); copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); + mvert[i].flag = mvert[i].bweight = 0; } } @@ -1131,6 +1136,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y); copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); + mvert[i].flag = mvert[i].bweight = 0; } } } @@ -1150,6 +1156,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) * faces which are now zerod out, see comment in: * ccgSubSurf__calcVertNormals(), - campbell */ normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); + mvert[i].flag = mvert[i].bweight = 0; } } @@ -1160,6 +1167,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) vd = ccgSubSurf_getVertData(ss, v); copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); + mvert[i].flag = mvert[i].bweight = 0; i++; } } @@ -1174,6 +1182,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) int edgeSize = ccgSubSurf_getEdgeSize(ss); int i = 0; short *edgeFlags = ccgdm->edgeFlags; + const short ed_interior_flag = ccgdm->drawInteriorEdges ? (ME_EDGEDRAW | ME_EDGERENDER) : 0; totface = ccgSubSurf_getNumFaces(ss); for (index = 0; index < totface; index++) { @@ -1184,10 +1193,10 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) for (x = 0; x < gridSize - 1; x++) { MEdge *med = &medge[i]; - if (ccgdm->drawInteriorEdges) - med->flag = ME_EDGEDRAW | ME_EDGERENDER; med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize); med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize); + med->crease = med->bweight = 0; + med->flag = ed_interior_flag; i++; } @@ -1196,21 +1205,21 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) MEdge *med; med = &medge[i]; - if (ccgdm->drawInteriorEdges) - med->flag = ME_EDGEDRAW | ME_EDGERENDER; med->v1 = getFaceIndex(ss, f, S, x, y, edgeSize, gridSize); med->v2 = getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize); + med->crease = med->bweight = 0; + med->flag = ed_interior_flag; i++; med = &medge[i]; - if (ccgdm->drawInteriorEdges) - med->flag = ME_EDGEDRAW | ME_EDGERENDER; med->v1 = getFaceIndex(ss, f, S, y, x, edgeSize, gridSize); med->v2 = getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize); + med->crease = med->bweight = 0; + med->flag = ed_interior_flag; i++; } } @@ -1239,6 +1248,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) MEdge *med = &medge[i]; med->v1 = getEdgeIndex(ss, e, x, edgeSize); med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); + med->crease = med->bweight = 0; med->flag = flags; i++; } @@ -1278,6 +1288,7 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) edgeSize, gridSize); mf->mat_nr = mat_nr; mf->flag = flag; + mf->edcode = 0; i++; } -- cgit v1.2.3 From 838064679894f41034c1f6e78ae33a81b4f14c75 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 21 Jan 2013 11:38:15 +0000 Subject: Fix image pool crash when acquiring buffer for NULL image --- source/blender/blenkernel/intern/image.c | 36 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 90158f8cc70..c56091ead62 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2888,6 +2888,21 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame return ibuf; } +BLI_INLINE int image_quick_test(Image *ima, ImageUser *iuser) +{ + if (ima == NULL) + return FALSE; + + if (iuser) { + if (iuser->ok == 0) + return FALSE; + } + else if (ima->ok == 0) + return FALSE; + + return TRUE; +} + /* Checks optional ImageUser and verifies/creates ImBuf. * * not thread-safe, so callee should worry about thread locks @@ -2902,14 +2917,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) *lock_r = NULL; /* quick reject tests */ - if (ima == NULL) - return NULL; - - if (iuser) { - if (iuser->ok == 0) - return NULL; - } - else if (ima->ok == 0) + if (!image_quick_test(ima, iuser)) return NULL; ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); @@ -3033,14 +3041,7 @@ int BKE_image_has_ibuf(Image *ima, ImageUser *iuser) ImBuf *ibuf; /* quick reject tests */ - if (ima == NULL) - return FALSE; - - if (iuser) { - if (iuser->ok == 0) - return FALSE; - } - else if (ima->ok == 0) + if (!image_quick_test(ima, iuser)) return FALSE; ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); @@ -3122,6 +3123,9 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool ImBuf *ibuf; int index, frame, found; + if (!image_quick_test(ima, iuser)) + return NULL; + if (pool == NULL) { /* pool could be NULL, in this case use general acquire function */ return BKE_image_acquire_ibuf(ima, iuser, NULL); -- cgit v1.2.3 From caac27dcbc4fb652fbb417b4b312493b0ef0eea0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 Jan 2013 15:41:00 +0000 Subject: mesh-cache deform modifier, supports MDD and PC2 formats. see wiki docs: http://wiki.blender.org/index.php/Doc:2.6/Manual/Modifiers/Deform/Mesh_Cache --- source/blender/blenkernel/intern/bpath.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index bb610ede9f7..b0021050e8f 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -459,6 +459,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int OceanModifierData *omd = (OceanModifierData *) md; rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data); } + else if (md->type == eModifierType_MeshCache) { + MeshCacheModifierData *mcmd = (MeshCacheModifierData *) md; + rewrite_path_fixed(mcmd->filepath, visit_cb, absbase, bpath_user_data); + } } if (ob->soft) { -- cgit v1.2.3 From d1a211188b588456b8ca76effb11e639442e8c10 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 22 Jan 2013 04:24:01 +0000 Subject: property change reporting now uses the context again, rather then checking a dir() on context, hard-code common paths. eg: bpy.context.scene.render.resolution_x = 1921 bpy.context.object.data.use_auto_smooth = True bpy.context.object.active_material.diffuse_intensity = 1 bpy.context.scene.world.exposure = 0.1 also remove duplicate GS() defines --- source/blender/blenkernel/intern/key.c | 13 ------------- source/blender/blenkernel/intern/library.c | 3 --- source/blender/blenkernel/intern/material.c | 13 ------------- 3 files changed, 29 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index ccc57a24540..803b1e68915 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -108,19 +108,6 @@ void BKE_key_free_nolib(Key *key) } -/* GS reads the memory pointed at in a specific ordering. There are, - * however two definitions for it. I have jotted them down here, both, - * but I think the first one is actually used. The thing is that - * big-endian systems might read this the wrong way round. OTOH, we - * constructed the IDs that are read out with this macro explicitly as - * well. I expect we'll sort it out soon... */ - -/* from blendef: */ -#define GS(a) (*((short *)(a))) - -/* from misc_util: flip the bytes from x */ -/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ - Key *BKE_key_add(ID *id) /* common function */ { Key *key; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 42f658afa93..817068ae41e 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -123,9 +123,6 @@ * only use this definition, makes little and big endian systems * work fine, in conjunction with MAKE_ID */ -/* from blendef: */ -#define GS(a) (*((short *)(a))) - /* ************* general ************************ */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index bf64bd3d093..f19dc93198d 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -681,19 +681,6 @@ Material *give_node_material(Material *ma) return NULL; } -/* GS reads the memory pointed at in a specific ordering. There are, - * however two definitions for it. I have jotted them down here, both, - * but I think the first one is actually used. The thing is that - * big-endian systems might read this the wrong way round. OTOH, we - * constructed the IDs that are read out with this macro explicitly as - * well. I expect we'll sort it out soon... */ - -/* from blendef: */ -#define GS(a) (*((short *)(a))) - -/* from misc_util: flip the bytes from x */ -/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ - void resize_object_material(Object *ob, const short totcol) { Material **newmatar; -- cgit v1.2.3 From 95a13a2c02caec332d4d5b521441f1c49ddb07a3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 22 Jan 2013 08:05:00 +0000 Subject: Fix projection texture painting crash It was caused by own mistake by not noticing externtex is used not only by render engine. Now this function uses pool passed as argument rather than using R.pool. --- source/blender/blenkernel/BKE_brush.h | 3 ++- source/blender/blenkernel/intern/brush.c | 8 ++++---- source/blender/blenkernel/intern/particle.c | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index b19a9c4d4eb..91f0525d4f3 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -36,6 +36,7 @@ struct ID; struct Brush; struct ImBuf; +struct ImagePool; struct Scene; struct wmOperator; // enum CurveMappingPreset; @@ -67,7 +68,7 @@ float BKE_brush_curve_strength_clamp(struct Brush *br, float p, const float len) float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ /* sampling */ -void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float sampleco[3], float rgba[4], const int thread); +void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float sampleco[3], float rgba[4], const int thread, struct ImagePool *pool); void BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread); void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf, int use_color_correction); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 6d655f8b495..792a6058872 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -472,7 +472,7 @@ int BKE_brush_clone_image_delete(Brush *brush) } /* Brush Sampling for 3d brushes. Currently used for texture painting only, but should be generalized */ -void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco[3], float rgba[4], const int thread) +void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco[3], float rgba[4], const int thread, struct ImagePool *pool) { MTex *mtex = &brush->mtex; @@ -482,7 +482,7 @@ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco const int radius = BKE_brush_size_get(scene, brush); if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { - hasrgb = externtex(mtex, sampleco, &tin, &tr, &tg, &tb, &ta, thread); + hasrgb = externtex(mtex, sampleco, &tin, &tr, &tg, &tb, &ta, thread, pool); } else { float co[3]; @@ -491,7 +491,7 @@ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco co[1] = sampleco[1] / radius; co[2] = 0.0f; - hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); + hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread, pool); } if (hasrgb) { @@ -526,7 +526,7 @@ void BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2] co[1] = xy[1] / radius; co[2] = 0.0f; - hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); + hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread, NULL); if (hasrgb) { rgba[0] = tr; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index b2851962b49..71854a93f4d 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3849,7 +3849,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti break; } - externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0); + externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL); if ((event & mtex->mapto) & PAMAP_ROUGH) ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend(def, ptex->rough1, value, mtex->roughfac, blend); @@ -3920,7 +3920,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex break; } - externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0); + externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL); if ((event & mtex->mapto) & PAMAP_TIME) { /* the first time has to set the base value for time regardless of blend mode */ -- cgit v1.2.3 From e11d22a6b751c750c40226cb027e7805adb7d4e4 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 22 Jan 2013 11:18:41 +0000 Subject: Matcap support in 3D Viewport. Full log is here: http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability#Matcap_in_3D_viewport Implementation notes: - Matcaps are an extension of Solid draw mode, and don't show in other drawmodes. (It's mostly intended to aid modeling/sculpt) - By design, Matcaps are a UI feature, and only stored locally for the UI itself, and won't affect rendering or materials. - Currently a set of 16 (GPL licensed) Matcaps have been compiled into Blender. It doesn't take memory or cpu time, until you use it. - Brush Icons and Matcaps use same code now, and only get generated/allocated on actually using it (instead of on startup). - The current set might get new or different images still, based on user feedback. - Matcap images are 512x512 pixels, so each image takes 1 Mb memory. Unused matcaps get freed immediately. The Matcap icon previews (128x128 pixels) stay in memory. - Loading own matcap image files will be added later. That needs design and code work to get it stable and memory-friendly. - The GLSL code uses the ID PreviewImage for matcaps. I tested it using the existing Material previews, which has its limits... especially for textured previews the normal-mapped matcap won't look good. --- source/blender/blenkernel/intern/icons.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index d8c3e260399..9c265814b8f 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -51,6 +51,8 @@ #include "BLO_sys_types.h" // for intptr_t support +#include "GPU_extensions.h" + /* GLOBALS */ static GHash *gIcons = NULL; @@ -138,7 +140,10 @@ void BKE_previewimg_freefunc(void *link) MEM_freeN(prv->rect[i]); prv->rect[i] = NULL; } + if (prv->gputexture[i]) + GPU_texture_free(prv->gputexture[i]); } + MEM_freeN(prv); } } @@ -165,6 +170,7 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv) else { prv_img->rect[i] = NULL; } + prv_img->gputexture[i] = NULL; } } return prv_img; -- cgit v1.2.3 From e7ed4605eb9770ec31b9bd33ed386a1f9bcfb1c3 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 22 Jan 2013 15:30:29 +0000 Subject: Bugfix #33945 OSX: in HiDPI mode, the brush circle doubled on every use. Was caused by new code storing and setting brush sizes. --- source/blender/blenkernel/intern/brush.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 792a6058872..70eaa00b82e 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -662,7 +662,9 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf void BKE_brush_size_set(Scene *scene, Brush *brush, int size) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; - + + size = (int)((float)size / U.pixelsize); + if (ups->flag & UNIFIED_PAINT_SIZE) ups->size = size; else -- cgit v1.2.3 From 78f5d531a4ccb1fd8bc4dae21b08423302b6039c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 22 Jan 2013 16:06:09 +0000 Subject: Fix/workaround for GLSL textured and matcap modes for dyntopo Currently used special checks in DM draw code, perhaps better would be simply to flush changes from PBVH to DM. Anyway, now things seems to be working OK, will check on better solution from code point of view later. --- source/blender/blenkernel/intern/cdderivedmesh.c | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 662cebd7204..66b457ec502 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1111,6 +1111,19 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, index_mp_to_orig = NULL; } + /* TODO: same as for solid draw, not entirely correct, but works fine for now, + * will skip using textures (dyntopo currently destroys UV anyway) and + * works fine for matcap + */ + if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { + if (dm->numTessFaceData) { + setMaterial(1, &gattribs); + BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, FALSE); + } + + return; + } + cdDM_update_normals_from_pbvh(dm); matnr = -1; @@ -1412,6 +1425,19 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, index_mp_to_orig = NULL; } + /* TODO: same as for solid draw, not entirely correct, but works fine for now, + * will skip using textures (dyntopo currently destroys UV anyway) and + * works fine for matcap + */ + if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { + if (dm->numTessFaceData) { + setMaterial(userData, 1, NULL); + BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, FALSE); + } + + return; + } + cdDM_update_normals_from_pbvh(dm); matnr = -1; -- cgit v1.2.3 From 8b8d4ba7effcf73d72e224d2934b6ad0f3a5ee74 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Tue, 22 Jan 2013 20:47:03 +0000 Subject: sim: Remove "continue physics" code This was left over from 2.4x days and is not used anymore. Now simulations are always interactive. --- source/blender/blenkernel/BKE_pointcache.h | 4 --- source/blender/blenkernel/intern/cloth.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 2 +- source/blender/blenkernel/intern/pointcache.c | 33 ++-------------------- source/blender/blenkernel/intern/softbody.c | 12 -------- 5 files changed, 4 insertions(+), 49 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 77b35e1a25c..7203400b267 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -294,10 +294,6 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra); /* Main cache writing call. */ int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra); -/****************** Continue physics ***************/ -void BKE_ptcache_set_continue_physics(struct Main *bmain, struct Scene *scene, int enable); -int BKE_ptcache_get_continue_physics(void); - /******************* Allocate & free ***************/ struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches); void BKE_ptcache_free_mem(struct ListBase *mem_cache); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index fdd7dc94979..c1293542963 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -483,7 +483,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; /* handle continuous simulation with the play button */ - if (BKE_ptcache_get_continue_physics() || ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe))) { + if ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe)) { BKE_ptcache_invalidate(cache); /* do simulation */ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 5eac86a7e77..fda5f6f2ecb 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4500,7 +4500,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) int startframe = 0, endframe = 100, oldtotpart = 0; /* cache shouldn't be used for hair or "continue physics" */ - if (part->type != PART_HAIR && BKE_ptcache_get_continue_physics() == 0) { + if (part->type != PART_HAIR) { psys_clear_temp_pointcache(psys); /* set suitable cache range automatically */ diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 2f21e588b85..ac4b3099ba0 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2536,7 +2536,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) after= 0; if (mode == PTCACHE_RESET_DEPSGRAPH) { - if (!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { + if (!(cache->flag & PTCACHE_BAKED)) { after= 1; } @@ -2544,12 +2544,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) cache->flag |= PTCACHE_OUTDATED; } else if (mode == PTCACHE_RESET_BAKED) { - if (!BKE_ptcache_get_continue_physics()) { - reset= 1; - clear= 1; - } - else - cache->flag |= PTCACHE_OUTDATED; + cache->flag |= PTCACHE_OUTDATED; } else if (mode == PTCACHE_RESET_OUTDATED) { reset = 1; @@ -2695,30 +2690,6 @@ void BKE_ptcache_remove(void) } } -/* Continuous Interaction */ - -static int CONTINUE_PHYSICS = 0; - -void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable) -{ - Object *ob; - - if (CONTINUE_PHYSICS != enable) { - CONTINUE_PHYSICS = enable; - - if (CONTINUE_PHYSICS == 0) { - for (ob=bmain->object.first; ob; ob=ob->id.next) - if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - } - } -} - -int BKE_ptcache_get_continue_physics(void) -{ - return CONTINUE_PHYSICS; -} - /* Point Cache handling */ PointCache *BKE_ptcache_add(ListBase *ptcaches) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 79356d39235..e2c6df5e528 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -4108,18 +4108,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i softbody_reset(ob, sb, vertexCos, numVerts); } - /* continue physics special case */ - if (BKE_ptcache_get_continue_physics()) { - BKE_ptcache_invalidate(cache); - /* do simulation */ - dtime = timescale; - softbody_update_positions(ob, sb, vertexCos, numVerts); - softbody_step(scene, ob, sb, dtime); - softbody_to_object(ob, vertexCos, numVerts, 0); - sb->last_frame = framenr; - return; - } - /* still no points? go away */ if (sb->totpoint==0) { return; -- cgit v1.2.3 From 27601aaf017263bf356dce37a4b90a764a819ee7 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 23 Jan 2013 05:56:22 +0000 Subject: rigidbody: Add DNA/RNA/BKE infrastructure for the rigid body sim This is just the basic structure, the simulation isn't hooked up yet. Scenes get a pointer to a rigid body world that holds rigid body objects. Objects get a pointer to a rigdid body object. Both rigid body world and objects aren't used directly in the simulation and only hold information to create the actual physics objects. Physics objects are created when rigid body objects are validated. In order to keep blender and bullet objects in sync care has to be taken to either call appropriate set functions or flag objects for validation. Part of GSoC 2010 and 2012. Authors: Joshua Leung (aligorith), Sergej Reich (sergof) --- source/blender/blenkernel/BKE_rigidbody.h | 94 ++++ source/blender/blenkernel/BKE_scene.h | 2 + source/blender/blenkernel/CMakeLists.txt | 3 + source/blender/blenkernel/SConscript | 1 + source/blender/blenkernel/intern/depsgraph.c | 11 +- source/blender/blenkernel/intern/object.c | 3 + source/blender/blenkernel/intern/rigidbody.c | 718 +++++++++++++++++++++++++++ source/blender/blenkernel/intern/scene.c | 20 + 8 files changed, 848 insertions(+), 4 deletions(-) create mode 100644 source/blender/blenkernel/BKE_rigidbody.h create mode 100644 source/blender/blenkernel/intern/rigidbody.c (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h new file mode 100644 index 00000000000..26a003841c4 --- /dev/null +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -0,0 +1,94 @@ +/* + * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BKE_rigidbody.h + * \ingroup blenkernel + * \brief API for Blender-side Rigid Body stuff + */ + + +#ifndef __BKE_RIGIDBODY_H__ +#define __BKE_RIGIDBODY_H__ + +struct RigidBodyWorld; +struct RigidBodyOb; + +struct Scene; +struct Object; +struct Group; + +/* -------------- */ +/* Memory Management */ + +void BKE_rigidbody_free_world(struct RigidBodyWorld *rbw); +void BKE_rigidbody_free_object(struct Object *ob); +void BKE_rigidbody_free_constraint(struct Object *ob); + +/* ...... */ + +struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob); +struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob); + +/* -------------- */ +/* Setup */ + +/* create Blender-side settings data - physics objects not initialised yet */ +struct RigidBodyWorld *BKE_rigidbody_create_world(struct Scene *scene); +struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Object *ob, short type); +struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type); + +/* 'validate' (i.e. make new or replace old) Physics-Engine objects */ +void BKE_rigidbody_validate_sim_world(struct Scene *scene, struct RigidBodyWorld *rbw, short rebuild); +void BKE_rigidbody_validate_sim_object(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild); +void BKE_rigidbody_validate_sim_shape(struct Object *ob, short rebuild); +void BKE_rigidbody_validate_sim_constraint(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild); + +/* -------------- */ +/* Utilities */ + +struct RigidBodyWorld *BKE_rigidbody_get_world(struct Scene *scene); +void BKE_rigidbody_remove_object(struct Scene *scene, struct Object *ob); +void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob); + +/* -------------- */ +/* Utility Macros */ + +/* get mass of Rigid Body Object to supply to RigidBody simulators */ +#define RBO_GET_MASS(rbo) \ + ((rbo && ((rbo->type == RBO_TYPE_PASSIVE) || (rbo->flag & RBO_FLAG_KINEMATIC) || (rbo->flag & RBO_FLAG_DISABLED))) ? (0.0f) : (rbo->mass)) +/* get collision margin for Rigid Body Object, triangle mesh and cone shapes cannot embed margin, convex hull always uses custom margin */ +#define RBO_GET_MARGIN(rbo) \ + ((rbo->flag & RBO_FLAG_USE_MARGIN || rbo->shape == RB_SHAPE_CONVEXH || rbo->shape == RB_SHAPE_TRIMESH || rbo->shape == RB_SHAPE_CONE) ? (rbo->margin) : (0.04f)) + +/* -------------- */ +/* Simulation */ + +void BKE_rigidbody_sync_transforms(struct Scene *scene, struct Object *ob, float ctime); +void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw); +void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime); + +#endif /* __BKE_RIGIDBODY_H__ */ diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 6447b2a8dee..2ac32a3f651 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -72,6 +72,7 @@ struct Scene *BKE_scene_add(struct Main *bmain, const char *name); /* base functions */ struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob); struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob); +void BKE_scene_base_remove(struct Scene *sce, struct Base *base); void BKE_scene_base_deselect_all(struct Scene *sce); void BKE_scene_base_select(struct Scene *sce, struct Base *selbase); int BKE_scene_base_iter_next(struct Scene **scene, int val, struct Base **base, struct Object **ob); @@ -115,6 +116,7 @@ int BKE_scene_use_new_shading_nodes(struct Scene *scene); void BKE_scene_disable_color_management(struct Scene *scene); int BKE_scene_check_color_management_enabled(const struct Scene *scene); +int BKE_scene_check_rigidbody_active(const struct Scene *scene); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index aca06a1abcf..846ed8a9bb4 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -37,6 +37,7 @@ set(INC ../modifiers ../nodes ../render/extern/include + ../rigidbody ../../../intern/guardedalloc ../../../intern/iksolver/extern ../../../intern/memutil @@ -128,6 +129,7 @@ set(SRC intern/pointcache.c intern/property.c intern/report.c + intern/rigidbody.c intern/sca.c intern/scene.c intern/screen.c @@ -219,6 +221,7 @@ set(SRC BKE_pointcache.h BKE_property.h BKE_report.h + BKE_rigidbody.h BKE_sca.h BKE_scene.h BKE_screen.h diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 0286172e639..b146235d63c 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -41,6 +41,7 @@ incs += ' ../render/extern/include ../makesrna' incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers' incs += ' #/intern/iksolver/extern ../blenloader' incs += ' #/extern/bullet2/src' +incs += ' ../rigidbody' incs += ' #/intern/opennl/extern #/intern/bsp/extern' incs += ' ../gpu #/extern/glew/include' incs += ' ../bmesh' diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 42389564ec0..78d7bfa5bc5 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2290,7 +2290,7 @@ static short animdata_use_time(AnimData *adt) return 0; } -static void dag_object_time_update_flags(Object *ob) +static void dag_object_time_update_flags(Scene *scene, Object *ob) { if (ob->constraints.first) { bConstraint *con; @@ -2350,6 +2350,9 @@ static void dag_object_time_update_flags(Object *ob) if (object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; if ((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; + if (ob->rigidbody_object && BKE_scene_check_rigidbody_active(scene)) + ob->recalc |= OB_RECALC_OB; + { AnimData *adt = BKE_animdata_from_id((ID *)ob->data); Mesh *me; @@ -2434,7 +2437,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s if (do_time) { /* now if DagNode were part of base, the node->lay could be checked... */ /* we do all now, since the scene_flush checks layers and clears recalc flags even */ - dag_object_time_update_flags(ob); + dag_object_time_update_flags(scene, ob); } /* handled in next loop */ @@ -2447,7 +2450,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s for (group = bmain->group.first; group; group = group->id.next) { if (group->id.flag & LIB_DOIT) { for (go = group->gobject.first; go; go = go->next) { - dag_object_time_update_flags(go->ob); + dag_object_time_update_flags(scene, go->ob); } } } @@ -2466,7 +2469,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s /* hrmf... an exception to look at once, for invisible camera object we do it over */ if (scene->camera) - dag_object_time_update_flags(scene->camera); + dag_object_time_update_flags(scene, scene->camera); } /* and store the info in groupobject */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 05031ddc142..2738c546ce1 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -98,6 +98,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_property.h" +#include "BKE_rigidbody.h" #include "BKE_sca.h" #include "BKE_scene.h" #include "BKE_sequencer.h" @@ -386,6 +387,7 @@ void BKE_object_free(Object *ob) BKE_free_constraints(&ob->constraints); free_partdeflect(ob->pd); + BKE_rigidbody_free_object(ob); if (ob->soft) sbFree(ob->soft); if (ob->bsoft) bsbFree(ob->bsoft); @@ -1288,6 +1290,7 @@ static Object *object_copy_do(Object *ob, int copy_caches) obn->bsoft = copy_bulletsoftbody(ob->bsoft); BKE_object_copy_particlesystems(obn, ob); + obn->rigidbody_object = BKE_rigidbody_copy_object(ob); obn->derivedDeform = NULL; obn->derivedFinal = NULL; diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c new file mode 100644 index 00000000000..e6f6c9a9a98 --- /dev/null +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -0,0 +1,718 @@ +/* + * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rigidbody.c + * \ingroup blenkernel + * \brief Blender-side interface and methods for dealing with Rigid Body simulations + */ + +#include +#include +#include +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "RBI_api.h" + +#include "DNA_anim_types.h" +#include "DNA_group_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BKE_animsys.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_effect.h" +#include "BKE_group.h" +#include "BKE_object.h" +#include "BKE_mesh.h" +#include "BKE_pointcache.h" +#include "BKE_rigidbody.h" +#include "BKE_global.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" + +/* ************************************** */ +/* Memory Management */ + +/* Freeing Methods --------------------- */ + +/* Free rigidbody world */ +void BKE_rigidbody_free_world(RigidBodyWorld *rbw) +{ + GroupObject *go; + /* sanity check */ + if (!rbw) + return; + + if (rbw->physics_world) { + /* free physics references, we assume that all physics objects in will have been added to the world */ + if (rbw->group) { + for (go = rbw->group->gobject.first; go; go = go->next) { + if (go->ob && go->ob->rigidbody_object) { + RigidBodyOb *rbo = go->ob->rigidbody_object; + + if (rbo->physics_object) + RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + } + } + } + /* free dynamics world */ + RB_dworld_delete(rbw->physics_world); + } + if (rbw->objects) + free(rbw->objects); + + /* free rigidbody world itself */ + MEM_freeN(rbw); +} + +/* Free RigidBody settings and sim instances */ +void BKE_rigidbody_free_object(Object *ob) +{ + RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL; + + /* sanity check */ + if (rbo == NULL) + return; + + /* free physics references */ + if (rbo->physics_object) { + RB_body_delete(rbo->physics_object); + rbo->physics_object = NULL; + } + + if (rbo->physics_shape) { + RB_shape_delete(rbo->physics_shape); + rbo->physics_shape = NULL; + } + + /* free data itself */ + MEM_freeN(rbo); + ob->rigidbody_object = NULL; +} + +/* Copying Methods --------------------- */ + +/* These just copy the data, clearing out references to physics objects. + * Anything that uses them MUST verify that the copied object will + * be added to relevant groups later... + */ + +RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) +{ + RigidBodyOb *rboN = NULL; + + if (ob->rigidbody_object) { + /* just duplicate the whole struct first (to catch all the settings) */ + rboN = MEM_dupallocN(ob->rigidbody_object); + + /* tag object as needing to be verified */ + rboN->flag |= RBO_FLAG_NEEDS_VALIDATE; + + /* clear out all the fields which need to be revalidated later */ + rboN->physics_object = NULL; + rboN->physics_shape = NULL; + } + + /* return new copy of settings */ + return rboN; +} + +/* ************************************** */ +/* Setup Utilities - Validate Sim Instances */ + +/* create collision shape of mesh - convex hull */ +static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob, float margin, bool *can_embed) +{ + rbCollisionShape *shape = NULL; + Mesh *me = NULL; + + if (ob->type == OB_MESH && ob->data) { + me = ob->data; + } + else { + printf("ERROR: cannot make Convex Hull collision shape for non-Mesh object\n"); + } + + if (me && me->totvert) { + shape = RB_shape_new_convex_hull((float *)me->mvert, sizeof(MVert), me->totvert, margin, can_embed); + } + else { + printf("ERROR: no vertices to define Convex Hull collision shape with\n"); + } + + return shape; +} + +/* create collision shape of mesh - triangulated mesh + * returns NULL if creation fails. + */ +static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) +{ + rbCollisionShape *shape = NULL; + + if (ob->type == OB_MESH) { + DerivedMesh *dm = CDDM_from_mesh(ob->data, ob); + + MVert *mvert; + MFace *mface; + int totvert; + int totface; + + /* ensure mesh validity, then grab data */ + DM_ensure_tessface(dm); + + mvert = (dm) ? dm->getVertArray(dm) : NULL; + totvert = (dm) ? dm->getNumVerts(dm) : 0; + mface = (dm) ? dm->getTessFaceArray(dm) : NULL; + totface = (dm) ? dm->getNumTessFaces(dm) : 0; + + /* sanity checking - potential case when no data will be present */ + if ((totvert == 0) || (totface == 0)) { + printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2); + } + else { + rbMeshData *mdata; + int i; + + /* init mesh data for collision shape */ + mdata = RB_trimesh_data_new(); + + /* loop over all faces, adding them as triangles to the collision shape + * (so for some faces, more than triangle will get added) + */ + for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) { + /* add first triangle - verts 1,2,3 */ + { + MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert); + MVert *vb = (IN_RANGE(mface->v2, 0, totvert)) ? (mvert + mface->v2) : (mvert); + MVert *vc = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert); + + RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co); + } + + /* add second triangle if needed - verts 1,3,4 */ + if (mface->v4) { + MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert); + MVert *vb = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert); + MVert *vc = (IN_RANGE(mface->v4, 0, totvert)) ? (mvert + mface->v4) : (mvert); + + RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co); + } + } + + /* construct collision shape + * + * These have been chosen to get better speed/accuracy tradeoffs with regards + * to limitations of each: + * - BVH-Triangle Mesh: for passive objects only. Despite having greater + * speed/accuracy, they cannot be used for moving objects. + * - GImpact Mesh: for active objects. These are slower and less stable, + * but are more flexible for general usage. + */ + if (ob->rigidbody_object->type == RBO_TYPE_PASSIVE) { + shape = RB_shape_new_trimesh(mdata); + } + else { + shape = RB_shape_new_gimpact_mesh(mdata); + } + } + + /* cleanup temp data */ + if (dm) { + dm->release(dm); + } + } + else { + printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n"); + } + + return shape; +} + +/* Create new physics sim collision shape for object and store it, + * or remove the existing one first and replace... + */ +void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + rbCollisionShape *new_shape = NULL; + BoundBox *bb = NULL; + float size[3] = {1.0f, 1.0f, 1.0f}; + float radius = 1.0f; + float height = 1.0f; + float capsule_height; + float hull_margin = 0.0f; + bool can_embed = true; + + /* sanity check */ + if (rbo == NULL) + return; + + /* don't create a new shape if we already have one and don't want to rebuild it */ + if (rbo->physics_shape && !rebuild) + return; + + /* if automatically determining dimensions, use the Object's boundbox + * - assume that all quadrics are standing upright on local z-axis + * - assume even distribution of mass around the Object's pivot + * (i.e. Object pivot is centralised in boundbox) + */ + // XXX: all dimensions are auto-determined now... later can add stored settings for this + /* get object dimensions without scaling */ + bb = BKE_object_boundbox_get(ob); + if (bb) { + size[0] = (bb->vec[4][0] - bb->vec[0][0]); + size[1] = (bb->vec[2][1] - bb->vec[0][1]); + size[2] = (bb->vec[1][2] - bb->vec[0][2]); + } + mul_v3_fl(size, 0.5f); + + if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { + /* take radius as largest x/y dimension, and height as z-dimension */ + radius = MAX2(size[0], size[1]); + height = size[2]; + } + else if (rbo->shape == RB_SHAPE_SPHERE) { + /* take radius to the the largest dimension to try and encompass everything */ + radius = MAX3(size[0], size[1], size[2]); + } + + /* create new shape */ + switch (rbo->shape) { + case RB_SHAPE_BOX: + new_shape = RB_shape_new_box(size[0], size[1], size[2]); + break; + + case RB_SHAPE_SPHERE: + new_shape = RB_shape_new_sphere(radius); + break; + + case RB_SHAPE_CAPSULE: + capsule_height = (height - radius) * 2.0f; + new_shape = RB_shape_new_capsule(radius, (capsule_height > 0.0f) ? capsule_height : 0.0f); + break; + case RB_SHAPE_CYLINDER: + new_shape = RB_shape_new_cylinder(radius, height); + break; + case RB_SHAPE_CONE: + new_shape = RB_shape_new_cone(radius, height * 2.0f); + break; + + case RB_SHAPE_CONVEXH: + /* try to emged collision margin */ + if (!(rbo->flag & RBO_FLAG_USE_MARGIN)) + hull_margin = 0.04f; + new_shape = rigidbody_get_shape_convexhull_from_mesh(ob, hull_margin, &can_embed); + if (!(rbo->flag & RBO_FLAG_USE_MARGIN)) + rbo->margin = (can_embed) ? 0.04f : 0.0f; /* RB_TODO ideally we shouldn't directly change the margin here */ + break; + case RB_SHAPE_TRIMESH: + new_shape = rigidbody_get_shape_trimesh_from_mesh(ob); + break; + } + /* assign new collision shape if creation was successful */ + if (new_shape) { + if (rbo->physics_shape) + RB_shape_delete(rbo->physics_shape); + rbo->physics_shape = new_shape; + RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo)); + } +} + +/* --------------------- */ + +/* Create physics sim representation of object given RigidBody settings + * < rebuild: even if an instance already exists, replace it + */ +void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short rebuild) +{ + RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL; + float loc[3]; + float rot[4]; + + /* sanity checks: + * - object doesn't have RigidBody info already: then why is it here? + */ + if (rbo == NULL) + return; + + /* make sure collision shape exists */ + if (rbo->physics_shape == NULL || rebuild) + BKE_rigidbody_validate_sim_shape(ob, true); + + if (rbo->physics_object) { + if (rebuild == false) + RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + } + if (!rbo->physics_object || rebuild) { + /* remove rigid body if it already exists before creating a new one */ + if (rbo->physics_object) { + RB_body_delete(rbo->physics_object); + } + + mat4_to_loc_quat(loc, rot, ob->obmat); + + rbo->physics_object = RB_body_new(rbo->physics_shape, loc, rot); + + RB_body_set_friction(rbo->physics_object, rbo->friction); + RB_body_set_restitution(rbo->physics_object, rbo->restitution); + + RB_body_set_damping(rbo->physics_object, rbo->lin_damping, rbo->ang_damping); + RB_body_set_sleep_thresh(rbo->physics_object, rbo->lin_sleep_thresh, rbo->ang_sleep_thresh); + RB_body_set_activation_state(rbo->physics_object, rbo->flag & RBO_FLAG_USE_DEACTIVATION); + + if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_START_DEACTIVATED) + RB_body_deactivate(rbo->physics_object); + + + RB_body_set_linear_factor(rbo->physics_object, + (ob->protectflag & OB_LOCK_LOCX) == 0, + (ob->protectflag & OB_LOCK_LOCY) == 0, + (ob->protectflag & OB_LOCK_LOCZ) == 0); + RB_body_set_angular_factor(rbo->physics_object, + (ob->protectflag & OB_LOCK_ROTX) == 0, + (ob->protectflag & OB_LOCK_ROTY) == 0, + (ob->protectflag & OB_LOCK_ROTZ) == 0); + + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); + } + + if (rbw && rbw->physics_world) + RB_dworld_add_body(rbw->physics_world, rbo->physics_object, rbo->col_groups); +} + +/* --------------------- */ + +/* Create physics sim world given RigidBody world settings */ +// NOTE: this does NOT update object references that the scene uses, in case those aren't ready yet! +void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild) +{ + /* sanity checks */ + if (rbw == NULL) + return; + + /* create new sim world */ + if (rebuild || rbw->physics_world == NULL) { + if (rbw->physics_world) + RB_dworld_delete(rbw->physics_world); + rbw->physics_world = RB_dworld_new(scene->physics_settings.gravity); + } + + RB_dworld_set_solver_iterations(rbw->physics_world, rbw->num_solver_iterations); + RB_dworld_set_split_impulse(rbw->physics_world, rbw->flag & RBW_FLAG_USE_SPLIT_IMPULSE); +} + +/* ************************************** */ +/* Setup Utilities - Create Settings Blocks */ + +/* Set up RigidBody world */ +RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) +{ + /* try to get whatever RigidBody world that might be representing this already */ + RigidBodyWorld *rbw; + + /* sanity checks + * - there must be a valid scene to add world to + * - there mustn't be a sim world using this group already + */ + if (scene == NULL) + return NULL; + + /* create a new sim world */ + rbw = MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld"); + + /* set default settings */ + rbw->ltime = PSFRA; + + rbw->time_scale = 1.0f; + + rbw->steps_per_second = 60; /* Bullet default (60 Hz) */ + rbw->num_solver_iterations = 10; /* 10 is bullet default */ + + /* return this sim world */ + return rbw; +} + +/* Add rigid body settings to the specified object */ +RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) +{ + RigidBodyOb *rbo; + RigidBodyWorld *rbw = scene->rigidbody_world; + + /* sanity checks + * - rigidbody world must exist + * - object must exist + * - cannot add rigid body if it already exists + */ + if (ob == NULL || (ob->rigidbody_object != NULL)) + return NULL; + + /* create new settings data, and link it up */ + rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb"); + + /* set default settings */ + rbo->type = type; + + rbo->mass = 1.0f; + + rbo->friction = 0.5f; /* best when non-zero. 0.5 is Bullet default */ + rbo->restitution = 0.0f; /* best when zero. 0.0 is Bullet default */ + + rbo->margin = 0.04f; /* 0.04 (in meters) is Bullet default */ + + rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */ + rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */ + + rbo->lin_damping = 0.04f; /* 0.04 is game engine default */ + rbo->ang_damping = 0.1f; /* 0.1 is game engine default */ + + rbo->col_groups = 1; + + /* use triangle meshes for passive objects + * use convex hulls for active objects since dynamic triangle meshes are very unstable + */ + if (type == RBO_TYPE_ACTIVE) + rbo->shape = RB_SHAPE_CONVEXH; + else + rbo->shape = RB_SHAPE_TRIMESH; + + /* set initial transform */ + mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat); + + /* flag cache as outdated */ + BKE_rigidbody_cache_reset(rbw); + + /* return this object */ + return rbo; +} + +/* ************************************** */ +/* Utilities API */ + +/* Get RigidBody world for the given scene, creating one if needed + * < scene: Scene to find active Rigid Body world for + */ +RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) +{ + /* sanity check */ + if (scene == NULL) + return NULL; + + return scene->rigidbody_world; +} + +void BKE_rigidbody_remove_object(Scene *scene, Object *ob) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + RigidBodyOb *rbo = ob->rigidbody_object; + GroupObject *go; + int i; + + if (rbw) { + /* remove from rigidbody world, free object won't do this */ + if (rbw->physics_world && rbo->physics_object) + RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + + /* remove object from array */ + if (rbw && rbw->objects) { + for (i = 0; i < rbw->numbodies; i++) { + if (rbw->objects[i] == ob) { + rbw->objects[i] = NULL; + break; + } + } + } + } + /* remove object's settings */ + BKE_rigidbody_free_object(ob); + /* flag cache as outdated */ + BKE_rigidbody_cache_reset(rbw); +} + + +/* ************************************** */ +/* Simulation Interface - Bullet */ + +/* Update object array and rigid body count so they're in sync with the rigid body group */ +static void rigidbody_update_ob_array(RigidBodyWorld *rbw) +{ + GroupObject *go; + int i, n; + + n = BLI_countlist(&rbw->group->gobject); + + if (rbw->numbodies != n) { + rbw->numbodies = n; + rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies); + } + + for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) { + Object *ob = go->ob; + rbw->objects[i] = ob; + } +} + +static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) +{ + float adj_gravity[3]; + + /* adjust gravity to take effector weights into account */ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(adj_gravity, scene->physics_settings.gravity); + } + else { + zero_v3(adj_gravity); + } + + /* update gravity, since this RNA setting is not part of RigidBody settings */ + RB_dworld_set_gravity(rbw->physics_world, adj_gravity); + + /* update object array in case there are changes */ + rigidbody_update_ob_array(rbw); +} + +static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) +{ + float loc[3]; + float rot[4]; + float scale[3]; + + /* only update if rigid body exists */ + if (rbo->physics_object == NULL) + return; + + mat4_decompose(loc, rot, scale, ob->obmat); + + /* update scale for all objects */ + RB_body_set_scale(rbo->physics_object, scale); + /* compensate for embedded convex hull collision margin */ + if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH) + RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo) * MIN3(scale[0], scale[1], scale[2])); + + /* update rigid body location and rotation for kinematic bodies */ + if (rbo->flag & RBO_FLAG_KINEMATIC) { + RB_body_activate(rbo->physics_object); + RB_body_set_loc_rot(rbo->physics_object, loc, rot); + } + /* NOTE: passive objects don't need to be updated since they don't move */ + + /* NOTE: no other settings need to be explicitly updated here, + * since RNA setters take care of the rest :) + */ +} + +/* Updates and validates world, bodies and shapes. + * < rebuild: rebuild entire simulation + */ +static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, int rebuild) +{ + GroupObject *go; + + /* update world */ + if (rebuild) + BKE_rigidbody_validate_sim_world(scene, rbw, true); + rigidbody_update_sim_world(scene, rbw); + + /* update objects */ + for (go = rbw->group->gobject.first; go; go = go->next) { + Object *ob = go->ob; + + if (ob && ob->type == OB_MESH) { + /* validate that we've got valid object set up here... */ + RigidBodyOb *rbo = ob->rigidbody_object; + /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ + BKE_object_where_is_calc(scene, ob); + + if (rbo == NULL) { + /* Since this object is included in the sim group but doesn't have + * rigid body settings (perhaps it was added manually), add! + * - assume object to be active? That is the default for newly added settings... + */ + ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, RBO_TYPE_ACTIVE); + BKE_rigidbody_validate_sim_object(rbw, ob, true); + + rbo = ob->rigidbody_object; + } + else { + /* perform simulation data updates as tagged */ + /* refresh object... */ + if (rebuild) { + /* World has been rebuilt so rebuild object */ + BKE_rigidbody_validate_sim_object(rbw, ob, true); + } + else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) { + BKE_rigidbody_validate_sim_object(rbw, ob, false); + } + /* refresh shape... */ + if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) { + /* mesh/shape data changed, so force shape refresh */ + BKE_rigidbody_validate_sim_shape(ob, true); + /* now tell RB sim about it */ + // XXX: we assume that this can only get applied for active/passive shapes that will be included as rigidbodies + RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape); + } + rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE); + } + + /* update simulation object... */ + rigidbody_update_sim_ob(scene, rbw, ob, rbo); + } + } +} + +/* Sync rigid body and object transformations */ +void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) +{ +// RB_TODO implement this +} + +void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) +{ +// RB_TODO implement this +} + +/* ------------------ */ + +/* Run RigidBody simulation for the specified physics world */ +void BKE_rigidbody_do_simulation(Scene *scene, float ctime) +{ +// RB_TODO implement this +} +/* ************************************** */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 9cf0724f82a..e48cf369d4f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -46,6 +46,7 @@ #include "DNA_group_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" @@ -72,6 +73,7 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_pointcache.h" +#include "BKE_rigidbody.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_world.h" @@ -310,6 +312,9 @@ void BKE_scene_free(Scene *sce) BKE_free_animdata((ID *)sce); BKE_keyingsets_free(&sce->keyingsets); + if (sce->rigidbody_world) + BKE_rigidbody_free_world(sce->rigidbody_world); + if (sce->r.avicodecdata) { free_avicodecdata(sce->r.avicodecdata); MEM_freeN(sce->r.avicodecdata); @@ -936,6 +941,16 @@ Base *BKE_scene_base_add(Scene *sce, Object *ob) return b; } +void BKE_scene_base_remove(Scene *sce, Base *base) +{ + /* remove rigid body object from world before removing object */ + if (base->object->rigidbody_object) + BKE_rigidbody_remove_object(sce, base->object); + + BLI_remlink(&sce->base, base); + MEM_freeN(base); +} + void BKE_scene_base_deselect_all(Scene *sce) { Base *b; @@ -1376,3 +1391,8 @@ int BKE_scene_check_color_management_enabled(const Scene *scene) { return strcmp(scene->display_settings.display_device, "None") != 0; } + +int BKE_scene_check_rigidbody_active(const Scene *scene) +{ + return scene && scene->rigidbody_world && scene->rigidbody_world->group && !(scene->rigidbody_world->flag & RBW_FLAG_MUTED); +} -- cgit v1.2.3 From fc377c17e3d4803ef4db7a72daae629a322ffde8 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 23 Jan 2013 05:56:27 +0000 Subject: rigidbody: Add force field support Force fields work with rigid bodies just like they do with other simulations. Increase min and max strength of force fields so they can influence heavy rigid bodies. TODO: Adjust force field strength based on the time step taken. Part of GSoC 2010 and 2012. Authors: Joshua Leung (aligorith), Sergej Reich (sergof) --- source/blender/blenkernel/intern/rigidbody.c | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index e6f6c9a9a98..90200fd6742 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -97,6 +97,10 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw) if (rbw->objects) free(rbw->objects); + /* free effector weights */ + if (rbw->effector_weights) + MEM_freeN(rbw->effector_weights); + /* free rigidbody world itself */ MEM_freeN(rbw); } @@ -459,6 +463,8 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) rbw = MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld"); /* set default settings */ + rbw->effector_weights = BKE_add_effector_weights(NULL); + rbw->ltime = PSFRA; rbw->time_scale = 1.0f; @@ -596,6 +602,7 @@ static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) /* adjust gravity to take effector weights into account */ if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { copy_v3_v3(adj_gravity, scene->physics_settings.gravity); + mul_v3_fl(adj_gravity, rbw->effector_weights->global_gravity * rbw->effector_weights->weight[0]); } else { zero_v3(adj_gravity); @@ -631,6 +638,43 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o RB_body_activate(rbo->physics_object); RB_body_set_loc_rot(rbo->physics_object, loc, rot); } + /* update influence of effectors - but don't do it on an effector */ + /* only dynamic bodies need effector update */ + else if (rbo->type == RBO_TYPE_ACTIVE && ((ob->pd == NULL) || (ob->pd->forcefield == PFIELD_NULL))) { + EffectorWeights *effector_weights = rbw->effector_weights; + EffectedPoint epoint; + ListBase *effectors; + + /* get effectors present in the group specified by effector_weights */ + effectors = pdInitEffectors(scene, ob, NULL, effector_weights); + if (effectors) { + float force[3] = {0.0f, 0.0f, 0.0f}; + float loc[3], vel[3]; + + /* create dummy 'point' which represents last known position of object as result of sim */ + // XXX: this can create some inaccuracies with sim position, but is probably better than using unsimulated vals? + RB_body_get_position(rbo->physics_object, loc); + RB_body_get_linear_velocity(rbo->physics_object, vel); + + pd_point_from_loc(scene, loc, vel, 0, &epoint); + + /* calculate net force of effectors, and apply to sim object + * - we use 'central force' since apply force requires a "relative position" which we don't have... + */ + pdDoEffectors(effectors, NULL, effector_weights, &epoint, force, NULL); + if (G.f & G_DEBUG) + printf("\tapplying force (%f,%f,%f) to '%s'\n", force[0], force[1], force[2], ob->id.name + 2); + /* activate object in case it is deactivated */ + if (!is_zero_v3(force)) + RB_body_activate(rbo->physics_object); + RB_body_apply_central_force(rbo->physics_object, force); + } + else if (G.f & G_DEBUG) + printf("\tno forces to apply to '%s'\n", ob->id.name + 2); + + /* cleanup */ + pdEndEffectors(&effectors); + } /* NOTE: passive objects don't need to be updated since they don't move */ /* NOTE: no other settings need to be explicitly updated here, -- cgit v1.2.3 From 089cf12435dfbc4b934a73b73ecd617b27ac678d Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 23 Jan 2013 05:56:34 +0000 Subject: rigidbody: Add point cache support Add read/write/interpolate functions. In order to get rigid body point cache id from object it's now required to pass the scene to BKE_ptcache_ids_from_object(). Rigid body cache is drawn in the orange color of the bullet logo. --- source/blender/blenkernel/BKE_pointcache.h | 3 + source/blender/blenkernel/intern/pointcache.c | 144 ++++++++++++++++++++++++++ source/blender/blenkernel/intern/rigidbody.c | 10 +- 3 files changed, 156 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 7203400b267..1cb50425c40 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -67,6 +67,7 @@ #define PTCACHE_TYPE_SMOKE_DOMAIN 3 #define PTCACHE_TYPE_SMOKE_HIGHRES 4 #define PTCACHE_TYPE_DYNAMICPAINT 5 +#define PTCACHE_TYPE_RIGIDBODY 6 /* high bits reserved for flags that need to be stored in file */ #define PTCACHE_TYPEFLAG_COMPRESS (1 << 16) @@ -91,6 +92,7 @@ struct PointCache; struct Scene; struct SmokeModifierData; struct SoftBody; +struct RigidBodyWorld; /* temp structure for read/write */ typedef struct PTCacheData { @@ -260,6 +262,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct Par void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd); void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd); void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface); +void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw); void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index ac4b3099ba0..afc552ae7f3 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -43,6 +43,7 @@ #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_particle_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" @@ -72,6 +73,8 @@ #include "BIK_api.h" +#include "RBI_api.h" + /* both in intern */ #ifdef WITH_SMOKE #include "smoke_API.h" @@ -867,6 +870,97 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v) return 1; } +/* Rigid Body functions */ +static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra)) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { + + RB_body_get_position(rbo->physics_object, rbo->pos); + RB_body_get_orientation(rbo->physics_object, rbo->orn); + + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos); + PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn); + } + } + + return 1; +} +static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { + + if (old_data) { + memcpy(rbo->pos, data, 3 * sizeof(float)); + memcpy(rbo->orn, data + 3, 4 * sizeof(float)); + } + else { + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos); + PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn); + } + } + } +} +static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + ParticleKey keys[4]; + float dfra; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { + + copy_v3_v3(keys[1].co, rbo->pos); + copy_v3_v3(keys[1].rot, rbo->orn); + + if (old_data) { + memcpy(keys[2].co, data, 3 * sizeof(float)); + memcpy(keys[2].rot, data + 3, 4 * sizeof(float)); + } + else { + BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + } + + dfra = cfra2 - cfra1; + + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); + interp_qt_qtqt(keys->rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); + + copy_v3_v3(rbo->pos, keys->co); + copy_v3_v3(rbo->orn, keys->rot); + } + } +} +static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra)) +{ + RigidBodyWorld *rbw = rb_v; + + return rbw->numbodies; +} + /* Creating ID's */ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { @@ -1072,6 +1166,42 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu pid->max_step = 1; } +void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw) +{ + + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->calldata= rbw; + pid->type= PTCACHE_TYPE_RIGIDBODY; + pid->cache= rbw->pointcache; + pid->cache_ptr= &rbw->pointcache; + pid->ptcaches= &rbw->ptcaches; + pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint; + + pid->write_point = ptcache_rigidbody_write; + pid->read_point = ptcache_rigidbody_read; + pid->interpolate_point = ptcache_rigidbody_interpolate; + + pid->write_stream = NULL; + pid->read_stream = NULL; + + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types= (1<info_types= 0; + + pid->stack_index = pid->cache->index; + + pid->default_step = 1; + pid->max_step = 1; +} + void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) { PTCacheID *pid; @@ -1133,6 +1263,12 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } } } + + if (scene && ob->rigidbody_object && scene->rigidbody_world) { + pid = MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_rigidbody(pid, ob, scene->rigidbody_world); + BLI_addtail(lb, pid); + } if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) { ListBase *lb_dupli_ob; @@ -2641,6 +2777,14 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } } + if (scene->rigidbody_world && ob->rigidbody_object) { + if (ob->rigidbody_object) + ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE; + BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world); + /* only flag as outdated, resetting should happen on start frame */ + pid.cache->flag |= PTCACHE_OUTDATED; + } + if (ob->type == OB_ARMATURE) BIK_clear_cache(ob->pose); diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 90200fd6742..17ced6fa54d 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -97,6 +97,10 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw) if (rbw->objects) free(rbw->objects); + /* free cache */ + BKE_ptcache_free_list(&(rbw->ptcaches)); + rbw->pointcache = NULL; + /* free effector weights */ if (rbw->effector_weights) MEM_freeN(rbw->effector_weights); @@ -472,6 +476,9 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) rbw->steps_per_second = 60; /* Bullet default (60 Hz) */ rbw->num_solver_iterations = 10; /* 10 is bullet default */ + rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches)); + rbw->pointcache->step = 1; + /* return this sim world */ return rbw; } @@ -749,7 +756,8 @@ void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) { -// RB_TODO implement this + if (rbw) + rbw->pointcache->flag |= PTCACHE_OUTDATED; } /* ------------------ */ -- cgit v1.2.3 From 2d8637946b047a8a9cc3fb6fe6d146b9961f92a6 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 23 Jan 2013 05:56:44 +0000 Subject: rigidbody: Add rigid body simulation Add operators to add/remove rigid body world and objects. Add UI scripts. The rigid body simulation works on scene level and overrides the position/orientation of rigid bodies when active. It does not deform meshes or generate data so there is no modifier. Usage: * Add rigid body world in the scene tab * Create a group * Add objects to the group * Assign group to the rigid body world * Play animation For convenience the rigid body tools operators in the tools panel of the 3d view will add a world, group and add objects to the group automatically so you only have to press one button to add/remove rigid bodies to the simulation. Part of GSoC 2010 and 2012. Authors: Joshua Leung (aligorith), Sergej Reich (sergof) --- source/blender/blenkernel/intern/object.c | 2 + source/blender/blenkernel/intern/rigidbody.c | 103 ++++++++++++++++++++++++++- source/blender/blenkernel/intern/scene.c | 6 ++ 3 files changed, 109 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 2738c546ce1..cf1b21e91de 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2146,6 +2146,8 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) BKE_object_to_mat4(ob, ob->obmat); } + BKE_rigidbody_sync_transforms(scene, ob, ctime); + /* solve constraints */ if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) { bConstraintOb *cob; diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 17ced6fa54d..359c46f2b0e 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -751,7 +751,35 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, int r /* Sync rigid body and object transformations */ void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) { -// RB_TODO implement this + RigidBodyWorld *rbw = scene->rigidbody_world; + RigidBodyOb *rbo = ob->rigidbody_object; + + /* keep original transform for kinematic and passive objects */ + if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE) + return; + + /* use rigid body transform after cache start frame */ + if (ctime > rbw->pointcache->startframe) { + float mat[4][4], size_mat[4][4], size[3]; + + /* keep original transform when the simulation is muted */ + if (rbw->flag & RBW_FLAG_MUTED) + return; + + normalize_qt(rbo->orn); // RB_TODO investigate why quaternion isn't normalized at this point + quat_to_mat4(mat, rbo->orn); + copy_v3_v3(mat[3], rbo->pos); + + mat4_to_size(size, ob->obmat); + size_to_mat4(size_mat, size); + mult_m4_m4m4(mat, mat, size_mat); + + copy_m4_m4(ob->obmat, mat); + } + /* otherwise set rigid body transform to current obmat */ + else { + mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat); + } } void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) @@ -765,6 +793,77 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) /* Run RigidBody simulation for the specified physics world */ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) { -// RB_TODO implement this + float timestep; + RigidBodyWorld *rbw = scene->rigidbody_world; + PointCache *cache; + PTCacheID pid; + int startframe, endframe; + + BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw); + BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL); + cache = rbw->pointcache; + + /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */ + if (rbw->physics_world == NULL || rbw->numbodies != BLI_countlist(&rbw->group->gobject)) { + cache->flag |= PTCACHE_OUTDATED; + } + + if (ctime <= startframe) { + rbw->ltime = startframe; + /* reset and rebuild simulation if necessary */ + if (cache->flag & PTCACHE_OUTDATED) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + rigidbody_update_simulation(scene, rbw, true); + BKE_ptcache_validate(cache, (int)ctime); + cache->last_exact = 0; + cache->flag &= ~PTCACHE_REDO_NEEDED; + } + return; + } + /* rebuild world if it's outdated on second frame */ + else if (ctime == startframe + 1 && rbw->ltime == startframe && cache->flag & PTCACHE_OUTDATED) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + rigidbody_update_simulation(scene, rbw, true); + } + /* make sure we don't go out of cache frame range */ + else if (ctime > endframe) { + ctime = endframe; + } + + /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */ + if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED)) + return; + else if (rbw->objects == NULL) + rigidbody_update_ob_array(rbw); + + /* try to read from cache */ + // RB_TODO deal with interpolated, old and baked results + if (BKE_ptcache_read(&pid, ctime)) { + BKE_ptcache_validate(cache, (int)ctime); + rbw->ltime = ctime; + return; + } + + /* advance simulation, we can only step one frame forward */ + if (ctime == rbw->ltime + 1) { + /* write cache for first frame when on second frame */ + if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { + BKE_ptcache_write(&pid, startframe); + } + + /* update and validate simulation */ + rigidbody_update_simulation(scene, rbw, false); + + /* calculate how much time elapsed since last step in seconds */ + timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale; + /* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */ + RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f)); + + /* write cache for current frame */ + BKE_ptcache_validate(cache, (int)ctime); + BKE_ptcache_write(&pid, (unsigned int)ctime); + + rbw->ltime = ctime; + } } /* ************************************** */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index e48cf369d4f..b0938f78435 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1206,6 +1206,12 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) BKE_animsys_evaluate_all_animation(bmain, sce, ctime); /*...done with recusrive funcs */ + /* run rigidbody sim */ + // XXX: this position may still change, objects not being updated correctly before simulation is run + // NOTE: current position is so that rigidbody sim affects other objects + if (BKE_scene_check_rigidbody_active(sce)) + BKE_rigidbody_do_simulation(sce, ctime); + /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later * when trying to find materials with drivers that need evaluating [#32017] */ -- cgit v1.2.3 From 47c96081d00f2edfb1148d5d7c276489f03a8581 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 23 Jan 2013 05:56:56 +0000 Subject: rigidbody: Add rigid body constraints Constraints connect two rigid bodies. Depending on which constraint is used different degrees of freedom are limited, e.g. a hinge constraint only allows the objects to rotate around a common axis. Constraints are implemented as individual objects and bahave similar to rigid bodies in terms of adding/removing/validating. The position and orientation of the constraint object is the pivot point of the constraint. Constraints have their own group in the rigid body world. To make connecting rigid bodies easier, there is a "Connect" operator that creates an empty objects with a rigid body constraint connecting the selected objects to active. Currently the following constraints are implemented: * Fixed * Point * Hinge * Slider * Piston * Generic Note: constraint limits aren't animatable yet). --- source/blender/blenkernel/intern/object.c | 4 +- source/blender/blenkernel/intern/pointcache.c | 2 +- source/blender/blenkernel/intern/rigidbody.c | 320 +++++++++++++++++++++++++- source/blender/blenkernel/intern/scene.c | 3 + 4 files changed, 326 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index cf1b21e91de..0c1a23bf41d 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -388,6 +388,7 @@ void BKE_object_free(Object *ob) free_partdeflect(ob->pd); BKE_rigidbody_free_object(ob); + BKE_rigidbody_free_constraint(ob); if (ob->soft) sbFree(ob->soft); if (ob->bsoft) bsbFree(ob->bsoft); @@ -1288,9 +1289,10 @@ static Object *object_copy_do(Object *ob, int copy_caches) } obn->soft = copy_softbody(ob->soft, copy_caches); obn->bsoft = copy_bulletsoftbody(ob->bsoft); + obn->rigidbody_object = BKE_rigidbody_copy_object(ob); + obn->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob); BKE_object_copy_particlesystems(obn, ob); - obn->rigidbody_object = BKE_rigidbody_copy_object(ob); obn->derivedDeform = NULL; obn->derivedFinal = NULL; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index afc552ae7f3..1670389566e 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2777,7 +2777,7 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } } - if (scene->rigidbody_world && ob->rigidbody_object) { + if (scene->rigidbody_world && (ob->rigidbody_object || ob->rigidbody_constraint)) { if (ob->rigidbody_object) ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE; BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world); diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 359c46f2b0e..d4a7013fb8f 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -74,13 +74,23 @@ /* Free rigidbody world */ void BKE_rigidbody_free_world(RigidBodyWorld *rbw) { - GroupObject *go; /* sanity check */ if (!rbw) return; if (rbw->physics_world) { /* free physics references, we assume that all physics objects in will have been added to the world */ + GroupObject *go; + if (rbw->constraints) { + for (go = rbw->constraints->gobject.first; go; go = go->next) { + if (go->ob && go->ob->rigidbody_constraint) { + RigidBodyCon *rbc = go->ob->rigidbody_constraint; + + if (rbc->physics_constraint) + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } + } + } if (rbw->group) { for (go = rbw->group->gobject.first; go; go = go->next) { if (go->ob && go->ob->rigidbody_object) { @@ -134,6 +144,26 @@ void BKE_rigidbody_free_object(Object *ob) ob->rigidbody_object = NULL; } +/* Free RigidBody constraint and sim instance */ +void BKE_rigidbody_free_constraint(Object *ob) +{ + RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL; + + /* sanity check */ + if (rbc == NULL) + return; + + /* free physics reference */ + if (rbc->physics_constraint) { + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; + } + + /* free data itself */ + MEM_freeN(rbc); + ob->rigidbody_constraint = NULL; +} + /* Copying Methods --------------------- */ /* These just copy the data, clearing out references to physics objects. @@ -161,6 +191,27 @@ RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) return rboN; } +RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) +{ + RigidBodyCon *rbcN = NULL; + + if (ob->rigidbody_constraint) { + /* just duplicate the whole struct first (to catch all the settings) */ + rbcN = MEM_dupallocN(ob->rigidbody_constraint); + + // RB_TODO be more clever about copying constrained objects + + /* tag object as needing to be verified */ + rbcN->flag |= RBC_FLAG_NEEDS_VALIDATE; + + /* clear out all the fields which need to be revalidated later */ + rbcN->physics_constraint = NULL; + } + + /* return new copy of settings */ + return rbcN; +} + /* ************************************** */ /* Setup Utilities - Validate Sim Instances */ @@ -381,6 +432,7 @@ void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short re return; /* make sure collision shape exists */ + /* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, but it's needed for constraints to update correctly */ if (rbo->physics_shape == NULL || rebuild) BKE_rigidbody_validate_sim_shape(ob, true); @@ -428,6 +480,151 @@ void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short re /* --------------------- */ +/* Create physics sim representation of constraint given rigid body constraint settings + * < rebuild: even if an instance already exists, replace it + */ +void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, short rebuild) +{ + RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL; + float loc[3]; + float rot[4]; + float lin_lower; + float lin_upper; + float ang_lower; + float ang_upper; + + /* sanity checks: + * - object should have a rigid body constraint + * - rigid body constraint should have at least one constrained object + */ + if (rbc == NULL) { + return; + } + + if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) { + if (rbc->physics_constraint) { + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; + } + return; + } + + if (rbc->physics_constraint) { + if (rebuild == false) + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } + if (rbc->physics_constraint == NULL || rebuild) { + rbRigidBody *rb1 = rbc->ob1->rigidbody_object->physics_object; + rbRigidBody *rb2 = rbc->ob2->rigidbody_object->physics_object; + + /* remove constraint if it already exists before creating a new one */ + if (rbc->physics_constraint) { + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; + } + + mat4_to_loc_quat(loc, rot, ob->obmat); + + if (rb1 && rb2) { + switch (rbc->type) { + case RBC_TYPE_POINT: + rbc->physics_constraint = RB_constraint_new_point(loc, rb1, rb2); + break; + case RBC_TYPE_FIXED: + rbc->physics_constraint = RB_constraint_new_fixed(loc, rot, rb1, rb2); + break; + case RBC_TYPE_HINGE: + rbc->physics_constraint = RB_constraint_new_hinge(loc, rot, rb1, rb2); + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) { + RB_constraint_set_limits_hinge(rbc->physics_constraint, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper); + } + else + RB_constraint_set_limits_hinge(rbc->physics_constraint, 0.0f, -1.0f); + break; + case RBC_TYPE_SLIDER: + rbc->physics_constraint = RB_constraint_new_slider(loc, rot, rb1, rb2); + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) + RB_constraint_set_limits_slider(rbc->physics_constraint, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper); + else + RB_constraint_set_limits_slider(rbc->physics_constraint, 0.0f, -1.0f); + break; + case RBC_TYPE_PISTON: + rbc->physics_constraint = RB_constraint_new_piston(loc, rot, rb1, rb2); + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) { + lin_lower = rbc->limit_lin_x_lower; + lin_upper = rbc->limit_lin_x_upper; + } + else { + lin_lower = 0.0f; + lin_upper = -1.0f; + } + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) { + ang_lower = rbc->limit_ang_x_lower; + ang_upper = rbc->limit_ang_x_upper; + } + else { + ang_lower = 0.0f; + ang_upper = -1.0f; + } + RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper); + break; + case RBC_TYPE_6DOF: + rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f); + break; + } + } + + RB_constraint_set_enabled(rbc->physics_constraint, rbc->flag & RBC_FLAG_ENABLED); + + if (rbc->flag & RBC_FLAG_USE_BREAKING) + RB_constraint_set_breaking_threshold(rbc->physics_constraint, rbc->breaking_threshold); + else + RB_constraint_set_breaking_threshold(rbc->physics_constraint, FLT_MAX); + + if (rbc->flag & RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS) + RB_constraint_set_solver_iterations(rbc->physics_constraint, rbc->num_solver_iterations); + else + RB_constraint_set_solver_iterations(rbc->physics_constraint, -1); + } + + if (rbw && rbw->physics_world && rbc->physics_constraint) { + RB_dworld_add_constraint(rbw->physics_world, rbc->physics_constraint, rbc->flag & RBC_FLAG_DISABLE_COLLISIONS); + } +} + +/* --------------------- */ + /* Create physics sim world given RigidBody world settings */ // NOTE: this does NOT update object references that the scene uses, in case those aren't ready yet! void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild) @@ -536,6 +733,55 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) return rbo; } +/* Add rigid body constraint to the specified object */ +RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) +{ + RigidBodyCon *rbc; + RigidBodyWorld *rbw = scene->rigidbody_world; + + /* sanity checks + * - rigidbody world must exist + * - object must exist + * - cannot add constraint if it already exists + */ + if (ob == NULL || (ob->rigidbody_constraint != NULL)) + return NULL; + + /* create new settings data, and link it up */ + rbc = MEM_callocN(sizeof(RigidBodyCon), "RigidBodyCon"); + + /* set default settings */ + rbc->type = type; + + rbc->ob1 = NULL; + rbc->ob2 = NULL; + + rbc->flag |= RBC_FLAG_ENABLED; + rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS; + + rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */ + rbc->num_solver_iterations = 10; /* 10 is Bullet default */ + + rbc->limit_lin_x_lower = -1.0f; + rbc->limit_lin_x_upper = 1.0f; + rbc->limit_lin_y_lower = -1.0f; + rbc->limit_lin_y_upper = 1.0f; + rbc->limit_lin_z_lower = -1.0f; + rbc->limit_lin_z_upper = 1.0f; + rbc->limit_ang_x_lower = -M_PI_4; + rbc->limit_ang_x_upper = M_PI_4; + rbc->limit_ang_y_lower = -M_PI_4; + rbc->limit_ang_y_upper = M_PI_4; + rbc->limit_ang_z_lower = -M_PI_4; + rbc->limit_ang_z_upper = M_PI_4; + + /* flag cache as outdated */ + BKE_rigidbody_cache_reset(rbw); + + /* return this object */ + return rbc; +} + /* ************************************** */ /* Utilities API */ @@ -555,6 +801,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) { RigidBodyWorld *rbw = scene->rigidbody_world; RigidBodyOb *rbo = ob->rigidbody_object; + RigidBodyCon *rbc; GroupObject *go; int i; @@ -572,9 +819,46 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) } } } + + /* remove object from rigid body constraints */ + if (rbw->constraints) { + for (go = rbw->constraints->gobject.first; go; go = go->next) { + Object *obt = go->ob; + if (obt) { + rbc = obt->rigidbody_constraint; + if (rbc->ob1 == ob) { + rbc->ob1 = NULL; + rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; + } + if (rbc->ob2 == ob) { + rbc->ob2 = NULL; + rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; + } + } + } + } } + /* remove object's settings */ BKE_rigidbody_free_object(ob); + + /* flag cache as outdated */ + BKE_rigidbody_cache_reset(rbw); +} + +void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + RigidBodyCon *rbc = ob->rigidbody_constraint; + + if (rbw) { + /* remove from rigidbody world, free object won't do this */ + if (rbw && rbw->physics_world && rbc->physics_constraint) + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } + /* remove object's settings */ + BKE_rigidbody_free_constraint(ob); + /* flag cache as outdated */ BKE_rigidbody_cache_reset(rbw); } @@ -746,6 +1030,40 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, int r rigidbody_update_sim_ob(scene, rbw, ob, rbo); } } + /* update constraints */ + if (rbw->constraints == NULL) /* no constraints, move on */ + return; + for (go = rbw->constraints->gobject.first; go; go = go->next) { + Object *ob = go->ob; + + if (ob) { + /* validate that we've got valid object set up here... */ + RigidBodyCon *rbc = ob->rigidbody_constraint; + /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ + BKE_object_where_is_calc(scene, ob); + + if (rbc == NULL) { + /* Since this object is included in the group but doesn't have + * constraint settings (perhaps it was added manually), add! + */ + ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED); + BKE_rigidbody_validate_sim_constraint(rbw, ob, true); + + rbc = ob->rigidbody_constraint; + } + else { + /* perform simulation data updates as tagged */ + if (rebuild) { + /* World has been rebuilt so rebuild constraint */ + BKE_rigidbody_validate_sim_constraint(rbw, ob, true); + } + else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) { + BKE_rigidbody_validate_sim_constraint(rbw, ob, false); + } + rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE; + } + } + } } /* Sync rigid body and object transformations */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b0938f78435..fa3dac67a7f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -943,6 +943,9 @@ Base *BKE_scene_base_add(Scene *sce, Object *ob) void BKE_scene_base_remove(Scene *sce, Base *base) { + /* remove rigid body constraint from world before removing object */ + if (base->object->rigidbody_constraint) + BKE_rigidbody_remove_constraint(sce, base->object); /* remove rigid body object from world before removing object */ if (base->object->rigidbody_object) BKE_rigidbody_remove_object(sce, base->object); -- cgit v1.2.3 From c48238fac6c3a8a767c290ebb1c5e22b18d9bfe9 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 23 Jan 2013 05:57:01 +0000 Subject: rigidbody: Add generic spring constraint Behaves like the generic constraint but has optional spring on each axis. TODO: Add option to set rest length. Patch by Markus Kasten (markus111), thanks! --- source/blender/blenkernel/intern/rigidbody.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index d4a7013fb8f..4f154bce071 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -569,8 +569,26 @@ void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, shor } RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper); break; + case RBC_TYPE_6DOF_SPRING: + rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2); + + RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X); + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x); + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x); + + RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y); + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y); + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y); + + RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z); + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z); + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z); + + RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint); + /* fall through */ case RBC_TYPE_6DOF: - rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2); + if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */ + rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2); if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper); @@ -775,6 +793,13 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty rbc->limit_ang_z_lower = -M_PI_4; rbc->limit_ang_z_upper = M_PI_4; + rbc->spring_damping_x = 0.5f; + rbc->spring_damping_y = 0.5f; + rbc->spring_damping_z = 0.5f; + rbc->spring_stiffness_x = 10.0f; + rbc->spring_stiffness_y = 10.0f; + rbc->spring_stiffness_z = 10.0f; + /* flag cache as outdated */ BKE_rigidbody_cache_reset(rbw); -- cgit v1.2.3 From 69ddc5eb99d36c7d2cf86a7537a3784d3c72777e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 23 Jan 2013 07:26:39 +0000 Subject: make bullet optional again --- source/blender/blenkernel/CMakeLists.txt | 6 +++-- source/blender/blenkernel/SConscript | 2 +- source/blender/blenkernel/intern/collision.c | 6 ++--- source/blender/blenkernel/intern/pointcache.c | 8 +++--- source/blender/blenkernel/intern/rigidbody.c | 39 ++++++++++++++++++++++++++- 5 files changed, 51 insertions(+), 10 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 846ed8a9bb4..fefd4c89fbe 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -37,7 +37,6 @@ set(INC ../modifiers ../nodes ../render/extern/include - ../rigidbody ../../../intern/guardedalloc ../../../intern/iksolver/extern ../../../intern/memutil @@ -264,7 +263,10 @@ if(WITH_BULLET) list(APPEND INC_SYS ${BULLET_INCLUDE_DIRS} ) - add_definitions(-DUSE_BULLET) + list(APPEND INC + ../rigidbody + ) + add_definitions(-DWITH_BULLET) endif() #if(WITH_MOD_CLOTH_ELTOPO) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index b146235d63c..e53e4724071 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -111,7 +111,7 @@ if env['WITH_BF_QUICKTIME']: incs += ' ' + env['BF_QUICKTIME_INC'] if env['WITH_BF_BULLET']: - defs.append('USE_BULLET') + defs.append('WITH_BULLET') if env['OURPLATFORM'] == 'darwin': if env['WITH_BF_OPENMP']: diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 60bf67e19e3..061657c8f2d 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -59,7 +59,7 @@ #include "BKE_modifier.h" #include "BKE_DerivedMesh.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "Bullet-C-Api.h" #endif #include "BLI_kdopbvh.h" @@ -385,7 +385,7 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, CollisionModifierData *collmd = (CollisionModifierData *) md2; /* Cloth *cloth = clmd->clothObject; */ /* UNUSED */ MFace *face1=NULL, *face2 = NULL; -#ifdef USE_BULLET +#ifdef WITH_BULLET ClothVertex *verts1 = clmd->clothObject->verts; #endif double distance = 0; @@ -458,7 +458,7 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, } } -#ifdef USE_BULLET +#ifdef WITH_BULLET // calc distance + normal distance = plNearestPoints ( verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa, collpair->pb, collpair->vector ); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 1670389566e..ef096adc7a7 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -73,7 +73,9 @@ #include "BIK_api.h" -#include "RBI_api.h" +#ifdef WITH_BULLET +# include "RBI_api.h" +#endif /* both in intern */ #ifdef WITH_SMOKE @@ -883,10 +885,10 @@ static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUS RigidBodyOb *rbo = ob->rigidbody_object; if (rbo->type == RBO_TYPE_ACTIVE) { - +#ifdef WITH_BULLET RB_body_get_position(rbo->physics_object, rbo->pos); RB_body_get_orientation(rbo->physics_object, rbo->orn); - +#endif PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos); PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn); } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 4f154bce071..9feb6d43bce 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -42,7 +42,9 @@ #include "BLI_blenlib.h" #include "BLI_math.h" -#include "RBI_api.h" +#ifdef WITH_BULLET +# include "RBI_api.h" +#endif #include "DNA_anim_types.h" #include "DNA_group_types.h" @@ -66,6 +68,8 @@ #include "RNA_access.h" +#ifdef WITH_BULLET + /* ************************************** */ /* Memory Management */ @@ -1210,3 +1214,36 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) } } /* ************************************** */ + +#else /* WITH_BULLET */ + +/* stubs */ +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +void BKE_rigidbody_free_world(RigidBodyWorld *rbw) {} +void BKE_rigidbody_free_object(Object *ob) {} +void BKE_rigidbody_free_constraint(Object *ob) {} +struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; } +struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; } +void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild) {} +void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short rebuild) {} +void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, short rebuild) {} +void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild) {} +struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; } +struct RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) { return NULL; } +struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) { return NULL; } +struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; } +void BKE_rigidbody_remove_object(Scene *scene, Object *ob) {} +void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {} +void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) {} +void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} +void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} + +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif + +#endif /* WITH_BULLET */ -- cgit v1.2.3 From d2161ec488bdee56a47d00375b9176e95339918c Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 23 Jan 2013 11:00:57 +0000 Subject: Blender 2.66 Release Cycles: * We enter BCon3 now, ongoing module work, stabilization of new features and fixes. --- source/blender/blenkernel/BKE_blender.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 2d596faabce..2548d95c383 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -52,7 +52,7 @@ extern "C" { /* can be left blank, otherwise a,b,c... etc with no quotes */ #define BLENDER_VERSION_CHAR a /* alpha/beta/rc/release, docs use this */ -#define BLENDER_VERSION_CYCLE alpha +#define BLENDER_VERSION_CYCLE beta extern char versionstr[]; /* from blender.c */ -- cgit v1.2.3 From 419ce840f974c00892df01445ccc23082bbbe7a1 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 23 Jan 2013 12:06:18 +0000 Subject: rigidbody: Make rigid bodies kinematic during transformation This allows moving rigid bodies on frame > startframe. Also rigid bodies can now be picked up and trown around while the simulation is running. Note: There is a small glitch with cancelling tansform during simulation but it's tricky to get rid of. TODO: Avoid static-static collision warnings --- source/blender/blenkernel/BKE_rigidbody.h | 1 + source/blender/blenkernel/intern/rigidbody.c | 57 ++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index 26a003841c4..607c3026388 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -87,6 +87,7 @@ void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob); /* -------------- */ /* Simulation */ +void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle); void BKE_rigidbody_sync_transforms(struct Scene *scene, struct Object *ob, float ctime); void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw); void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime); diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 9feb6d43bce..ea127542962 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -953,8 +953,14 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH) RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo) * MIN3(scale[0], scale[1], scale[2])); + /* make transformed objects temporarily kinmatic so that they can be moved by the user during simulation */ + if ((ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) || rbo->type == RBO_TYPE_PASSIVE) { + RB_body_set_kinematic_state(rbo->physics_object, TRUE); + RB_body_set_mass(rbo->physics_object, 0.0f); + } + /* update rigid body location and rotation for kinematic bodies */ - if (rbo->flag & RBO_FLAG_KINEMATIC) { + if (rbo->flag & RBO_FLAG_KINEMATIC || (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) { RB_body_activate(rbo->physics_object); RB_body_set_loc_rot(rbo->physics_object, loc, rot); } @@ -1095,6 +1101,24 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, int r } } +static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw) +{ + GroupObject *go; + + for (go = rbw->group->gobject.first; go; go = go->next) { + Object *ob = go->ob; + + if (ob) { + RigidBodyOb *rbo = ob->rigidbody_object; + /* reset kinematic state for transformed objects */ + if (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) { + RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + } + } + } +} + /* Sync rigid body and object transformations */ void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) { @@ -1105,8 +1129,8 @@ void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE) return; - /* use rigid body transform after cache start frame */ - if (ctime > rbw->pointcache->startframe) { + /* use rigid body transform after cache start frame if objects is not being transformed */ + if (ctime > rbw->pointcache->startframe && !(ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) { float mat[4][4], size_mat[4][4], size[3]; /* keep original transform when the simulation is muted */ @@ -1129,6 +1153,31 @@ void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) } } +void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + + /* return rigid body and objext to their initial states */ + copy_v3_v3(rbo->pos, ob->loc); + copy_v3_v3(ob->loc, loc); + + if (ob->rotmode > 0) { + eulO_to_quat(rbo->orn, ob->rot, ob->rotmode); + copy_v3_v3(ob->rot, rot); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + axis_angle_to_quat(rbo->orn, ob->rotAxis, ob->rotAngle); + copy_v3_v3(ob->rotAxis, rotAxis); + ob->rotAngle = rotAngle; + } + else { + copy_qt_qt(rbo->orn, ob->quat); + copy_qt_qt(ob->quat, quat); + } + RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn); + // RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop) +} + void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) { if (rbw) @@ -1206,6 +1255,8 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) /* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */ RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f)); + rigidbody_update_simulation_post_step(rbw); + /* write cache for current frame */ BKE_ptcache_validate(cache, (int)ctime); BKE_ptcache_write(&pid, (unsigned int)ctime); -- cgit v1.2.3 From b9472cbd83373c303102f92432a72b1cfc0a349f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 23 Jan 2013 13:13:16 +0000 Subject: Code cleanup: move render baking code into own file. --- source/blender/blenkernel/BKE_depsgraph.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index cf7e4b24288..49dc1bfd732 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -36,13 +36,14 @@ extern "C" { // #define DEPS_DEBUG -struct ID; -struct Main; -struct Scene; -struct DagNodeQueue; struct DagForest; struct DagNode; +struct DagNodeQueue; struct GHash; +struct ID; +struct Main; +struct Object; +struct Scene; /* **** DAG relation types *** */ -- cgit v1.2.3 From 6558a22b91920e8d7b74d9b3b796a0cb263236ef Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Wed, 23 Jan 2013 14:55:41 +0000 Subject: Fix for missing function stub when WITH_BULLET is disabled. --- source/blender/blenkernel/intern/rigidbody.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index ea127542962..c2b64f5892c 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1290,6 +1290,7 @@ struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; } void BKE_rigidbody_remove_object(Scene *scene, Object *ob) {} void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {} void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) {} +void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {} void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} -- cgit v1.2.3 From c24777ee9e169dca5c8ad0a5dd5fbcc20ac180d1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 23 Jan 2013 23:42:18 +0000 Subject: style cleanup --- source/blender/blenkernel/intern/rigidbody.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index c2b64f5892c..2cbd0ebcb0a 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -466,7 +466,7 @@ void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short re RB_body_set_linear_factor(rbo->physics_object, - (ob->protectflag & OB_LOCK_LOCX) == 0, + (ob->protectflag & OB_LOCK_LOCX) == 0, (ob->protectflag & OB_LOCK_LOCY) == 0, (ob->protectflag & OB_LOCK_LOCZ) == 0); RB_body_set_angular_factor(rbo->physics_object, -- cgit v1.2.3 From 5489d5c2b5cb984112fe1b8dc1dbabbfbd6fb473 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Thu, 24 Jan 2013 03:49:30 +0000 Subject: rigidbody: Fix [#33971] Bullet Physics crash + patch BKE_rigidbody_aftertrans_update() can be called before rigid body is validated so check before updating physics_object. Thanks to Antony Riakiotakis (psy-fi) for the initial patch. --- source/blender/blenkernel/intern/rigidbody.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 2cbd0ebcb0a..7cab0d7471f 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1157,7 +1157,7 @@ void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], flo { RigidBodyOb *rbo = ob->rigidbody_object; - /* return rigid body and objext to their initial states */ + /* return rigid body and object to their initial states */ copy_v3_v3(rbo->pos, ob->loc); copy_v3_v3(ob->loc, loc); @@ -1174,7 +1174,8 @@ void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], flo copy_qt_qt(rbo->orn, ob->quat); copy_qt_qt(ob->quat, quat); } - RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn); + if (rbo->physics_object) + RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn); // RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop) } -- cgit v1.2.3 From 296f91c4cc02a5822bf8c74031be1ec35db86d3c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Jan 2013 04:02:30 +0000 Subject: add 'deform - integrate' option to mesh-cache, This means the deformation on the input to the modifier can be re-applied ontop of the mesh cache. In practice this is most useful for using corrective shape-keys with mesh-cache. --- source/blender/blenkernel/BKE_mesh.h | 10 ++++++ source/blender/blenkernel/intern/mesh.c | 62 +++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 3466a914bce..cfe562e231c 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -100,6 +100,16 @@ void BKE_mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart, float BKE_mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart, struct MVert *mvarray, const float polynormal[3]); +void BKE_mesh_calc_relative_deform( + const struct MPoly *mpoly, const int totpoly, + const struct MLoop *mloop, const int totvert, + + const float (*vert_cos_src)[3], + const float (*vert_cos_dst)[3], + + const float (*vert_cos_org)[3], + float (*vert_cos_new)[3]); + /* Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ int poly_find_loop_from_vert(const struct MPoly *poly, diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 79cbd2ef886..03df0c28944 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2993,6 +2993,68 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, } } +/** + * This function takes the difference between 2 vertex-coord-arrays + * (\a vert_cos_src, \a vert_cos_dst), + * and applies the difference to \a vert_cos_new relative to \a vert_cos_org. + * + * \param vert_cos_src reference deform source. + * \param vert_cos_dst reference deform destination. + * + * \param vert_cos_org reference for the output location. + * \param vert_cos_new resulting coords. + */ +void BKE_mesh_calc_relative_deform( + const MPoly *mpoly, const int totpoly, + const MLoop *mloop, const int totvert, + + const float (*vert_cos_src)[3], + const float (*vert_cos_dst)[3], + + const float (*vert_cos_org)[3], + float (*vert_cos_new)[3]) +{ + const MPoly *mp; + int i; + + int *vert_accum = MEM_callocN(sizeof(*vert_accum) * totvert, __func__); + + memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * totvert); + + for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { + const MLoop *loopstart = mloop + mp->loopstart; + int j; + + for (j = 0; j < mp->totloop; j++) { + int v_prev = (loopstart + ((mp->totloop + (j - 1)) % mp->totloop))->v; + int v_curr = (loopstart + j)->v; + int v_next = (loopstart + ((j + 1) % mp->totloop))->v; + + float tvec[3]; + + barycentric_transform( + tvec, vert_cos_dst[v_curr], + vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next], + vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next] + ); + + add_v3_v3(vert_cos_new[v_curr], tvec); + vert_accum[v_curr] += 1; + } + } + + for (i = 0; i < totvert; i++) { + if (vert_accum[i]) { + mul_v3_fl(vert_cos_new[i], 1.0f / (float)vert_accum[i]); + } + else { + copy_v3_v3(vert_cos_new[i], vert_cos_org[i]); + } + } + + MEM_freeN(vert_accum); +} + /* Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, -- cgit v1.2.3 From 8a60c7dc7dd0c83c69a451efe1ab49e5db0cdb74 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Jan 2013 09:36:22 +0000 Subject: fix for missing initialization of vert data in ccgDM_copyFinalVertArray --- source/blender/blenkernel/intern/subsurf_ccg.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index d665269c6ca..8a4471eec29 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1119,6 +1119,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) vd = ccgSubSurf_getFaceCenterData(f); copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); + mvert[i].flag = mvert[i].bweight = 0; i++; for (S = 0; S < numVerts; S++) { -- cgit v1.2.3 From 9592cade86b8ca15b72584f038508278434f8d89 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 24 Jan 2013 11:21:40 +0000 Subject: Armature rigging: Added more clear warning print for cases when a Proxy cannot be resolved. --- source/blender/blenkernel/BKE_action.h | 2 +- source/blender/blenkernel/intern/action.c | 9 +++++---- source/blender/blenkernel/intern/object.c | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 2d7030b2d42..2d20672a015 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -220,7 +220,7 @@ void BKE_pose_remove_group(struct Object *ob); void what_does_obaction(struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe); /* for proxy */ -void BKE_pose_copy_result(struct bPose *to, struct bPose *from); +int BKE_pose_copy_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void BKE_pose_rest(struct bPose *pose); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 63e12dfb99d..1aceca0bbd5 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1118,18 +1118,18 @@ void BKE_pose_rest(bPose *pose) } /* both poses should be in sync */ -void BKE_pose_copy_result(bPose *to, bPose *from) +int BKE_pose_copy_result(bPose *to, bPose *from) { bPoseChannel *pchanto, *pchanfrom; if (to == NULL || from == NULL) { - printf("pose result copy error to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */ - return; + printf("Pose copy error, pose to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */ + return 0; } if (to == from) { printf("BKE_pose_copy_result source and target are the same\n"); - return; + return 0; } @@ -1153,6 +1153,7 @@ void BKE_pose_copy_result(bPose *to, bPose *from) pchanto->protectflag = pchanfrom->protectflag; } } + return 1; } /* For the calculation of the effects of an Action at the given frame on an object diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0c1a23bf41d..555fa0791fd 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2711,8 +2711,8 @@ void BKE_object_handle_update(Scene *scene, Object *ob) case OB_ARMATURE: if (ob->id.lib && ob->proxy_from) { - // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name); - BKE_pose_copy_result(ob->pose, ob->proxy_from->pose); + if (0 == BKE_pose_copy_result(ob->pose, ob->proxy_from->pose)) + printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name+2, ob->proxy_from->id.name+2); } else { BKE_pose_where_is(scene, ob); -- cgit v1.2.3 From 66bf63d7af52762a81876adc2907c4fc414716f9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Jan 2013 11:28:26 +0000 Subject: use inline functions for subsurf MVert,MEdge mesh array functions, also some include cleanup for scons/cmake. --- source/blender/blenkernel/intern/subsurf_ccg.c | 110 ++++++++++++------------- 1 file changed, 51 insertions(+), 59 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 8a4471eec29..2e10407bee8 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1097,6 +1097,14 @@ void subsurf_copy_grid_paint_mask(DerivedMesh *dm, const MPoly *mpoly, } } +/* utility functon */ +BLI_INLINE void ccgDM_to_MVert(MVert *mv, const CCGKey *key, CCGElem *elem) +{ + copy_v3_v3(mv->co, CCG_elem_co(key, elem)); + normal_float_to_short_v3(mv->no, CCG_elem_no(key, elem)); + mv->flag = mv->bweight = 0; +} + static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; @@ -1107,7 +1115,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) int totvert, totedge, totface; int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); - int i = 0; + unsigned int i = 0; CCG_key_top_level(&key, ss); @@ -1117,27 +1125,20 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); vd = ccgSubSurf_getFaceCenterData(f); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); - mvert[i].flag = mvert[i].bweight = 0; - i++; + ccgDM_to_MVert(&mvert[i++], &key, vd); for (S = 0; S < numVerts; S++) { - for (x = 1; x < gridSize - 1; x++, i++) { + for (x = 1; x < gridSize - 1; x++) { vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); - mvert[i].flag = mvert[i].bweight = 0; + ccgDM_to_MVert(&mvert[i++], &key, vd); } } for (S = 0; S < numVerts; S++) { for (y = 1; y < gridSize - 1; y++) { - for (x = 1; x < gridSize - 1; x++, i++) { + for (x = 1; x < gridSize - 1; x++) { vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); - mvert[i].flag = mvert[i].bweight = 0; + ccgDM_to_MVert(&mvert[i++], &key, vd); } } } @@ -1148,16 +1149,14 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) CCGEdge *e = ccgdm->edgeMap[index].edge; int x; - for (x = 1; x < edgeSize - 1; x++, i++) { - vd = ccgSubSurf_getEdgeData(ss, e, x); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); + for (x = 1; x < edgeSize - 1; x++) { /* This gives errors with -debug-fpe * the normals don't seem to be unit length. * this is most likely caused by edges with no * faces which are now zerod out, see comment in: * ccgSubSurf__calcVertNormals(), - campbell */ - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); - mvert[i].flag = mvert[i].bweight = 0; + vd = ccgSubSurf_getEdgeData(ss, e, x); + ccgDM_to_MVert(&mvert[i++], &key, vd); } } @@ -1166,13 +1165,20 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) CCGVert *v = ccgdm->vertMap[index].vert; vd = ccgSubSurf_getVertData(ss, v); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); - mvert[i].flag = mvert[i].bweight = 0; - i++; + ccgDM_to_MVert(&mvert[i++], &key, vd); } } + +/* utility functon */ +BLI_INLINE void ccgDM_to_MEdge(MEdge *med, const int v1, const int v2, const short flag) +{ + med->v1 = v1; + med->v2 = v2; + med->crease = med->bweight = 0; + med->flag = flag; +} + static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; @@ -1181,7 +1187,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) int totedge, totface; int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); - int i = 0; + unsigned int i = 0; short *edgeFlags = ccgdm->edgeFlags; const short ed_interior_flag = ccgdm->drawInteriorEdges ? (ME_EDGEDRAW | ME_EDGERENDER) : 0; @@ -1192,36 +1198,22 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) for (S = 0; S < numVerts; S++) { for (x = 0; x < gridSize - 1; x++) { - MEdge *med = &medge[i]; - - med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize); - med->crease = med->bweight = 0; - med->flag = ed_interior_flag; - i++; + ccgDM_to_MEdge(&medge[i++], + getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize), + getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize), + ed_interior_flag); } for (x = 1; x < gridSize - 1; x++) { for (y = 0; y < gridSize - 1; y++) { - MEdge *med; - - med = &medge[i]; - med->v1 = getFaceIndex(ss, f, S, x, y, - edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, S, x, y + 1, - edgeSize, gridSize); - med->crease = med->bweight = 0; - med->flag = ed_interior_flag; - i++; - - med = &medge[i]; - med->v1 = getFaceIndex(ss, f, S, y, x, - edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, S, y + 1, x, - edgeSize, gridSize); - med->crease = med->bweight = 0; - med->flag = ed_interior_flag; - i++; + ccgDM_to_MEdge(&medge[i++], + getFaceIndex(ss, f, S, x, y, edgeSize, gridSize), + getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize), + ed_interior_flag); + ccgDM_to_MEdge(&medge[i++], + getFaceIndex(ss, f, S, y, x, edgeSize, gridSize), + getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize), + ed_interior_flag); } } } @@ -1230,28 +1222,28 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) totedge = ccgSubSurf_getNumEdges(ss); for (index = 0; index < totedge; index++) { CCGEdge *e = ccgdm->edgeMap[index].edge; - unsigned int flags = 0; + short ed_flag = 0; int x; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e)); - if (!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE; + if (!ccgSubSurf_getEdgeNumFaces(e)) { + ed_flag |= ME_LOOSEEDGE; + } if (edgeFlags) { if (edgeIdx != -1) { - flags |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER); + ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER); } } else { - flags |= ME_EDGEDRAW | ME_EDGERENDER; + ed_flag |= ME_EDGEDRAW | ME_EDGERENDER; } for (x = 0; x < edgeSize - 1; x++) { - MEdge *med = &medge[i]; - med->v1 = getEdgeIndex(ss, e, x, edgeSize); - med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); - med->crease = med->bweight = 0; - med->flag = flags; - i++; + ccgDM_to_MEdge(&medge[i++], + getEdgeIndex(ss, e, x, edgeSize), + getEdgeIndex(ss, e, x + 1, edgeSize), + ed_flag); } } } -- cgit v1.2.3 From 1da7d7d1a0a4297cf6b09758c01f98f50543993f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Jan 2013 14:48:08 +0000 Subject: use bool for new code. --- source/blender/blenkernel/BKE_action.h | 2 +- source/blender/blenkernel/intern/action.c | 8 ++++---- source/blender/blenkernel/intern/object.c | 6 ++++-- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 2d20672a015..4f54f93a7fc 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -220,7 +220,7 @@ void BKE_pose_remove_group(struct Object *ob); void what_does_obaction(struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe); /* for proxy */ -int BKE_pose_copy_result(struct bPose *to, struct bPose *from); +bool BKE_pose_copy_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void BKE_pose_rest(struct bPose *pose); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 1aceca0bbd5..5ccf9146440 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1118,18 +1118,18 @@ void BKE_pose_rest(bPose *pose) } /* both poses should be in sync */ -int BKE_pose_copy_result(bPose *to, bPose *from) +bool BKE_pose_copy_result(bPose *to, bPose *from) { bPoseChannel *pchanto, *pchanfrom; if (to == NULL || from == NULL) { printf("Pose copy error, pose to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */ - return 0; + return false; } if (to == from) { printf("BKE_pose_copy_result source and target are the same\n"); - return 0; + return false; } @@ -1153,7 +1153,7 @@ int BKE_pose_copy_result(bPose *to, bPose *from) pchanto->protectflag = pchanfrom->protectflag; } } - return 1; + return true; } /* For the calculation of the effects of an Action at the given frame on an object diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 555fa0791fd..b5e82586f5a 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2711,8 +2711,10 @@ void BKE_object_handle_update(Scene *scene, Object *ob) case OB_ARMATURE: if (ob->id.lib && ob->proxy_from) { - if (0 == BKE_pose_copy_result(ob->pose, ob->proxy_from->pose)) - printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name+2, ob->proxy_from->id.name+2); + if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { + printf("Proxy copy error, lib Object: %s proxy Object: %s\n", + ob->id.name + 2, ob->proxy_from->id.name + 2); + } } else { BKE_pose_where_is(scene, ob); -- cgit v1.2.3 From b12a0199480f5d452828450fa257020635f7ad6d Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 24 Jan 2013 16:11:07 +0000 Subject: Usability - Cycles materials now render in Blender Internal too, skipping the nodes. Not very useful, but at least things then show up on renders and in previews. - Node editor: if wrong shader nodes are in a tree, they draw with thene color RED ALERT headers now. (Switching render engine will show it). --- source/blender/blenkernel/BKE_node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 16d7ba8b090..d3fb7eeffc1 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -577,7 +577,7 @@ struct ShadeResult; struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data); void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); -void ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr); +int ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr); void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode); void nodeShaderSynchronizeID(struct bNode *node, int copyto); -- cgit v1.2.3 From da4028d4a8265b7d4ba608729127604ea0f87a21 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 24 Jan 2013 17:21:22 +0000 Subject: Fix #33953: blender crash after few steps with .exr image in compositor Issue was caused by FILE multilayer ImBuf sharing buffers with render result, and SEQUENCE multilayer ImBufs duplicating buffers. Which is nice by it's own. But, changing image source wouldn't remove any loaded image buffers, meaning if you've got loaded FILE multilayers they'll likely became invalid. That behavior of handling multilayers on changing source was done as a fix for #24976, which is now actually not needed (removing check for multilayer doesn't change behavior at all). Just to be sure added check to RNA, so signal wouldn't be fired if source wasn't actually changed form a menu. --- source/blender/blenkernel/intern/image.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index c56091ead62..82b0d231869 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2205,9 +2205,20 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } } +#if 0 /* force reload on first use, but not for multilayer, that makes nodes and buttons in ui drawing fail */ if (ima->type != IMA_TYPE_MULTILAYER) image_free_buffers(ima); +#else + /* image buffers for non-sequence multilayer will share buffers with RenderResult, + * however sequence multilayer will own buffers. Such logic makes switching from + * single multilayer file to sequence completely instable + * since changes in nodes seems this workaround isn't needed anymore, all sockets + * are nicely detecting anyway, but freeing buffers always here makes multilayer + * sequences behave stable + */ + image_free_buffers(ima); +#endif ima->ok = 1; if (iuser) -- cgit v1.2.3 From c411cde415ee7dc8a208e932d5ba1a240c4e669e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Jan 2013 21:57:13 +0000 Subject: header cleanup, include BLI before BKE, also use bool for ntreeShaderExecTree --- source/blender/blenkernel/BKE_DerivedMesh.h | 2 +- source/blender/blenkernel/BKE_main.h | 3 +-- source/blender/blenkernel/BKE_node.h | 2 +- source/blender/blenkernel/intern/bvhutils.c | 2 +- source/blender/blenkernel/intern/ocean.c | 9 ++++----- 5 files changed, 8 insertions(+), 10 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 64fb49c4d66..5f504df5628 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -731,4 +731,4 @@ BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int return (j != ORIGINDEX_NONE) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : ORIGINDEX_NONE; } -#endif +#endif /* __BKE_DERIVEDMESH_H__ */ diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 1b7b29432e2..8e4d370e8a0 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -99,5 +99,4 @@ typedef struct Main { } #endif -#endif - +#endif /* __BKE_MAIN_H__ */ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index d3fb7eeffc1..718fa2f9ecd 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -577,7 +577,7 @@ struct ShadeResult; struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data); void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); -int ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr); +bool ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr); void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode); void nodeShaderSynchronizeID(struct bNode *node, int copyto); diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index ad828a70dd8..5028d978351 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -38,11 +38,11 @@ #include "BLI_utildefines.h" #include "BLI_linklist.h" +#include "BLI_math.h" #include "BKE_DerivedMesh.h" #include "BKE_tessmesh.h" -#include "BLI_math.h" #include "MEM_guardedalloc.h" /* Math stuff for ray casting on mesh faces and for nearest surface */ diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index c4274aa1f93..695ac7da792 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -35,10 +35,6 @@ #include "DNA_scene_types.h" -#include "BKE_global.h" /* XXX TESTING */ -#include "BKE_image.h" -#include "BKE_ocean.h" - #include "BLI_math.h" #include "BLI_path_util.h" #include "BLI_rand.h" @@ -46,6 +42,9 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BKE_image.h" +#include "BKE_ocean.h" + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -1425,4 +1424,4 @@ void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), /* unused */ (void)update_cb; } -#endif /* WITH_OCEANSIM */ \ No newline at end of file +#endif /* WITH_OCEANSIM */ -- cgit v1.2.3 From 4f565d48fb9fc280f4794a536dae30dab0e6d65e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 26 Jan 2013 05:28:58 +0000 Subject: Motion Path calculations for objects now takes rigidbodies sim effects into account --- source/blender/blenkernel/intern/anim.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 4058809c275..dab54756c82 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -69,6 +69,7 @@ #include "BKE_depsgraph.h" #include "BKE_anim.h" #include "BKE_report.h" +#include "BKE_rigidbody.h" // XXX bad level call... @@ -327,6 +328,7 @@ static void motionpaths_calc_update_scene(Scene *scene) { #if 1 // 'production' optimizations always on Base *base, *last = NULL; + float ctime = BKE_scene_frame_get(scene); /* only stuff that moves or needs display still */ DAG_scene_update_flags(G.main, scene, scene->lay, TRUE); @@ -340,6 +342,14 @@ static void motionpaths_calc_update_scene(Scene *scene) last = base; } + /* run rigidbody sim + * NOTE: keep in sync with BKE_scene_update_for_newframe() in scene.c + */ + // XXX: this position may still change, objects not being updated correctly before simulation is run + // NOTE: current position is so that rigidbody sim affects other objects + if (BKE_scene_check_rigidbody_active(scene)) + BKE_rigidbody_do_simulation(scene, ctime); + /* perform updates for tagged objects */ /* XXX: this will break if rigs depend on scene or other data that * is animated but not attached to/updatable from objects */ -- cgit v1.2.3 From 7e49a39acda5cdc86ce87470f7dc10cd80f1eba7 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 26 Jan 2013 17:19:21 +0000 Subject: Check for deletion before moving vert in dyntopo collapse edge Fixes [#33964] Dyntopo crash with edge collapse + undo projects.blender.org/tracker/?func=detail&aid=33964&group_id=9&atid=498 --- source/blender/blenkernel/intern/pbvh_bmesh.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index c464de64c6a..9a0b1a76988 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -857,9 +857,12 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, } } - /* Move v1 to the midpoint of v1 and v2 */ - BM_log_vert_before_modified(bvh->bm, bvh->bm_log, v1); - mid_v3_v3v3(v1->co, v1->co, v2->co); + /* Move v1 to the midpoint of v1 and v2 (if v1 still exists, it + * may have been deleted above) */ + if (!BLI_ghash_haskey(deleted_verts, v1)) { + BM_log_vert_before_modified(bvh->bm, bvh->bm_log, v1); + mid_v3_v3v3(v1->co, v1->co, v2->co); + } /* Delete v2 */ BLI_assert(BM_vert_face_count(v2) == 0); -- cgit v1.2.3 From c84383301c5a2582e95259a7e4468a23a3566401 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Sat, 26 Jan 2013 17:38:45 +0000 Subject: Fix [#34005] blender will close immediately in debug mode on deleting objects Was silly mistake from rigidbody merge, base was used after it's been freed. Now don't free base in BKE_scene_base_remove() and rename it to BKE_scene_base_unlink(). --- source/blender/blenkernel/BKE_scene.h | 2 +- source/blender/blenkernel/intern/scene.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 2ac32a3f651..9bf0991272a 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -72,7 +72,7 @@ struct Scene *BKE_scene_add(struct Main *bmain, const char *name); /* base functions */ struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob); struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob); -void BKE_scene_base_remove(struct Scene *sce, struct Base *base); +void BKE_scene_base_unlink(struct Scene *sce, struct Base *base); void BKE_scene_base_deselect_all(struct Scene *sce); void BKE_scene_base_select(struct Scene *sce, struct Base *selbase); int BKE_scene_base_iter_next(struct Scene **scene, int val, struct Base **base, struct Object **ob); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index fa3dac67a7f..9e8cf985f71 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -941,7 +941,7 @@ Base *BKE_scene_base_add(Scene *sce, Object *ob) return b; } -void BKE_scene_base_remove(Scene *sce, Base *base) +void BKE_scene_base_unlink(Scene *sce, Base *base) { /* remove rigid body constraint from world before removing object */ if (base->object->rigidbody_constraint) @@ -951,7 +951,6 @@ void BKE_scene_base_remove(Scene *sce, Base *base) BKE_rigidbody_remove_object(sce, base->object); BLI_remlink(&sce->base, base); - MEM_freeN(base); } void BKE_scene_base_deselect_all(Scene *sce) -- cgit v1.2.3