diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2010-10-03 15:33:32 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2010-10-03 15:33:32 +0400 |
commit | 854ef1770075c6e1579ccbbd30eda57484527760 (patch) | |
tree | 78b799cb79a1f1c40e176ff1f51efe82d61c4896 /source/blender/blenkernel | |
parent | df528a92097d42e5f5d18ecb9f2981d75546b4d5 (diff) | |
parent | 05884e09beed97669fbec4d35b4e9427bfe997d3 (diff) |
Merged changes in the trunk up to revision 32271.
Diffstat (limited to 'source/blender/blenkernel')
21 files changed, 457 insertions, 125 deletions
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index f6d41190c5a..9f38c5833a2 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -163,6 +163,8 @@ void CTX_wm_screen_set(bContext *C, struct bScreen *screen); /* to be removed */ void CTX_wm_area_set(bContext *C, struct ScrArea *sa); void CTX_wm_region_set(bContext *C, struct ARegion *region); void CTX_wm_menu_set(bContext *C, struct ARegion *menu); +const char *CTX_wm_operator_poll_msg_get(struct bContext *C); +void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg); /* Data Context diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index db6d995aa74..39de5517170 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -69,7 +69,8 @@ void duplicateNurblist( struct ListBase *lb1, struct ListBase *lb2); void test2DNurb( struct Nurb *nu); void minmaxNurb( struct Nurb *nu, float *min, float *max); -void makeknots( struct Nurb *nu, short uv); +void nurbs_knot_calc_u(struct Nurb *nu); +void nurbs_knot_calc_v(struct Nurb *nu); void makeNurbfaces(struct Nurb *nu, float *coord_array, int rowstride); void makeNurbcurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index e246b51af09..0a07e6d482c 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -115,7 +115,7 @@ void BKE_image_release_ibuf(struct Image *ima, void *lock); struct Image *BKE_add_image_file(const char *name, int frame); /* adds image, adds ibuf, generates color or pattern */ -struct Image *BKE_add_image_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]); +struct Image *BKE_add_image_size(unsigned int width, unsigned int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]); /* adds image from imbuf, owns imbuf */ struct Image *BKE_add_image_imbuf(struct ImBuf *ibuf); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 95a9394427f..51120a61e69 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -245,6 +245,17 @@ typedef struct ModifierTypeInfo { */ int (*dependsOnTime)(struct ModifierData *md); + + /* True when a deform modifier uses normals, the requiredDataMask + * cant be used here because that refers to a normal layer where as + * in this case we need to know if the deform modifier uses normals. + * + * this is needed because applying 2 deform modifiers will give the + * second modifier bogus normals. + * */ + int (*dependsOnNormals)(struct ModifierData *md); + + /* Should call the given walk function on with a pointer to each Object * pointer that the modifier data stores. This is used for linking on file * load and for unlinking objects or forwarding object references. diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 925b1d7171a..5a6a151afee 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -38,8 +38,11 @@ #define TRUE 1 #endif -/* Macro to convert a value to string in the preprocessor */ -#define QUOTE(x) #x +/* Macro to convert a value to string in the preprocessor + * STRINGIFY_ARG: gives the defined name in the string + * STRINGIFY: gives the defined value. */ +#define STRINGIFY_ARG(x) #x +#define STRINGIFY(x) STRINGIFY_ARG(x) /* these values need to be hardcoded in structs, dna does not recognize defines */ /* also defined in DNA_space_types.h */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b4eb1d073a6..c8645f91de8 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -116,6 +116,10 @@ IF(NOT WITH_FLUID) ADD_DEFINITIONS(-DDISABLE_ELBEEM) ENDIF(NOT WITH_FLUID) +IF(WITH_JACK) + ADD_DEFINITIONS(-DWITH_JACK) +ENDIF(WITH_JACK) + IF(WITH_LZO) LIST(APPEND INC ../../../extern/lzo/minilzo) ADD_DEFINITIONS(-DWITH_LZO) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 5069fddefd6..0345ef26c9a 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -53,6 +53,9 @@ if env['WITH_BF_CINEON']: if env['WITH_BF_HDR']: defs.append('WITH_HDR') +if env['WITH_BF_JACK']: + defs.append('WITH_JACK') + if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') incs += ' ' + env['BF_FFMPEG_INC'] diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index de7b962e38a..01b02653a51 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -239,6 +239,15 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me) if(!CustomData_has_layer(&tmp.fdata, CD_MFACE)) CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupFaceArray(dm), totface); + /* object had got displacement layer, should copy this layer to save sculpted data */ + /* NOTE: maybe some other layers should be copied? nazgul */ + if(CustomData_has_layer(&me->fdata, CD_MDISPS)) { + if (totface == me->totface) { + MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + CustomData_add_layer(&tmp.fdata, CD_MDISPS, CD_DUPLICATE, mdisps, totface); + } + } + mesh_update_customdata_pointers(&tmp); CustomData_free(&me->vdata, me->totvert); @@ -1661,8 +1670,20 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos DerivedMesh *dm, *orcodm, *clothorcodm, *finaldm; int numVerts = me->totvert; int required_mode; + int isPrevDeform= FALSE; + int skipVirtualArmature = (useDeform < 0); + + if(!skipVirtualArmature) { + firstmd = modifiers_getVirtualModifierList(ob); + } + else { + /* game engine exception */ + firstmd = ob->modifiers.first; + if(firstmd && firstmd->type == eModifierType_Armature) + firstmd = firstmd->next; + } - md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob); + md = firstmd; modifiers_clearErrors(ob); @@ -1778,6 +1799,16 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } } + /* if this is not the last modifier in the stack then recalculate the normals + * to avoid giving bogus normals to the next modifier see: [#23673] */ + if(isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + /* XXX, this covers bug #23673, but we may need normal calc for other types */ + if(dm->type == DM_TYPE_CDDM) { + CDDM_apply_vert_coords(dm, deformedVerts); + CDDM_calc_normals(dm); + } + } + mti->deformVerts(md, ob, dm, deformedVerts, numVerts, useRenderParams, useDeform); } else { DerivedMesh *ndm; @@ -1888,6 +1919,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } } + isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform); + /* grab modifiers until index i */ if((index >= 0) && (modifiers_indexInObject(ob, md) >= index)) break; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 59e81293c9f..fe69f13bbda 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4358,8 +4358,7 @@ void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n, void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) { bConstraint *con; - float solution[4][4], delta[4][4]; - float oldmat[4][4], imat[4][4]; + float oldmat[4][4]; float enf; /* check that there is a valid constraint object to evaluate */ diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 7928424e47c..a5d96baf049 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -64,6 +64,7 @@ struct bContext { struct ARegion *region; struct ARegion *menu; struct bContextStore *store; + const char *operator_poll_msg; /* reason for poll failing */ } wm; /* data context */ @@ -399,6 +400,16 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu) C->wm.menu= menu; } +void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg) +{ + C->wm.operator_poll_msg= msg; +} + +const char *CTX_wm_operator_poll_msg_get(bContext *C) +{ + return C->wm.operator_poll_msg; +} + /* data context utility functions */ struct bContextDataResult { diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 358dd1914e7..9578b5185af 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -74,12 +74,22 @@ void unlink_curve(Curve *cu) for(a=0; a<cu->totcol; a++) { if(cu->mat[a]) cu->mat[a]->id.us--; - cu->mat[a]= 0; + cu->mat[a]= NULL; } if(cu->vfont) cu->vfont->id.us--; - cu->vfont= 0; + cu->vfont= NULL; + + if(cu->vfontb) cu->vfontb->id.us--; + cu->vfontb= NULL; + + if(cu->vfonti) cu->vfonti->id.us--; + cu->vfonti= NULL; + + if(cu->vfontbi) cu->vfontbi->id.us--; + cu->vfontbi= NULL; + if(cu->key) cu->key->id.us--; - cu->key= 0; + cu->key= NULL; } /* frees editcurve entirely */ @@ -210,9 +220,12 @@ void make_local_curve(Curve *cu) */ if(cu->id.lib==0) return; - - if(cu->vfont) cu->vfont->id.lib= 0; - + + if(cu->vfont) cu->vfont->id.lib= NULL; + if(cu->vfontb) cu->vfontb->id.lib= NULL; + if(cu->vfonti) cu->vfonti->id.lib= NULL; + if(cu->vfontbi) cu->vfontbi->id.lib= NULL; + if(cu->id.us==1) { cu->id.lib= 0; cu->id.flag= LIB_LOCAL; @@ -623,7 +636,7 @@ static void makecyclicknots(float *knots, short pnts, short order) -void makeknots(Nurb *nu, short uv) +static void makeknots(Nurb *nu, short uv) { if(nu->type == CU_NURBS) { if(uv == 1) { @@ -655,6 +668,16 @@ void makeknots(Nurb *nu, short uv) } } +void nurbs_knot_calc_u(Nurb *nu) +{ + makeknots(nu, 1); +} + +void nurbs_knot_calc_v(Nurb *nu) +{ + makeknots(nu, 2); +} + static void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end) { float d, e; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 1f4b0f303f7..1f867a615b2 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -42,6 +42,7 @@ #include "BLI_blenlib.h" #include "BLI_linklist.h" +#include "BLI_math.h" #include "BLI_mempool.h" #include "BKE_customdata.h" @@ -452,22 +453,27 @@ static void layerSwap_mdisps(void *data, const int *ci) int corners, cornersize, S; /* this function is untested .. */ - corners = mdisp_corners(s); - cornersize = s->totdisp/corners; + if(s->disps) { + corners = mdisp_corners(s); + cornersize = s->totdisp/corners; - d = MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); + d = MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); - for(S = 0; S < corners; S++) - memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float)); - - if(s->disps) - MEM_freeN(s->disps); - s->disps = d; + for(S = 0; S < corners; S++) + memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float)); + + if(s->disps) + MEM_freeN(s->disps); + s->disps = d; + } } static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights, int count, void *dest) { + MDisps *d = dest; + int i; + // XXX #if 0 MDisps *d = dest; @@ -514,6 +520,11 @@ static void layerInterp_mdisps(void **sources, float *weights, float *sub_weight copy_v3_v3(d->disps[y * st + x], srcdisp); } } +#else + if(d->disps) { + for(i = 0; i < d->totdisp; ++i) + zero_v3(d->disps[i]); + } #endif } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 344f8500075..cb2261932ce 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -382,7 +382,7 @@ Image *BKE_add_image_file(const char *name, int frame) return ima; } -static ImBuf *add_ibuf_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) +static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) { ImBuf *ibuf; unsigned char *rect= NULL; @@ -415,7 +415,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int depth, int fl } /* adds new image block, creates ImBuf and initializes color */ -Image *BKE_add_image_size(int width, int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) +Image *BKE_add_image_size(unsigned int width, unsigned int height, char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) { /* on save, type is changed to FILE in editsima.c */ Image *ima= image_alloc(name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); @@ -2139,10 +2139,15 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) BLI_lock_thread(LOCK_VIEWER); *lock_r= ima; - /* Composite Viewer, all handled in compositor */ - /* fake ibuf, will be filled in compositor */ - ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); - image_assign_ibuf(ima, ibuf, 0, frame); + frame= iuser?iuser->framenr:0; + ibuf= image_get_ibuf(ima, 0, frame); + + if(!ibuf) { + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); + image_assign_ibuf(ima, ibuf, 0, frame); + } } } } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 135ddbab2b7..cb98c2282bc 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1690,6 +1690,45 @@ static int node_recurs_check(bNode *node, bNode ***nsort, int level) return 0xFFF; } + +static void ntreeSetOutput(bNodeTree *ntree) +{ + bNode *node; + + /* find the active outputs, might become tree type dependant handler */ + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { + bNode *tnode; + int output= 0; + + /* we need a check for which output node should be tagged like this, below an exception */ + if(node->type==CMP_NODE_OUTPUT_FILE) + continue; + + /* there is more types having output class, each one is checked */ + for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) { + if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) { + /* same type, exception for viewer */ + if(tnode->type==node->type || + (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && + ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) { + if(tnode->flag & NODE_DO_OUTPUT) { + output++; + if(output>1) + tnode->flag &= ~NODE_DO_OUTPUT; + } + } + } + } + if(output==0) + node->flag |= NODE_DO_OUTPUT; + } + } + + /* here we could recursively set which nodes have to be done, + might be different for editor or for "real" use... */ +} + void ntreeSolveOrder(bNodeTree *ntree) { bNode *node, **nodesort, **nsort; @@ -1738,38 +1777,11 @@ void ntreeSolveOrder(bNodeTree *ntree) } MEM_freeN(nodesort); - - /* find the active outputs, might become tree type dependant handler */ - for(node= ntree->nodes.first; node; node= node->next) { - if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { - bNode *tnode; - int output= 0; - - /* we need a check for which output node should be tagged like this, below an exception */ - if(node->type==CMP_NODE_OUTPUT_FILE) - continue; - - /* there is more types having output class, each one is checked */ - for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) { - if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) { - if(tnode->type==node->type) { - if(tnode->flag & NODE_DO_OUTPUT) { - output++; - if(output>1) - tnode->flag &= ~NODE_DO_OUTPUT; - } - } - } - } - if(output==0) - node->flag |= NODE_DO_OUTPUT; - } - } - - /* here we could recursively set which nodes have to be done, - might be different for editor or for "real" use... */ + + ntreeSetOutput(ntree); } + /* Should be callback! */ /* Do not call execs here */ void NodeTagChanged(bNodeTree *ntree, bNode *node) @@ -2466,6 +2478,9 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) /* fixed seed, for example noise texture */ BLI_srandom(rd->cfra); + /* ensures only a single output node is enabled */ + ntreeSetOutput(ntree); + /* sets need_exec tags in nodes */ curnode = totnode= setExecutableNodes(ntree, &thdata); @@ -2564,7 +2579,10 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) } /* end animdata uglyness */ - + + /* ensures only a single output node is enabled */ + ntreeSetOutput(ntree); + /* move over the compbufs */ /* right after ntreeCopyTree() oldsock pointers are valid */ for(node= ntree->nodes.first; node; node= node->next) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index f45c0717b26..d9ee67920eb 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -532,12 +532,10 @@ void unlink_object(Scene *scene, Object *ob) } /* textures */ - tex= bmain->tex.first; - while(tex) { - if(tex->env) { - if(tex->env->object == ob) tex->env->object= NULL; - } - tex= tex->id.next; + for(tex= bmain->tex.first; tex; tex= tex->id.next) { + if(tex->env && (ob==tex->env->object)) tex->env->object= NULL; + if(tex->pd && (ob==tex->pd->object)) tex->pd->object= NULL; + if(tex->vd && (ob==tex->vd->object)) tex->vd->object= NULL; } /* worlds */ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 6b75f5d417c..723ff7faed3 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -272,7 +272,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) } psmd= psys_get_modifier(ob, psys); - if(psys->renderdata) { + if(psys->renderdata || G.rendering) { if(!(psmd->modifier.mode & eModifierMode_Render)) return 0; } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 741580048cf..784f6e40706 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1008,11 +1008,22 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - if(psys->part) { - pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_particles(pid, ob, psys); - BLI_addtail(lb, pid); - } + if(psys->part==NULL) + continue; + + /* check to make sure point cache is actually used by the particles */ + if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) + continue; + + if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) + continue; + + if(psys->part->type == PART_FLUID) + continue; + + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_particles(pid, ob, psys); + BLI_addtail(lb, pid); } for(md=ob->modifiers.first; md; md=md->next) { @@ -1876,6 +1887,9 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) else cache->flag |= PTCACHE_FRAMES_SKIPPED; } + + if(cache->cached_frames) + cache->cached_frames[cfra] = 1; if(pf) ptcache_file_close(pf); @@ -1893,6 +1907,9 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) { int len; /* store the length of the string */ + int i; + int sta = pid->cache->startframe; + int end = pid->cache->endframe; /* mode is same as fopen's modes */ DIR *dir; @@ -1936,6 +1953,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) pid->cache->last_exact = MIN2(pid->cache->startframe, 0); BLI_join_dirfile(path_full, path, de->d_name); BLI_delete(path_full, 0, 0); + if(pid->cache->cached_frames) for(i=0; i<end-sta+1; i++) + pid->cache->cached_frames[i] = 0; } else { /* read the number of the file */ int frame, len2 = (int)strlen(de->d_name); @@ -1950,6 +1969,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) BLI_join_dirfile(path_full, path, de->d_name); BLI_delete(path_full, 0, 0); + if(frame >=sta && frame <= end) + pid->cache->cached_frames[frame-sta] = 0; } } } @@ -1970,11 +1991,16 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) for(; pm; pm=pm->next) ptcache_free_data(pm); BLI_freelistN(&pid->cache->mem_cache); + + if(pid->cache->cached_frames) for(i=0; i<end-sta+1; i++) + pid->cache->cached_frames[i] = 0; } else { while(pm) { if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { link = pm; + if(pm->frame >=sta && pm->frame <= end) + pid->cache->cached_frames[pm->frame-sta] = 0; ptcache_free_data(pm); pm = pm->next; BLI_freelinkN(&pid->cache->mem_cache, link); @@ -2004,6 +2030,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) } } } + if(pid->cache->cached_frames && cfra>=sta && cfra<=end) + pid->cache->cached_frames[cfra-sta] = 0; break; } @@ -2014,6 +2042,12 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { if(!pid->cache) return 0; + + if(cfra<pid->cache->startframe || cfra > pid->cache->endframe) + return 0; + + if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0) + return 0; if(pid->cache->flag & PTCACHE_DISK_CACHE) { char filename[MAX_PTCACHE_FILE]; @@ -2073,6 +2107,71 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra *endframe += (int)(offset+0.5f); } } + + /* verify cached_frames array is up to date */ + if(cache->cached_frames) { + if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { + MEM_freeN(cache->cached_frames); + cache->cached_frames = NULL; + } + } + + if(cache->cached_frames==NULL && cache->endframe > cache->startframe) { + int sta=cache->startframe; + int end=cache->endframe; + + cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); + + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[MAX_PTCACHE_PATH]; + char filename[MAX_PTCACHE_FILE]; + char ext[MAX_PTCACHE_PATH]; + int len; /* store the length of the string */ + + ptcache_path(pid, path); + + len = BKE_ptcache_id_filename(pid, filename, (int)cfra, 0, 0); /* no path */ + + dir = opendir(path); + if (dir==NULL) + return; + + snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + /* read the number of the file */ + int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + if(frame >= sta && frame <= end) + cache->cached_frames[frame-sta] = 1; + } + } + } + } + closedir(dir); + } + else { + PTCacheMem *pm= pid->cache->mem_cache.first; + + pm= pid->cache->mem_cache.first; + + while(pm) { + if(pm->frame >= sta && pm->frame <= end) + cache->cached_frames[pm->frame-sta] = 1; + pm = pm->next; + } + } + } } int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) @@ -2293,6 +2392,8 @@ void BKE_ptcache_free(PointCache *cache) BKE_ptcache_free_mem(&cache->mem_cache); if(cache->edit && cache->free_edit) cache->free_edit(cache->edit); + if(cache->cached_frames) + MEM_freeN(cache->cached_frames); MEM_freeN(cache); } void BKE_ptcache_free_list(ListBase *ptcaches) @@ -2840,7 +2941,10 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - if(totframes && cache->totpoint) + /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ + if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) + sprintf(cache->info, "%i frames found!", totframes); + else if(totframes && cache->totpoint) sprintf(cache->info, "%i points found!", cache->totpoint); else sprintf(cache->info, "No valid data to read!"); diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 461cb075bb0..7b428661c6d 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2873,7 +2873,7 @@ static void init_speed_effect(Sequence *seq) v = (SpeedControlVars *)seq->effectdata; v->globalSpeed = 1.0; v->frameMap = 0; - v->flags = 0; + v->flags |= SEQ_SPEED_INTEGRATE; /* should be default behavior */ v->length = 0; } @@ -2936,9 +2936,8 @@ static void store_icu_yrange_speed(struct Sequence * seq, } void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) { - float ctime, div; int cfra; - float fallback_fac; + float fallback_fac = 1.0f; SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; FCurve *fcu= NULL; @@ -2955,7 +2954,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) /* XXX - new in 2.5x. should we use the animation system this way? * The fcurve is needed because many frames need evaluating at once - campbell */ - fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_fader", 0); + fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0); if (!v->frameMap || v->length != seq->len) { @@ -2966,17 +2965,12 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) v->frameMap = MEM_callocN(sizeof(float) * v->length, "speedcontrol frameMap"); } - - fallback_fac = 1.0; - /* if there is no fcurve, try to make retiming easy by stretching the - strip */ - if (!fcu && seq->seq1->enddisp != seq->seq1->start && seq->seq1->len != 0) { - fallback_fac = (float) seq->seq1->len / - (float) (seq->seq1->enddisp - seq->seq1->start); - } + /* if there is no fcurve, use value as simple multiplier */ + if (!fcu) + fallback_fac = seq->speed_fader; /* same as speed_factor in rna*/ - if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) { + if (v->flags & SEQ_SPEED_INTEGRATE) { float cursor = 0; float facf; @@ -2985,10 +2979,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) for (cfra = 1; cfra < v->length; cfra++) { if(fcu) { - ctime = seq->startdisp + cfra; - div = 1.0; - - facf = evaluate_fcurve(fcu, ctime/div); + facf = evaluate_fcurve(fcu, seq->startdisp + cfra); } else { facf = fallback_fac; } @@ -3010,19 +3001,16 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) for (cfra = 0; cfra < v->length; cfra++) { if(fcu) { - ctime = seq->startdisp + cfra; - div = 1.0; - - facf = evaluate_fcurve(fcu, ctime / div); - if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) { - facf *= v->length; - } + facf = evaluate_fcurve(fcu, seq->startdisp + cfra); + } else { + facf = fallback_fac; } - - if (!fcu) { - facf = (float) cfra * fallback_fac; + + if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) { + facf *= seq->seq1->len; } facf *= v->globalSpeed; + if (facf >= seq->seq1->len) { facf = seq->seq1->len - 1; } else { diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index d2d8d5a6e07..965ce9801d7 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -800,20 +800,25 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix static int get_lamp(Scene *scene, float *light) { Base *base_tmp = NULL; - for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) - { - if(base_tmp->object->type == OB_LAMP) - { - Lamp *la = (Lamp *)base_tmp->object->data; - - if(la->type == LA_LOCAL) - { - VECCOPY(light, base_tmp->object->obmat[3]); - return 1; - } - } - } - return 0; + int found_lamp = 0; + + // try to find a lamp, preferably local + for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) { + if(base_tmp->object->type == OB_LAMP) { + Lamp *la = base_tmp->object->data; + + if(la->type == LA_LOCAL) { + copy_v3_v3(light, base_tmp->object->obmat[3]); + return 1; + } + else if(!found_lamp) { + copy_v3_v3(light, base_tmp->object->obmat[3]); + found_lamp = 1; + } + } + } + + return found_lamp; } static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) @@ -1338,10 +1343,17 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM cache_wt = sds->point_cache[1]; BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd); - if(!smd->domain->fluid) + if(!smd->domain->fluid || framenr == startframe) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_validate(cache, framenr); + cache->flag &= ~PTCACHE_REDO_NEEDED; + BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED); + if(cache_wt) { + BKE_ptcache_validate(cache_wt, framenr); + cache_wt->flag &= ~PTCACHE_REDO_NEEDED; + } } if(framenr < startframe) @@ -1368,6 +1380,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM if(cache_result == PTCACHE_READ_EXACT) { BKE_ptcache_validate(cache, framenr); + smd->time = framenr; if(sds->wt) { @@ -1388,14 +1401,21 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM else return; } - - /* only calculate something when we advanced a frame */ - if(framenr == smd->time) + /* only calculate something when we advanced a single frame */ + else if(framenr != (int)smd->time+1) return; tstart(); smoke_calc_domain(scene, ob, smd); + + /* if on second frame, write cache for first frame */ + /* this needs to be done for smoke too so that pointcache works properly */ + if((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) { + BKE_ptcache_write_cache(&pid, startframe); + if(sds->wt) + BKE_ptcache_write_cache(&pid_wt, startframe); + } // set new time smd->time = scene->r.cfra; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 26392132038..5e95b19b64f 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -433,9 +433,11 @@ void sound_seek_scene(struct bContext *C) if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) { - // AUD_XXX TODO: fix scrubbing, it currently doesn't stop playing if(scene->audio.flag & AUDIO_SYNC) + { + AUD_seek(scene->sound_scene_handle, CFRA / FPS); AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS); + } else AUD_seek(scene->sound_scene_handle, CFRA / FPS); AUD_resume(scene->sound_scene_handle); diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 6cd207f628c..473c10d6ced 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -160,7 +160,7 @@ static int write_audio_frame(void) pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; if (av_interleaved_write_frame(outfile, &pkt) != 0) { - // XXX error("Error writing audio packet"); + fprintf(stderr, "Error writing audio packet!\n"); return -1; } return 0; @@ -290,7 +290,9 @@ static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports packet.data = video_buffer; packet.size = outsize; ret = av_interleaved_write_frame(outfile, &packet); - } else ret = 0; + } else { + ret = 0; + } if (ret != 0) { success= 0; @@ -778,6 +780,69 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report return 1; } +/** + * Writes any delayed frames in the encoder. This function is called before + * closing the encoder. + * + * <p> + * Since an encoder may use both past and future frames to predict + * inter-frames (H.264 B-frames, for example), it can output the frames + * in a different order from the one it was given. + * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write + * them in the order 1, 4, 2, 3 - first the two frames used for predition, + * and then the bidirectionally-predicted frames. What this means in practice + * is that the encoder may not immediately produce one output frame for each + * input frame. These delayed frames must be flushed before we close the + * stream. We do this by calling avcodec_encode_video with NULL for the last + * parameter. + * </p> + */ +void flush_ffmpeg(void) +{ + int outsize = 0; + int ret = 0; + + AVCodecContext* c = get_codec_from_stream(video_stream); + /* get the delayed frames */ + while (1) { + AVPacket packet; + av_init_packet(&packet); + + outsize = avcodec_encode_video(c, video_buffer, video_buffersize, NULL); + if (outsize < 0) { + fprintf(stderr, "Error encoding delayed frame %d\n", outsize); + break; + } + if (outsize == 0) { + break; + } + if (c->coded_frame->pts != AV_NOPTS_VALUE) { +#ifdef FFMPEG_CODEC_TIME_BASE + packet.pts = av_rescale_q(c->coded_frame->pts, + c->time_base, + video_stream->time_base); +#else + packet.pts = c->coded_frame->pts; +#endif + fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); + } else { + fprintf(stderr, "Video Frame PTS: not set\n"); + } + if (c->coded_frame->key_frame) { + packet.flags |= PKT_FLAG_KEY; + } + packet.stream_index = video_stream->index; + packet.data = video_buffer; + packet.size = outsize; + ret = av_interleaved_write_frame(outfile, &packet); + if (ret != 0) { + fprintf(stderr, "Error writing delayed frame %d\n", ret); + break; + } + } + avcodec_flush_buffers(get_codec_from_stream(video_stream)); +} + /* ********************************************************************** * public interface ********************************************************************** */ @@ -888,7 +953,6 @@ int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, return success; } - void end_ffmpeg(void) { int i; @@ -905,6 +969,11 @@ void end_ffmpeg(void) audio_mixdown_device = 0; } + if (video_stream && get_codec_from_stream(video_stream)) { + fprintf(stderr, "Flushing delayed frames...\n"); + flush_ffmpeg (); + } + if (outfile) { av_write_trailer(outfile); } @@ -913,8 +982,8 @@ void end_ffmpeg(void) if (video_stream && get_codec_from_stream(video_stream)) { avcodec_close(get_codec_from_stream(video_stream)); - video_stream = 0; printf("zero video stream %p\n", video_stream); + video_stream = 0; } @@ -1195,20 +1264,47 @@ void ffmpeg_set_preset(RenderData *rd, int preset) rd->ffcodecdata.mux_packet_size = 2048; rd->ffcodecdata.mux_rate = 10080000; + /* + * All options here are for x264, but must be set via ffmpeg. + * The names are therefore different - Search for "x264 to FFmpeg option mapping" + * to get a list. + */ + + /* + * Use CABAC coder. Using "coder:1", which should be equivalent, + * crashes Blender for some reason. Either way - this is no big deal. + */ ffmpeg_property_add_string(rd, "video", "coder:vlc"); + + /* + * The other options were taken from the libx264-default.preset + * included in the ffmpeg distribution. + */ ffmpeg_property_add_string(rd, "video", "flags:loop"); ffmpeg_property_add_string(rd, "video", "cmp:chroma"); ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); ffmpeg_property_add_string(rd, "video", "me:hex"); - ffmpeg_property_add_string(rd, "video", "subq:5"); + ffmpeg_property_add_string(rd, "video", "subq:6"); ffmpeg_property_add_string(rd, "video", "me_range:16"); + ffmpeg_property_add_string(rd, "video", "qdiff:4"); ffmpeg_property_add_string(rd, "video", "keyint_min:25"); ffmpeg_property_add_string(rd, "video", "sc_threshold:40"); ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71"); ffmpeg_property_add_string(rd, "video", "b_strategy:1"); - + ffmpeg_property_add_string(rd, "video", "bf:3"); + ffmpeg_property_add_string(rd, "video", "refs:2"); + ffmpeg_property_add_string(rd, "video", "qcomp:0.6"); + ffmpeg_property_add_string(rd, "video", "directpred:3"); + ffmpeg_property_add_string(rd, "video", "trellis:0"); + ffmpeg_property_add_string(rd, "video", "flags2:wpred"); + ffmpeg_property_add_string(rd, "video", "flags2:dct8x8"); + ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); + ffmpeg_property_add_string(rd, "video", "wpredp:2"); + + // This makes x264 output lossless. Will be a separate option later. + //ffmpeg_property_add_string(rd, "video", "cqp:0"); break; case FFMPEG_PRESET_THEORA: |