From 93beb0b85a4a0e301d9bfae9edee1fe7bdabba12 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 27 Oct 2009 19:53:34 +0000 Subject: Commit of the sculpt patch (#19672). Further development will be in this branch until we merge to trunk. --- source/blender/blenkernel/BKE_DerivedMesh.h | 2 +- source/blender/blenkernel/BKE_paint.h | 7 +- source/blender/blenkernel/intern/cdderivedmesh.c | 91 +++++++++++++++++++++++- source/blender/blenkernel/intern/object.c | 10 ++- source/blender/blenkernel/intern/subsurf_ccg.c | 2 +- 5 files changed, 104 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 076747cb845..75d9ae7f360 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -204,7 +204,7 @@ struct DerivedMesh { * * Also called for *final* editmode DerivedMeshes */ - void (*drawFacesSolid)(DerivedMesh *dm, + void (*drawFacesSolid)(DerivedMesh *dm, void *tree, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)); /* Draw all faces diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index ba42aca1872..558659b520f 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -34,6 +34,7 @@ struct MultireModifierData; struct MVert; struct Object; struct Paint; +struct PBVH; struct Scene; struct StrokeCache; @@ -76,8 +77,10 @@ typedef struct SculptSession { /* Used temporarily per-stroke */ float *vertexcosnos; - ListBase damaged_rects; - ListBase damaged_verts; + + /* Partial redraw */ + struct PBVH *tree; + int partial_redraw; /* Used to cache the render of the active texture */ unsigned int texcache_side, *texcache, texcache_actual; diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index e38bb00fe8d..6ae1057767d 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -49,7 +49,7 @@ #include "BLI_blenlib.h" #include "BLI_edgehash.h" #include "BLI_editVert.h" -#include "BLI_ghash.h" +#include "BLI_pbvh.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -360,7 +360,68 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) } } -static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) +static int nodes_drawn = 0; +static int is_partial = 0; +/* XXX: Just a temporary replacement for the real drawing code */ +static void draw_partial_cb(const int *face_indices, + const int *vert_indices, + int totface, int totvert, void *data_v) +{ + /* XXX: Just some quick code to show leaf nodes in different colors */ + /*float col[3]; int i; + if(is_partial) { + col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6; + } + else { + srand((long long)data_v); + for(i = 0; i < 3; ++i) + col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7; + } + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); + + glColor3f(1, 0, 0);*/ + GPU_draw_buffers(data_v); + ++nodes_drawn; +} + +int find_all(float bb_min[3], float bb_max[3], void *data) +{ + return 1; +} + +/* Adapted from: + http://www.gamedev.net/community/forums/topic.asp?topic_id=512123 + Returns true if the AABB is at least partially within the frustum + (ok, not a real frustum), false otherwise. +*/ +int planes_contain_AABB(float bb_min[3], float bb_max[3], void *data) +{ + float (*planes)[4] = data; + int i, axis; + float vmin[3], vmax[3]; + + for(i = 0; i < 4; ++i) { + for(axis = 0; axis < 3; ++axis) { + if(planes[i][axis] > 0) { + vmin[axis] = bb_min[axis]; + vmax[axis] = bb_max[axis]; + } + else { + vmin[axis] = bb_max[axis]; + vmax[axis] = bb_min[axis]; + } + } + + if(Inpf(planes[i], vmin) + planes[i][3] > 0) + return 0; + } + + return 1; +} + +static void cdDM_drawFacesSolid(DerivedMesh *dm, void *tree, + float (*partial_redraw_planes)[4], + int (*setMaterial)(int, void *attribs)) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mvert = cddm->mvert; @@ -376,6 +437,32 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *a glVertex3fv(mvert[index].co); \ } + if(tree) { + BLI_pbvh_search(tree, BLI_pbvh_update_search_cb, + PBVH_NodeData, NULL, NULL, + PBVH_SEARCH_UPDATE); + + if(partial_redraw_planes) { + BLI_pbvh_search(tree, planes_contain_AABB, + partial_redraw_planes, + draw_partial_cb, PBVH_DrawData, + PBVH_SEARCH_MODIFIED); + } + else { + BLI_pbvh_search(tree, find_all, NULL, + draw_partial_cb, PBVH_DrawData, + PBVH_SEARCH_NORMAL); + + } + + is_partial = !!partial_redraw_planes; + + //printf("nodes drawn=%d\n", nodes_drawn); + nodes_drawn = 0; + + return; + } + if( GPU_buffer_legacy(dm) ) { DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" ); glBegin(glmode = GL_QUADS); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ba8d41f54bb..5c3419fb488 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -72,6 +72,8 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" +#include "BLI_ghash.h" +#include "BLI_pbvh.h" #include "BKE_utildefines.h" @@ -228,8 +230,6 @@ void free_sculptsession(SculptSession **ssp) { if(ssp && *ssp) { SculptSession *ss = *ssp; - if(ss->projverts) - MEM_freeN(ss->projverts); if(ss->fmap) MEM_freeN(ss->fmap); @@ -246,6 +246,12 @@ void free_sculptsession(SculptSession **ssp) if(ss->mesh_co_orig) MEM_freeN(ss->mesh_co_orig); + if(ss->tree) + BLI_pbvh_free(ss->tree); + + if(ss->face_normals) + MEM_freeN(ss->face_normals); + MEM_freeN(ss); *ssp = NULL; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 6e95fe7ebc7..7c83431ebd8 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1615,7 +1615,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) } /* Only used by non-editmesh types */ -static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { +static void ccgDM_drawFacesSolid(DerivedMesh *dm, void *tree, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); -- cgit v1.2.3 From 243c73e96e18c126227d43728e2d3639c9f7ee41 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 28 Oct 2009 06:06:05 +0000 Subject: Moved the PBVH from sculpt session to DerivedMesh/CDDM. * Multires sculpting appears to work now * PBVH gets recalculated in some cases where it shouldn't, haven't looked into this yet --- source/blender/blenkernel/BKE_DerivedMesh.h | 13 ++- source/blender/blenkernel/BKE_paint.h | 4 +- source/blender/blenkernel/intern/cdderivedmesh.c | 107 +++++++++++++++++++++-- source/blender/blenkernel/intern/object.c | 11 --- source/blender/blenkernel/intern/subsurf_ccg.c | 2 +- 5 files changed, 115 insertions(+), 22 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 75d9ae7f360..d9b0c4bc357 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -59,6 +59,8 @@ struct MCol; struct ColorBand; struct GPUVertexAttribs; struct GPUDrawObject; +struct ListBase; +struct PBVH; /* number of sub-elements each mesh element has (for interpolation) */ #define SUB_ELEMS_VERT 0 @@ -73,6 +75,7 @@ struct DerivedMesh { int needsFree; /* checked on ->release, is set to 0 for cached results */ int deformedOnly; /* set by modifier stack if only deformed from original */ BVHCache bvhCache; + struct GPUDrawObject *drawObject; /* Misc. Queries */ @@ -180,6 +183,14 @@ struct DerivedMesh { /* Get vertex normal, undefined if index is not valid */ void (*getVertNo)(DerivedMesh *dm, int index, float no_r[3]); + /* Get a map of vertices to faces + */ + struct ListBase *(*getFaceMap)(DerivedMesh *dm); + + /* Get the BVH used for paint modes + */ + struct PBVH *(*getPBVH)(DerivedMesh *dm); + /* Drawing Operations */ /* Draw all vertices as bgl points (no options) */ @@ -204,7 +215,7 @@ struct DerivedMesh { * * Also called for *final* editmode DerivedMeshes */ - void (*drawFacesSolid)(DerivedMesh *dm, void *tree, float (*partial_redraw_planes)[4], + void (*drawFacesSolid)(DerivedMesh *dm, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)); /* Draw all faces diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 558659b520f..5bca174628d 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -69,17 +69,15 @@ typedef struct SculptSession { struct MFace *mface; int totvert, totface; float *face_normals; + struct PBVH *tree; /* Mesh connectivity */ struct ListBase *fmap; - struct IndexNode *fmap_mem; - int fmap_size; /* Used temporarily per-stroke */ float *vertexcosnos; /* Partial redraw */ - struct PBVH *tree; int partial_redraw; /* Used to cache the render of the active texture */ diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 6ae1057767d..66e09022ff5 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -77,6 +77,12 @@ typedef struct { MVert *mvert; MEdge *medge; MFace *mface; + + /* Cached */ + struct PBVH *pbvh; + /* Mesh connectivity */ + struct ListBase *fmap; + struct IndexNode *fmap_mem; } CDDerivedMesh; /**************** DerivedMesh interface functions ****************/ @@ -171,6 +177,82 @@ static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3]) no_r[2] = no[2]/32767.f; } +/* Updates all the face and vertex normals in a node + + Note: the correctness of some vertex normals will be a little + off, not sure if this will be noticeable or not */ +static void update_node_normals(const int *face_indices, + const int *vert_indices, + int totface, int totvert, void *data) +{ + DerivedMesh *dm = data; + CDDerivedMesh *cddm = data; + float (*face_nors)[3]; + int i; + + /* make a face normal layer if not present */ + face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); + if(!face_nors) + face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, + NULL, dm->numFaceData); + + /* Update face normals */ + for(i = 0; i < totface; ++i) { + MFace *f = cddm->mface + face_indices[i]; + float *fn = face_nors[face_indices[i]]; + + if(f->v4) + CalcNormFloat4(cddm->mvert[f->v1].co, cddm->mvert[f->v2].co, + cddm->mvert[f->v3].co, cddm->mvert[f->v4].co, fn); + else + CalcNormFloat(cddm->mvert[f->v1].co, cddm->mvert[f->v2].co, + cddm->mvert[f->v3].co, fn); + } + + /* Update vertex normals */ + for(i = 0; i < totvert; ++i) { + const int v = vert_indices[i]; + float no[3] = {0,0,0}; + IndexNode *face; + + for(face = cddm->fmap[v].first; face; face = face->next) + VecAddf(no, no, face_nors[face->index]); + + Normalize(no); + + cddm->mvert[v].no[0] = no[0] * 32767; + cddm->mvert[v].no[1] = no[1] * 32767; + cddm->mvert[v].no[2] = no[2] * 32767; + } +} + +static ListBase *cdDM_getFaceMap(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*) dm; + + if(!cddm->fmap) { + create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, cddm->mface, + dm->getNumVerts(dm), dm->getNumFaces(dm)); + printf("rebuild fmap\n"); + } + + return cddm->fmap; +} + +static struct PBVH *cdDM_getPBVH(DerivedMesh *dm) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*) dm; + + if(!cddm->pbvh) { + cddm->pbvh = BLI_pbvh_new(update_node_normals, cddm); + BLI_pbvh_build(cddm->pbvh, cddm->mface, cddm->mvert, + dm->getNumFaces(dm), dm->getNumVerts(dm)); + printf("rebuild pbvh\n"); + } + + return cddm->pbvh; +} + static void cdDM_drawVerts(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -419,7 +501,7 @@ int planes_contain_AABB(float bb_min[3], float bb_max[3], void *data) return 1; } -static void cdDM_drawFacesSolid(DerivedMesh *dm, void *tree, +static void cdDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)) { @@ -437,19 +519,19 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, void *tree, glVertex3fv(mvert[index].co); \ } - if(tree) { - BLI_pbvh_search(tree, BLI_pbvh_update_search_cb, + if(cddm->pbvh) { + BLI_pbvh_search(cddm->pbvh, BLI_pbvh_update_search_cb, PBVH_NodeData, NULL, NULL, PBVH_SEARCH_UPDATE); if(partial_redraw_planes) { - BLI_pbvh_search(tree, planes_contain_AABB, + BLI_pbvh_search(cddm->pbvh, planes_contain_AABB, partial_redraw_planes, draw_partial_cb, PBVH_DrawData, PBVH_SEARCH_MODIFIED); } else { - BLI_pbvh_search(tree, find_all, NULL, + BLI_pbvh_search(cddm->pbvh, find_all, NULL, draw_partial_cb, PBVH_DrawData, PBVH_SEARCH_NORMAL); @@ -1376,12 +1458,21 @@ static void cdDM_foreachMappedFaceCenter( } } +static void cdDM_free_internal(CDDerivedMesh *cddm) +{ + if(cddm->pbvh) BLI_pbvh_free(cddm->pbvh); + if(cddm->fmap) MEM_freeN(cddm->fmap); + if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem); +} + static void cdDM_release(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*)dm; - if (DM_release(dm)) + if (DM_release(dm)) { + cdDM_free_internal(cddm); MEM_freeN(cddm); + } } /**************** CDDM interface functions ****************/ @@ -1416,6 +1507,9 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->getVertCo = cdDM_getVertCo; dm->getVertNo = cdDM_getVertNo; + dm->getPBVH = cdDM_getPBVH; + dm->getFaceMap = cdDM_getFaceMap; + dm->drawVerts = cdDM_drawVerts; dm->drawUVEdges = cdDM_drawUVEdges; @@ -1901,6 +1995,7 @@ static void MultiresDM_release(DerivedMesh *dm) } if(DM_release(dm)) { + cdDM_free_internal(&mrdm->cddm); MEM_freeN(mrdm->subco); MEM_freeN(mrdm->orco); if(mrdm->vert_face_map) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 5c3419fb488..c1b9634e5ec 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -72,8 +72,6 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" -#include "BLI_ghash.h" -#include "BLI_pbvh.h" #include "BKE_utildefines.h" @@ -231,12 +229,6 @@ void free_sculptsession(SculptSession **ssp) if(ssp && *ssp) { SculptSession *ss = *ssp; - if(ss->fmap) - MEM_freeN(ss->fmap); - - if(ss->fmap_mem) - MEM_freeN(ss->fmap_mem); - if(ss->texcache) MEM_freeN(ss->texcache); @@ -246,9 +238,6 @@ void free_sculptsession(SculptSession **ssp) if(ss->mesh_co_orig) MEM_freeN(ss->mesh_co_orig); - if(ss->tree) - BLI_pbvh_free(ss->tree); - if(ss->face_normals) MEM_freeN(ss->face_normals); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 7c83431ebd8..1482bd75ff2 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1615,7 +1615,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) } /* Only used by non-editmesh types */ -static void ccgDM_drawFacesSolid(DerivedMesh *dm, void *tree, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)) { +static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); -- cgit v1.2.3 From 3078c806358c4c802e0d2df66a2b9a13471128c1 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 2 Nov 2009 18:47:03 +0000 Subject: Sculpt: Multithreading & PBVH Changes * Sculpting, normal update and bounding box code is now multithreaded using OpenMP. * Fix a number of update issues: normals on node boundaries, outdated bounding boxes, partial redraw, .. . There's probably still a few left, but should be better now. * Clicking once now does a single paint instead of two (was also painting on mouse up event). * Smooth shading now is enabled for the full mesh when the first face uses it (so it can be tested at least). Implementation Notes: * PBVH search can now be done either using a callback or bt gathering the nodes in an array. The latter makes multithreading with OpenMP easier. * Normals update code is now inside PBVH, was doing it per node before but should do all faces first and only then vertices. * Instead of using search modes + 1 modified flag, now nodes get 4 flags to indicate what needs to be updated for them, found that this makes it easier for me to understand the code and fix update bugs. * PBVHNode is now exposed as an abstract type, I think this makes it more clear what is happening than having it's data passed as part of callback functions. * Active_verts list was replaced by looping over nodes and the vertices inside them. However the grab brush still uses the active_verts system, will fix that later. * Some micro-optimizations, like avoiding a few multiplications/divisions, using local variables instead of pointers, or looping over fewer vertices to update the bounding boxes. --- source/blender/blenkernel/BKE_mesh.h | 1 + source/blender/blenkernel/intern/brush.c | 2 +- source/blender/blenkernel/intern/cdderivedmesh.c | 95 ++++++------------------ 3 files changed, 26 insertions(+), 72 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 09c1ab9f7d6..edb4e2cf2a9 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -47,6 +47,7 @@ struct Object; struct MTFace; struct VecNor; struct CustomData; +struct Scene; #ifdef __cplusplus extern "C" { diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 115d31b587c..8a4ffca8244 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -83,7 +83,7 @@ Brush *add_brush(const char *name) brush->clone.alpha= 0.5; brush->sculpt_tool = SCULPT_TOOL_DRAW; - brush_curve_preset(brush, BRUSH_PRESET_SHARP); + brush_curve_preset(brush, BRUSH_PRESET_SMOOTH); /* enable fake user by default */ brush->id.flag |= LIB_FAKEUSER; diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 66e09022ff5..b7234a86af9 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -177,55 +177,6 @@ static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3]) no_r[2] = no[2]/32767.f; } -/* Updates all the face and vertex normals in a node - - Note: the correctness of some vertex normals will be a little - off, not sure if this will be noticeable or not */ -static void update_node_normals(const int *face_indices, - const int *vert_indices, - int totface, int totvert, void *data) -{ - DerivedMesh *dm = data; - CDDerivedMesh *cddm = data; - float (*face_nors)[3]; - int i; - - /* make a face normal layer if not present */ - face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); - if(!face_nors) - face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, - NULL, dm->numFaceData); - - /* Update face normals */ - for(i = 0; i < totface; ++i) { - MFace *f = cddm->mface + face_indices[i]; - float *fn = face_nors[face_indices[i]]; - - if(f->v4) - CalcNormFloat4(cddm->mvert[f->v1].co, cddm->mvert[f->v2].co, - cddm->mvert[f->v3].co, cddm->mvert[f->v4].co, fn); - else - CalcNormFloat(cddm->mvert[f->v1].co, cddm->mvert[f->v2].co, - cddm->mvert[f->v3].co, fn); - } - - /* Update vertex normals */ - for(i = 0; i < totvert; ++i) { - const int v = vert_indices[i]; - float no[3] = {0,0,0}; - IndexNode *face; - - for(face = cddm->fmap[v].first; face; face = face->next) - VecAddf(no, no, face_nors[face->index]); - - Normalize(no); - - cddm->mvert[v].no[0] = no[0] * 32767; - cddm->mvert[v].no[1] = no[1] * 32767; - cddm->mvert[v].no[2] = no[2] * 32767; - } -} - static ListBase *cdDM_getFaceMap(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -244,7 +195,7 @@ static struct PBVH *cdDM_getPBVH(DerivedMesh *dm) CDDerivedMesh *cddm = (CDDerivedMesh*) dm; if(!cddm->pbvh) { - cddm->pbvh = BLI_pbvh_new(update_node_normals, cddm); + cddm->pbvh = BLI_pbvh_new(); BLI_pbvh_build(cddm->pbvh, cddm->mface, cddm->mvert, dm->getNumFaces(dm), dm->getNumVerts(dm)); printf("rebuild pbvh\n"); @@ -445,9 +396,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) static int nodes_drawn = 0; static int is_partial = 0; /* XXX: Just a temporary replacement for the real drawing code */ -static void draw_partial_cb(const int *face_indices, - const int *vert_indices, - int totface, int totvert, void *data_v) +static void draw_partial_cb(PBVHNode *node, void *data) { /* XXX: Just some quick code to show leaf nodes in different colors */ /*float col[3]; int i; @@ -462,21 +411,16 @@ static void draw_partial_cb(const int *face_indices, glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); glColor3f(1, 0, 0);*/ - GPU_draw_buffers(data_v); + GPU_draw_buffers(BLI_pbvh_node_get_draw_buffers(node)); ++nodes_drawn; } -int find_all(float bb_min[3], float bb_max[3], void *data) -{ - return 1; -} - /* Adapted from: http://www.gamedev.net/community/forums/topic.asp?topic_id=512123 Returns true if the AABB is at least partially within the frustum (ok, not a real frustum), false otherwise. */ -int planes_contain_AABB(float bb_min[3], float bb_max[3], void *data) +int planes_contain_AABB(PBVHNode *node, float bb_min[3], float bb_max[3], void *data) { float (*planes)[4] = data; int i, axis; @@ -520,21 +464,28 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, } if(cddm->pbvh) { - BLI_pbvh_search(cddm->pbvh, BLI_pbvh_update_search_cb, - PBVH_NodeData, NULL, NULL, - PBVH_SEARCH_UPDATE); + float (*face_nors)[3]; + + /* make a face normal layer if not present */ + face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); + if(!face_nors) + face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, + NULL, dm->numFaceData); + + BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals|PBVH_UpdateDrawBuffers, + face_nors, cdDM_getFaceMap(dm)); + + /* should be per face */ + if(dm->numFaceData && mface->flag & ME_SMOOTH) + glShadeModel(GL_SMOOTH); if(partial_redraw_planes) { - BLI_pbvh_search(cddm->pbvh, planes_contain_AABB, - partial_redraw_planes, - draw_partial_cb, PBVH_DrawData, - PBVH_SEARCH_MODIFIED); + BLI_pbvh_search_callback(cddm->pbvh, planes_contain_AABB, + partial_redraw_planes, draw_partial_cb, NULL); } else { - BLI_pbvh_search(cddm->pbvh, find_all, NULL, - draw_partial_cb, PBVH_DrawData, - PBVH_SEARCH_NORMAL); - + BLI_pbvh_search_callback(cddm->pbvh, NULL, NULL, + draw_partial_cb, NULL); } is_partial = !!partial_redraw_planes; @@ -542,6 +493,8 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, //printf("nodes drawn=%d\n", nodes_drawn); nodes_drawn = 0; + glShadeModel(GL_FLAT); + return; } -- cgit v1.2.3 From a4e91f8f1a820f0c6d063d601ff8042eca13a501 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 3 Nov 2009 22:50:09 +0000 Subject: Moved the show brush flag from sculpt to paint, and it now shows/hides the brush as expected. Also fixed some errors in the UI scripts. --- source/blender/blenkernel/intern/paint.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 3dfe3966e2f..5cc2190c088 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -175,6 +175,8 @@ void paint_init(Paint *p, const char col[3]) memcpy(p->paint_cursor_col, col, 3); p->paint_cursor_col[3] = 128; + + p->flags |= PAINT_SHOW_BRUSH; } void free_paint(Paint *paint) -- cgit v1.2.3 From b90d8ec0f454dfdd12f1284aabaff12b4cc93481 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 4 Nov 2009 20:23:48 +0000 Subject: Sculpt: derivedmesh no longer created CD_ORIGINDEX layer when there is no modifier, saving some memory. --- source/blender/blenkernel/intern/cdderivedmesh.c | 37 +++++++++++------------- source/blender/blenkernel/intern/constraint.c | 7 ++--- source/blender/blenkernel/intern/modifier.c | 2 +- source/blender/blenkernel/intern/object.c | 8 +++-- source/blender/blenkernel/intern/particle.c | 10 +++---- source/blender/blenkernel/intern/subsurf_ccg.c | 18 ++++++------ 6 files changed, 40 insertions(+), 42 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index b7234a86af9..c9c035ba6d1 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1017,7 +1017,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo continue; } else if(setDrawOptions) { - orig = index[a]; + orig = (index)? index[a]: a; if(orig == ORIGINDEX_NONE) continue; @@ -1514,17 +1514,12 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm"); DerivedMesh *dm = &cddm->dm; CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS); - int i, *index, alloctype; + int alloctype; - /* this does a referenced copy, the only new layers being ORIGINDEX, - * with an exception for fluidsim */ + /* this does a referenced copy, with an exception for fluidsim */ DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface); - CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totvert); - CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totedge); - CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface); - dm->deformedOnly = 1; alloctype= CD_REFERENCE; @@ -1540,18 +1535,6 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); - index = CustomData_get_layer(&dm->vertData, CD_ORIGINDEX); - for(i = 0; i < mesh->totvert; ++i, ++index) - *index = i; - - index = CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX); - for(i = 0; i < mesh->totedge; ++i, ++index) - *index = i; - - index = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX); - for(i = 0; i < mesh->totface; ++i, ++index) - *index = i; - return dm; } @@ -1696,6 +1679,13 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); + if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) + CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); + if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX)) + CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) + CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); + cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); @@ -2000,6 +1990,13 @@ DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts else DM_init(dm, numVerts, numEdges, numFaces); + if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) + CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); + if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX)) + CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) + CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); + CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index a319838a56f..a94fd8f6bd2 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -440,15 +440,14 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, f /* only continue if there's a valid DerivedMesh */ if (dm) { MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); - int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX); int numVerts = dm->getNumVerts(dm); int i, j, count = 0; float co[3], nor[3]; - /* check that dvert and index are valid pointers (just in case) */ - if (dvert && index) { + /* check that dvert is a valid pointers (just in case) */ + if (dvert) { /* get the average of all verts with that are in the vertex-group */ - for (i = 0; i < numVerts; i++, index++) { + for (i = 0; i < numVerts; i++) { for (j = 0; j < dvert[i].totweight; j++) { /* does this vertex belong to nominated vertex group? */ if (dvert[i].dw[j].def_nr == dgroup) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index a445b6986f6..639797564cc 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5695,7 +5695,7 @@ static void hookModifier_deformVerts( /* if DerivedMesh is present and has original index data, * use it */ - if(dm && dm->getVertData(dm, 0, CD_ORIGINDEX)) { + if(dm && dm->getVertDataArray(dm, CD_ORIGINDEX)) { int j; int orig_index; for(j = 0; j < numVerts; ++j) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index c1b9634e5ec..7ed120c3cfb 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1781,13 +1781,15 @@ static void give_parvert(Object *par, int nr, float *vec) DerivedMesh *dm = par->derivedFinal; if(dm) { - int i, count = 0, numVerts = dm->getNumVerts(dm); + int i, count = 0, vindex, numVerts = dm->getNumVerts(dm); int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX); float co[3]; /* get the average of all verts with (original index == nr) */ - for(i = 0; i < numVerts; ++i, ++index) { - if(*index == nr) { + for(i = 0; i < numVerts; ++i) { + vindex= (index)? *index: i; + + if(vindex == nr) { dm->getVertCo(dm, i, co); VecAddf(vec, vec, co); count++; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 43a624b3013..6bd2a03a628 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -790,7 +790,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) totface= dm->getNumFaces(dm); totorigface= me->totface; - if(totface == 0 || totorigface == 0 || origindex == NULL) + if(totface == 0 || totorigface == 0) return tot; facearea= MEM_callocN(sizeof(float)*totorigface, "SimplifyFaceArea"); @@ -807,14 +807,14 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) /* compute number of children per original face */ for(a=0; aindex[a]]; + b= (origindex)? origindex[ctx->index[a]]: ctx->index[a]; if(b != -1) elems[b].totchild++; } /* compute areas and centers of original faces */ for(mf=mface, a=0; av1].co); @@ -910,7 +910,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) skipped= 0; for(a=0, newtot=0; aindex[a]]; + b= (origindex)? origindex[ctx->index[a]]: ctx->index[a]; if(b != -1) { if(elems[b].curchild++ < ceil(elems[b].lambda*elems[b].totchild)) { ctx->index[newtot]= ctx->index[a]; @@ -943,7 +943,7 @@ int psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float if(!data->dosimplify) return 0; - b= data->origindex[cpa->num]; + b= (data->origindex)? data->origindex[cpa->num]: cpa->num; if(b == -1) return 0; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 1482bd75ff2..125c8a0c464 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -546,7 +546,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, // load verts faceBase = i = 0; mvert = CDDM_get_verts(result); - origIndex = result->getVertData(result, 0, CD_ORIGINDEX); + origIndex = result->getVertDataArray(result, CD_ORIGINDEX); for(index = 0; index < totface; index++) { CCGFace *f = faceMap2[index]; @@ -663,7 +663,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, // load edges i = 0; med = CDDM_get_edges(result); - origIndex = result->getEdgeData(result, 0, CD_ORIGINDEX); + origIndex = result->getEdgeDataArray(result, CD_ORIGINDEX); for(index = 0; index < totface; index++) { CCGFace *f = faceMap2[index]; @@ -738,7 +738,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, // load faces i = 0; mf = CDDM_get_faces(result); - origIndex = result->getFaceData(result, 0, CD_ORIGINDEX); + origIndex = result->getFaceDataArray(result, CD_ORIGINDEX); for(index = 0; index < totface; index++) { CCGFace *f = faceMap2[index]; @@ -846,7 +846,7 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, mv = mvert; index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX); - for(i = 0; i < totvert; i++, mv++, index++) { + for(i = 0; i < totvert; i++, mv++) { CCGVert *v; if(vertexCos) { @@ -855,12 +855,12 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), mv->co, 0, &v); } - ((int*)ccgSubSurf_getVertUserData(ss, v))[1] = *index; + ((int*)ccgSubSurf_getVertUserData(ss, v))[1] = (index)? *index++: i; } me = medge; index = (int *)dm->getEdgeDataArray(dm, CD_ORIGINDEX); - for(i = 0; i < totedge; i++, me++, index++) { + for(i = 0; i < totedge; i++, me++) { CCGEdge *e; float crease; @@ -870,12 +870,12 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, ccgSubSurf_syncEdge(ss, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(me->v1), SET_INT_IN_POINTER(me->v2), crease, &e); - ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = *index; + ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index)? *index++: i; } mf = mface; index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX); - for (i = 0; i < totface; i++, mf++, index++) { + for (i = 0; i < totface; i++, mf++) { CCGFace *f; fVerts[0] = SET_INT_IN_POINTER(mf->v1); @@ -901,7 +901,7 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, return; } - ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = *index; + ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = (index)? *index++: i; } ccgSubSurf_processSync(ss); -- cgit v1.2.3 From 636fe9068094668dd4bfe28dd144b1217ec7e0c8 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 4 Nov 2009 20:36:38 +0000 Subject: Sculpt: updating normals now no longer uses the vert-face map, to save memory. The weak point now is the thread-safe atomic access to normals from multiple threads, did not seem to be a bottleneck in my tests but I don't really trust it to be fast. --- source/blender/blenkernel/intern/cdderivedmesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index c9c035ba6d1..5d671c79183 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -473,7 +473,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, NULL, dm->numFaceData); BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals|PBVH_UpdateDrawBuffers, - face_nors, cdDM_getFaceMap(dm)); + face_nors); /* should be per face */ if(dm->numFaceData && mface->flag & ME_SMOOTH) -- cgit v1.2.3 From 55611fb2e6ff42daf2b74b212e13ed5db04283a7 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 4 Nov 2009 20:40:15 +0000 Subject: Sculpt: don't create DM face normals in sculpt mode, only update them if they exist already, to save memory. --- source/blender/blenkernel/intern/cdderivedmesh.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 5d671c79183..7cc46d39158 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -464,13 +464,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, } if(cddm->pbvh) { - float (*face_nors)[3]; - - /* make a face normal layer if not present */ - face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); - if(!face_nors) - face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, - NULL, dm->numFaceData); + float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL); BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals|PBVH_UpdateDrawBuffers, face_nors); -- cgit v1.2.3 From 678d37fe4e2f68d57022fb210281031025150b0f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 4 Nov 2009 20:56:46 +0000 Subject: Sculpt: now uses it's own Undo stack like editmesh. The main advantage here is that it is able to store changes in the mesh more compact than global undo. It doesn't integrate well with multires yet, will tackle that when I start looking into multires, for now still focusing on sculpt on regular meshes. --- source/blender/blenkernel/BKE_paint.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 5bca174628d..ffb4e6ae743 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -70,6 +70,7 @@ typedef struct SculptSession { int totvert, totface; float *face_normals; struct PBVH *tree; + struct Object *ob; /* Mesh connectivity */ struct ListBase *fmap; -- cgit v1.2.3 From 68278f35e8ae7e6ca387695d752a907ade5f8c4e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 4 Nov 2009 21:10:28 +0000 Subject: Sculpt: tool updates for latest changes * Smooth: vert-face map is now only created when this tool is used, would be best to also avoid using it here to avoid a sudden increase in memory, but is not trivial. * Grab: now no longer uses active verts list and loops over nodes like other tools. * Layer: uses original coordinates from undo now to save memory when not using persistent layer. * Anchored: this option works again now, though is still quite slow as it loops over all verts/faces. Smooth, layer tools and the anchored option could still be improved to use less memory and/or work faster by only doing things per node. --- source/blender/blenkernel/BKE_paint.h | 2 +- source/blender/blenkernel/intern/object.c | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index ffb4e6ae743..2b4fb9d938d 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -85,7 +85,7 @@ typedef struct SculptSession { unsigned int texcache_side, *texcache, texcache_actual; /* Layer brush persistence between strokes */ - float (*mesh_co_orig)[3]; /* Copy of the mesh vertices' locations */ + float (*layer_co)[3]; /* Copy of the mesh vertices' locations */ float *layer_disps; /* Displacements for each vertex */ struct SculptStroke *stroke; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7ed120c3cfb..6f0749e0fcd 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -235,11 +235,8 @@ void free_sculptsession(SculptSession **ssp) if(ss->layer_disps) MEM_freeN(ss->layer_disps); - if(ss->mesh_co_orig) - MEM_freeN(ss->mesh_co_orig); - - if(ss->face_normals) - MEM_freeN(ss->face_normals); + if(ss->layer_co) + MEM_freeN(ss->layer_co); MEM_freeN(ss); -- cgit v1.2.3 From 132783328209f24873629113665f01b35364fdd0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 6 Nov 2009 16:46:35 +0000 Subject: Sculpt: WIP brush behavior changes * Draw/Inflate/Layer now keep working on the original mesh coordinates and normals from when the stroke started. This helps avoid the mesh blowing up, but can still be better. The old behavior is still available as "Accumulate" in the UI. * This requires some more memory usage for the BVH, would like to find a way to avoid that. * Smooth falloff is now the default. * Spacing is now enabled by default, with a value of 7.5. * Anchored now stores normals per node to save some memory. --- source/blender/blenkernel/intern/brush.c | 3 ++- source/blender/blenkernel/intern/cdderivedmesh.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 8a4ffca8244..b415e7b7b17 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -75,13 +75,14 @@ Brush *add_brush(const char *name) brush->rgb[2]= 1.0f; brush->alpha= 0.2f; brush->size= 25; - brush->spacing= 10.0f; + brush->spacing= 7.5f; brush->smooth_stroke_radius= 75; brush->smooth_stroke_factor= 0.9; brush->rate= 0.1f; brush->jitter= 0.0f; brush->clone.alpha= 0.5; brush->sculpt_tool = SCULPT_TOOL_DRAW; + brush->flag |= BRUSH_SPACE; brush_curve_preset(brush, BRUSH_PRESET_SMOOTH); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 7cc46d39158..7acf77c6f90 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -420,11 +420,13 @@ static void draw_partial_cb(PBVHNode *node, void *data) Returns true if the AABB is at least partially within the frustum (ok, not a real frustum), false otherwise. */ -int planes_contain_AABB(PBVHNode *node, float bb_min[3], float bb_max[3], void *data) +int planes_contain_AABB(PBVHNode *node, void *data) { float (*planes)[4] = data; int i, axis; - float vmin[3], vmax[3]; + float vmin[3], vmax[3], bb_min[3], bb_max[3]; + + BLI_pbvh_node_get_BB(node, bb_min, bb_max); for(i = 0; i < 4; ++i) { for(axis = 0; axis < 3; ++axis) { -- cgit v1.2.3 From b7d717cead9000c4600d71ed15fc10ebc103c591 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 23 Nov 2009 23:03:04 +0000 Subject: added a function to duplicate bPoseChannel's internal data - constraints, id-props etc. duplicate_pose_channel_data(), the code to do this was inline in editarmature.c duplicating editbones now duplicates posebone id-props also removed an if test for &channew->constraints since it will always be true. --- source/blender/blenkernel/BKE_action.h | 6 ++++- source/blender/blenkernel/intern/action.c | 42 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index e0b65c1996f..6029ce01794 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -140,7 +140,11 @@ void free_pose(struct bPose *pose); */ void copy_pose(struct bPose **dst, struct bPose *src, int copyconstraints); - +/** + * Copy the internal members of each pose channel including constraints + * and ID-Props, used when duplicating bones in editmode. + */ +void duplicate_pose_channel_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from); /** * Return a pointer to the pose channel of the given name diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index af3c4719e32..8fe80edabb9 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -640,6 +640,48 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan } } +/* makes copies of internal data, unlike copy_pose_channel_data which only + * copies the pose state. + * hint: use when copying bones in editmode (on returned value from verify_pose_channel) */ +void duplicate_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *pchan_from) +{ + /* copy transform locks */ + pchan->protectflag = pchan_from->protectflag; + + /* copy rotation mode */ + pchan->rotmode = pchan_from->rotmode; + + /* copy bone group */ + pchan->agrp_index= pchan_from->agrp_index; + + /* ik (dof) settings */ + pchan->ikflag = pchan_from->ikflag; + VECCOPY(pchan->limitmin, pchan_from->limitmin); + VECCOPY(pchan->limitmax, pchan_from->limitmax); + VECCOPY(pchan->stiffness, pchan_from->stiffness); + pchan->ikstretch= pchan_from->ikstretch; + pchan->ikrotweight= pchan_from->ikrotweight; + pchan->iklinweight= pchan_from->iklinweight; + + /* constraints */ + copy_constraints(&pchan->constraints, &pchan_from->constraints); + + /* id-properties */ + if(pchan->prop) { + /* unlikely but possible it exists */ + IDP_FreeProperty(pchan->prop); + MEM_freeN(pchan->prop); + pchan->prop= NULL; + } + if(pchan_from->prop) { + pchan->prop= IDP_CopyProperty(pchan_from->prop); + } + + /* custom shape */ + pchan->custom= pchan_from->custom; +} + + /* checks for IK constraint, Spline IK, and also for Follow-Path constraint. * can do more constraints flags later */ -- cgit v1.2.3 From d55ac4da2bae18c3623c8ffe656dc04330241c04 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Nov 2009 09:24:32 +0000 Subject: - added rna api function scene.update(), needed for rig generation to update driver deps - removed some warnings --- source/blender/blenkernel/BKE_constraint.h | 2 +- source/blender/blenkernel/intern/action.c | 1 - source/blender/blenkernel/intern/constraint.c | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index a8ccc84a7c3..e9110b99098 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -114,7 +114,7 @@ bConstraintTypeInfo *get_constraint_typeinfo(int type); void unique_constraint_name(struct bConstraint *con, struct ListBase *list); void free_constraints(struct ListBase *list); -void copy_constraints(struct ListBase *dst, struct ListBase *src); +void copy_constraints(struct ListBase *dst, const struct ListBase *src); void relink_constraints(struct ListBase *list); void free_constraint_data(struct bConstraint *con); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 8fe80edabb9..cb6fef0bc30 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -153,7 +153,6 @@ void make_local_action(bAction *act) } } - void free_action (bAction *act) { /* sanity check */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 46fdec90528..0f3213cbc5d 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3788,7 +3788,7 @@ void relink_constraints (ListBase *conlist) /* ......... */ /* duplicate all of the constraints in a constraint stack */ -void copy_constraints (ListBase *dst, ListBase *src) +void copy_constraints (ListBase *dst, const ListBase *src) { bConstraint *con, *srccon; -- cgit v1.2.3 From 89f9d3873d5290dd34d32de5c55415e43ee1fe6a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Nov 2009 14:03:29 +0000 Subject: bugfix [#19983] clicking onto normal input of a material node crash actually happened when clicking on any input --- source/blender/blenkernel/intern/node.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 4c378d25a8c..a27c3b6494b 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1675,7 +1675,9 @@ void ntreeSocketUseFlags(bNodeTree *ntree) /* tag all thats in use */ for(link= ntree->links.first; link; link= link->next) { - link->fromsock->flag |= SOCK_IN_USE; + + if(link->fromsock) // FIXME, see below + link->fromsock->flag |= SOCK_IN_USE; if(link->tosock) // FIXME This can be NULL, when dragging a new link in the UI, should probably copy the node tree for preview render - campbell link->tosock->flag |= SOCK_IN_USE; } -- cgit v1.2.3 From dcd1642121a14ddc3191399fb7120fe0a15437ce Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 24 Nov 2009 17:12:32 +0000 Subject: RNA api - EditBone was missing 'selected' - renamed 'selectable' to --> 'restrict_select', matching object mode. - renamed 'active_pchan' --> 'active_pose_bone' --- source/blender/blenkernel/BKE_context.h | 2 +- source/blender/blenkernel/intern/context.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 7f64538b10d..947ec914fa4 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -248,7 +248,7 @@ int CTX_data_selected_editable_bones(const bContext *C, ListBase *list); int CTX_data_visible_bones(const bContext *C, ListBase *list); int CTX_data_editable_bones(const bContext *C, ListBase *list); -struct bPoseChannel *CTX_data_active_pchan(const bContext *C); +struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C); int CTX_data_selected_pchans(const bContext *C, ListBase *list); int CTX_data_visible_pchans(const bContext *C, ListBase *list); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 21549f6b147..164e7a23d92 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -878,9 +878,9 @@ int CTX_data_editable_bones(const bContext *C, ListBase *list) return ctx_data_collection_get(C, "editable_bones", list); } -struct bPoseChannel *CTX_data_active_pchan(const bContext *C) +struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C) { - return ctx_data_pointer_get(C, "active_pchan"); + return ctx_data_pointer_get(C, "active_pose_bone"); } int CTX_data_selected_pchans(const bContext *C, ListBase *list) -- cgit v1.2.3 From 802779eb2d266f6a1de717fe9e7dcadc9774a7d3 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 25 Nov 2009 09:25:58 +0000 Subject: Assorted fixes - compile + drivers: * Fixed a few compile warnings for scons+mingw * Driver variables are now added with the ID-type set to ID_OB (objects) by default since this is more convenient --- source/blender/blenkernel/intern/fcurve.c | 3 +++ source/blender/blenkernel/intern/sequence.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index c451168a005..e90fccf6b29 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -731,6 +731,9 @@ DriverTarget *driver_add_new_target (ChannelDriver *driver) dtar= MEM_callocN(sizeof(DriverTarget), "DriverTarget"); BLI_addtail(&driver->targets, dtar); + /* make the default ID-type ID_OB, since most driver targets refer to objects */ + dtar->idtype= ID_OB; + /* give the target a 'unique' name */ strcpy(dtar->name, "var"); BLI_uniquename(&driver->targets, dtar, "var", '_', offsetof(DriverTarget, name), 64); diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index 07969704521..1920e82b4ab 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -2007,7 +2007,7 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int } } } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions - Scene *sce= seq->scene, *oldsce= scene; + Scene *sce= seq->scene;// *oldsce= scene; Render *re; RenderResult rres; char scenename[64]; -- cgit v1.2.3 From 6c881a7a6d9a5168ebbc5aa5339ed4324aef2154 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 25 Nov 2009 12:00:31 +0000 Subject: AnimSys - Transform Locks + RNA: The Animation System now respects the Transform Locks too (i.e. lock x-location, etc.) when writing settings. This means that it is no longer necessary to set up "constant drivers" to make sure some values don't get accidentally animated. Internally, added a new callback for properties in RNA, which is responsible for checking if the item at some array-index is editable. This needs to be manually called for each place which uses rna to set settings for arrays (see the code changes in anim_sys.c for changes how to do this; the same thing needs to be done in the UI code too, and probably in py-api too) --- source/blender/blenkernel/intern/anim_sys.c | 36 +++++++++++++++++++---------- 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 5ebcec63cd4..a6f733708c7 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -697,20 +697,26 @@ static short animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_i switch (RNA_property_type(prop)) { case PROP_BOOLEAN: - if (RNA_property_array_length(&new_ptr, prop)) - RNA_property_boolean_set_index(&new_ptr, prop, array_index, (int)value); + if (RNA_property_array_length(&new_ptr, prop)) { + if (RNA_property_editable_index(&new_ptr, prop, array_index)) + RNA_property_boolean_set_index(&new_ptr, prop, array_index, (int)value); + } else RNA_property_boolean_set(&new_ptr, prop, (int)value); break; case PROP_INT: - if (RNA_property_array_length(&new_ptr, prop)) - RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); + if (RNA_property_array_length(&new_ptr, prop)){ + if (RNA_property_editable_index(&new_ptr, prop, array_index)) + RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); + } else RNA_property_int_set(&new_ptr, prop, (int)value); break; case PROP_FLOAT: - if (RNA_property_array_length(&new_ptr, prop)) - RNA_property_float_set_index(&new_ptr, prop, array_index, value); + if (RNA_property_array_length(&new_ptr, prop)) { + if (RNA_property_editable_index(&new_ptr, prop, array_index)) + RNA_property_float_set_index(&new_ptr, prop, array_index, value); + } else RNA_property_float_set(&new_ptr, prop, value); break; @@ -1434,20 +1440,26 @@ void nladata_flush_channels (ListBase *channels) switch (RNA_property_type(prop)) { case PROP_BOOLEAN: - if (RNA_property_array_length(ptr, prop)) - RNA_property_boolean_set_index(ptr, prop, array_index, (int)value); + if (RNA_property_array_length(ptr, prop)) { + if (RNA_property_editable_index(ptr, prop, array_index)) + RNA_property_boolean_set_index(ptr, prop, array_index, (int)value); + } else RNA_property_boolean_set(ptr, prop, (int)value); break; case PROP_INT: - if (RNA_property_array_length(ptr, prop)) - RNA_property_int_set_index(ptr, prop, array_index, (int)value); + if (RNA_property_array_length(ptr, prop)) { + if (RNA_property_editable_index(ptr, prop, array_index)) + RNA_property_int_set_index(ptr, prop, array_index, (int)value); + } else RNA_property_int_set(ptr, prop, (int)value); break; case PROP_FLOAT: - if (RNA_property_array_length(ptr, prop)) - RNA_property_float_set_index(ptr, prop, array_index, value); + if (RNA_property_array_length(ptr, prop)) { + if (RNA_property_editable_index(ptr, prop, array_index)) + RNA_property_float_set_index(ptr, prop, array_index, value); + } else RNA_property_float_set(ptr, prop, value); break; -- cgit v1.2.3 From 90cc7c8abd7b4c36002031edba8b75207fb98086 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 25 Nov 2009 12:27:21 +0000 Subject: Sculpt: CCGSubsurf new functions to update normals, update subdivision levels, copy coordinates from face grids, and stitch together face grids. --- source/blender/blenkernel/intern/CCGSubSurf.c | 1470 +++++++++++++++---------- source/blender/blenkernel/intern/CCGSubSurf.h | 5 + 2 files changed, 903 insertions(+), 572 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index cee032f364e..86595dea8fb 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -1130,6 +1130,643 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss) { return eCCGError_None; } +#define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset) +#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize) +static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, + CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF, + int numEffectedV, int numEffectedE, int numEffectedF) { + int i,ptrIdx; + int subdivLevels = ss->subdivLevels; + int lvl = ss->subdivLevels; + int edgeSize = 1 + (1<normalDataOffset; + int vertDataSize = ss->meshIFC.vertDataSize; + + for (ptrIdx=0; ptrIdxnumVerts; S++) { + for (y=0; ynumVerts)%f->numVerts]->flags&Edge_eEffected) + for (x=0; xflags&Edge_eEffected) + for (y=0; yflags&Vert_eEffected) + NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1)); + } + } + + for (ptrIdx=0; ptrIdxnumVerts; S++) { + int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected); + int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected); + int yLimitNext = xLimit; + int xLimitPrev = yLimit; + + for (y=0; yflags&Vert_eEffected) { + NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no); + } + } + + if (x==0 && y==0) { + int K; + + if (!yLimitNext || 1numVerts, 0, 1), no); + if (!xLimitPrev || 1numVerts)%f->numVerts, 1, 0), no); + + for (K=0; KnumVerts; K++) { + if (K!=S) { + NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no); + } + } + } else if (y==0) { + NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no); + if (!yLimitNext || xnumVerts, 0, x+1), no); + } else if (x==0) { + NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no); + if (!xLimitPrev || ynumVerts)%f->numVerts, y+1, 0), no); + } + } + } + } + } + // XXX can I reduce the number of normalisations here? + for (ptrIdx=0; ptrIdxnumFaces; i++) { + CCGFace *f = v->faces[i]; + NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1)); + } + + length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]); + + if (length>FLT_EPSILON) { + float invLength = 1.0f/length; + no[0] *= invLength; + no[1] *= invLength; + no[2] *= invLength; + } else { + NormZero(no); + } + + for (i=0; inumFaces; i++) { + CCGFace *f = v->faces[i]; + NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no); + } + } + for (ptrIdx=0; ptrIdxnumFaces) { + CCGFace *fLast = e->faces[e->numFaces-1]; + int x; + + for (i=0; inumFaces-1; i++) { + CCGFace *f = e->faces[i]; + + for (x=1; xnumFaces-1; i++) { + CCGFace *f = e->faces[i]; + + for (x=1; xnumVerts; S++) { + NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1), + FACE_getIFNo(f, lvl, S, gridSize-1, 0)); + } + } + for (ptrIdx=0; ptrIdxnumVerts; S++) { + for (y=0; yFLT_EPSILON) { + float invLength = 1.0f/length; + no[0] *= invLength; + no[1] *= invLength; + no[2] *= invLength; + } else { + NormZero(no); + } + } + } + } + } +} +#undef FACE_getIFNo + +#define VERT_getCo(v, lvl) _vert_getCo(v, lvl, vertDataSize) +#define EDGE_getCo(e, lvl, x) _edge_getCo(e, lvl, x, vertDataSize) +#define FACE_getIECo(f, lvl, S, x) _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize) +#define FACE_getIFCo(f, lvl, S, x, y) _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize) +static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, + CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF, + int numEffectedV, int numEffectedE, int numEffectedF, int curLvl) { + int subdivLevels = ss->subdivLevels; + int edgeSize = 1 + (1<q, *r = ss->r; + int vertDataSize = ss->meshIFC.vertDataSize; + + for (ptrIdx=0; ptrIdxnumVerts; S++) { + for (y=0; ynumVerts; S++) { + for (x=0; xnumVerts, 1, fx); + void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1); + void *co = FACE_getIECo(f, nextLvl, S, fx); + + VertDataAvg4(co, co0, co1, co2, co3); + } + + /* interior face interior edge midpoints + * o old interior face points + * o new interior face midpoints + */ + + /* vertical */ + for (x=1; x1.0) { + for (x=0; xnumFaces; i++) { + CCGFace *f = e->faces[i]; + VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize)); + numFaces++; + } + + VertDataMulN(q, 1.0f/(2.0f+numFaces)); + + VertDataCopy(r, co0); + VertDataAdd(r, co1); + VertDataMulN(r, 0.5); + + VertDataCopy(co, q); + VertDataSub(r, q); + VertDataMulN(r, sharpness); + VertDataAdd(co, r); + } + } + } + + /* exterior vertex shift + * o old vertex points (shifting) + * o old exterior edge points + * o new interior face midpoints + */ + for (ptrIdx=0; ptrIdxnumEdges; i++) { + CCGEdge *e = v->edges[i]; + float sharpness = EDGE_getSharpness(e, curLvl); + + if (seam && _edge_isBoundary(e)) + seamEdges++; + + if (sharpness!=0.0f) { + sharpCount++; + avgSharpness += sharpness; + } else { + allSharp = 0; + } + } + + if(sharpCount) { + avgSharpness /= sharpCount; + if (avgSharpness>1.0) { + avgSharpness = 1.0; + } + } + + if (seam && seamEdges < 2) + seam = 0; + + if (!v->numEdges) { + VertDataCopy(nCo, co); + } else if (_vert_isBoundary(v)) { + int numBoundary = 0; + + VertDataZero(r); + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[i]; + if (_edge_isBoundary(e)) { + VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); + numBoundary++; + } + } + + VertDataCopy(nCo, co); + VertDataMulN(nCo, 0.75); + VertDataMulN(r, 0.25f/numBoundary); + VertDataAdd(nCo, r); + } else { + int cornerIdx = (1 + (1<<(curLvl))) - 2; + int numEdges = 0, numFaces = 0; + + VertDataZero(q); + for (i=0; inumFaces; i++) { + CCGFace *f = v->faces[i]; + VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx)); + numFaces++; + } + VertDataMulN(q, 1.0f/numFaces); + VertDataZero(r); + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[i]; + VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize)); + numEdges++; + } + VertDataMulN(r, 1.0f/numEdges); + + VertDataCopy(nCo, co); + VertDataMulN(nCo, numEdges-2.0f); + VertDataAdd(nCo, q); + VertDataAdd(nCo, r); + VertDataMulN(nCo, 1.0f/numEdges); + } + + if ((sharpCount>1 && v->numFaces) || seam) { + VertDataZero(q); + + if (seam) { + avgSharpness = 1.0f; + sharpCount = seamEdges; + allSharp = 1; + } + + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[i]; + float sharpness = EDGE_getSharpness(e, curLvl); + + if (seam) { + if (_edge_isBoundary(e)) + VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); + } else if (sharpness != 0.0) { + VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); + } + } + + VertDataMulN(q, (float) 1/sharpCount); + + if (sharpCount!=2 || allSharp) { + // q = q + (co-q)*avgSharpness + VertDataCopy(r, co); + VertDataSub(r, q); + VertDataMulN(r, avgSharpness); + VertDataAdd(q, r); + } + + // r = co*.75 + q*.25 + VertDataCopy(r, co); + VertDataMulN(r, .75); + VertDataMulN(q, .25); + VertDataAdd(r, q); + + // nCo = nCo + (r-nCo)*avgSharpness + VertDataSub(r, nCo); + VertDataMulN(r, avgSharpness); + VertDataAdd(nCo, r); + } + } + + /* exterior edge interior shift + * o old exterior edge midpoints (shifting) + * o old exterior edge midpoints + * o new interior face midpoints + */ + for (ptrIdx=0; ptrIdx1.0) { + avgSharpness = 1.0; + } + } else { + sharpCount = 0; + avgSharpness = 0; + } + + if (_edge_isBoundary(e) && (!e->numFaces || sharpCount<2)) { + for (x=1; xnumFaces; i++) { + CCGFace *f = e->faces[i]; + VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize)); + VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize)); + + VertDataAdd(r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize)); + numFaces++; + } + VertDataMulN(q, 1.0/(numFaces*2.0f)); + VertDataMulN(r, 1.0/(2.0f + numFaces)); + + VertDataCopy(nCo, co); + VertDataMulN(nCo, (float) numFaces); + VertDataAdd(nCo, q); + VertDataAdd(nCo, r); + VertDataMulN(nCo, 1.0f/(2+numFaces)); + + if (sharpCount==2) { + VertDataCopy(q, co); + VertDataMulN(q, 6.0f); + VertDataAdd(q, EDGE_getCo(e, curLvl, x-1)); + VertDataAdd(q, EDGE_getCo(e, curLvl, x+1)); + VertDataMulN(q, 1/8.0f); + + VertDataSub(q, nCo); + VertDataMulN(q, avgSharpness); + VertDataAdd(nCo, q); + } + } + } + } + + for (ptrIdx=0; ptrIdxnumVerts; S++) { + VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1)); + } + VertDataMulN(q, 1.0f/f->numVerts); + VertDataZero(r); + for (S=0; SnumVerts; S++) { + VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1)); + } + VertDataMulN(r, 1.0f/f->numVerts); + + VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f); + VertDataAdd(FACE_getCenterData(f), q); + VertDataAdd(FACE_getCenterData(f), r); + VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts); + + for (S=0; SnumVerts; S++) { + /* interior face shift + * o old interior face point (shifting) + * o new interior edge midpoints + * o new interior face midpoints + */ + for (x=1; xnumVerts, 1, fx-1), + FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1), + FACE_getIFCo(f, nextLvl, S, fx+1, +1), + FACE_getIFCo(f, nextLvl, S, fx-1, +1)); + + VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1), + FACE_getIECo(f, nextLvl, S, fx+1), + FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx), + FACE_getIFCo(f, nextLvl, S, fx, 1)); + + VertDataCopy(nCo, co); + VertDataSub(nCo, q); + VertDataMulN(nCo, 0.25f); + VertDataAdd(nCo, r); + } + } + } + + /* copy down */ + edgeSize = 1 + (1<<(nextLvl)); + gridSize = 1 + (1<<((nextLvl)-1)); + cornerIdx = gridSize-1; + for (i=0; iv0, nextLvl)); + VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl)); + } + for (i=0; inumVerts; S++) { + CCGEdge *e = FACE_getEdges(f)[S]; + CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; + + VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f)); + VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f)); + VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl)); + VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx)); + for (x=1; xnumVerts, 0, x), co); + } + for (x=0; xsubdivLevels; int vertDataSize = ss->meshIFC.vertDataSize; - int i,ptrIdx,cornerIdx; - int S,x,y; - void *q = ss->q, *r = ss->r; + int i, j, ptrIdx, S; int curLvl, nextLvl; - int j; + void *q = ss->q, *r = ss->r; effectedV = CCGSUBSURF_alloc(ss, sizeof(*effectedV)*ss->vMap->numEntries); effectedE = CCGSUBSURF_alloc(ss, sizeof(*effectedE)*ss->eMap->numEntries); @@ -1172,10 +1807,6 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) { } } -#define VERT_getCo(v, lvl) _vert_getCo(v, lvl, vertDataSize) -#define EDGE_getCo(e, lvl, x) _edge_getCo(e, lvl, x, vertDataSize) -#define FACE_getIECo(f, lvl, S, x) _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize) -#define FACE_getIFCo(f, lvl, S, x, y) _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize) curLvl = 0; nextLvl = curLvl+1; @@ -1388,645 +2019,340 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) { } for (curLvl=1; curLvlcalcVertNormals) + ccgSubSurf__calcVertNormals(ss, + effectedV, effectedE, effectedF, + numEffectedV, numEffectedE, numEffectedF); - /* interior face midpoints - * o old interior face points - */ - for (S=0; SnumVerts; S++) { - for (y=0; yflags = 0; + } + for (ptrIdx=0; ptrIdxflags = 0; + } - /* interior edge midpoints - * o old interior edge points - * o new interior face midpoints - */ - for (S=0; SnumVerts; S++) { - for (x=0; xnumVerts, 1, fx); - void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1); - void *co = FACE_getIECo(f, nextLvl, S, fx); - - VertDataAvg4(co, co0, co1, co2, co3); - } + CCGSUBSURF_free(ss, effectedF); + CCGSUBSURF_free(ss, effectedE); + CCGSUBSURF_free(ss, effectedV); +} - /* interior face interior edge midpoints - * o old interior face points - * o new interior face midpoints - */ - - /* vertical */ - for (x=1; xfMap->numEntries); + num = 0; + for (i=0; ifMap->curSize; i++) { + CCGFace *f = (CCGFace*) ss->fMap->buckets[i]; + + for (; f; f = f->next) + array[num++] = f; } - /* exterior edge midpoints - * o old exterior edge points - * o new interior face midpoints - */ - for (ptrIdx=0; ptrIdx1.0) { - for (x=0; xnumFaces; i++) { - CCGFace *f = e->faces[i]; - VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize)); - numFaces++; - } + arrayV = CCGSUBSURF_alloc(ss, sizeof(*arrayV)*ss->vMap->numEntries); + arrayE = CCGSUBSURF_alloc(ss, sizeof(*arrayE)*ss->eMap->numEntries); + numV = numE = 0; - VertDataMulN(q, 1.0f/(2.0f+numFaces)); + for (i=0; iflags |= Face_eEffected; + } - VertDataCopy(r, co0); - VertDataAdd(r, co1); - VertDataMulN(r, 0.5); + for (i=0; ivMap->curSize; i++) { + CCGVert *v = (CCGVert*) ss->vMap->buckets[i]; - VertDataCopy(co, q); - VertDataSub(r, q); - VertDataMulN(r, sharpness); - VertDataAdd(co, r); - } + for (; v; v = v->next) { + for(j=0; jnumFaces; j++) + if(!(v->faces[j]->flags & Face_eEffected)) + break; + + if(j == v->numFaces) { + arrayV[numV++] = v; + v->flags |= Vert_eEffected; } } + } - /* exterior vertex shift - * o old vertex points (shifting) - * o old exterior edge points - * o new interior face midpoints - */ - for (ptrIdx=0; ptrIdxeMap->curSize; i++) { + CCGEdge *e = (CCGEdge*) ss->eMap->buckets[i]; - for (i=0; inumEdges; i++) { - CCGEdge *e = v->edges[i]; - float sharpness = EDGE_getSharpness(e, curLvl); + for (; e; e = e->next) { + for(j=0; jnumFaces; j++) + if(!(e->faces[j]->flags & Face_eEffected)) + break; + + if(j == e->numFaces) { + e->flags |= Edge_eEffected; + arrayE[numE++] = e; + } + } + } - if (seam && _edge_isBoundary(e)) - seamEdges++; + *verts = arrayV; + *numVerts = numV; + *edges = arrayE; + *numEdges = numE; +} - if (sharpness!=0.0f) { - sharpCount++; - avgSharpness += sharpness; - } else { - allSharp = 0; - } - } +/* copy face grid coordinates to other places */ +CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF) +{ + int i, S, x, gridSize, cornerIdx, subdivLevels; + int vertDataSize = ss->meshIFC.vertDataSize, freeF; - if(sharpCount) { - avgSharpness /= sharpCount; - if (avgSharpness>1.0) { - avgSharpness = 1.0; - } - } + subdivLevels = ss->subdivLevels; + lvl = (lvl)? lvl: subdivLevels; + gridSize = 1 + (1<<(lvl-1)); + cornerIdx = gridSize-1; - if (seam && seamEdges < 2) - seam = 0; + ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF); - if (!v->numEdges) { - VertDataCopy(nCo, co); - } else if (_vert_isBoundary(v)) { - int numBoundary = 0; + for (i=0; inumEdges; i++) { - CCGEdge *e = v->edges[i]; - if (_edge_isBoundary(e)) { - VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); - numBoundary++; - } - } + for (S=0; SnumVerts; S++) { + CCGEdge *e = FACE_getEdges(f)[S]; + CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; - VertDataCopy(nCo, co); - VertDataMulN(nCo, 0.75); - VertDataMulN(r, 0.25f/numBoundary); - VertDataAdd(nCo, r); - } else { - int cornerIdx = (1 + (1<<(curLvl))) - 2; - int numEdges = 0, numFaces = 0; + VertDataCopy(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0)); + VertDataCopy(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx)); - VertDataZero(q); - for (i=0; inumFaces; i++) { - CCGFace *f = v->faces[i]; - VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx)); - numFaces++; - } - VertDataMulN(q, 1.0f/numFaces); - VertDataZero(r); - for (i=0; inumEdges; i++) { - CCGEdge *e = v->edges[i]; - VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize)); - numEdges++; - } - VertDataMulN(r, 1.0f/numEdges); + for (x=0; x1 && v->numFaces) || seam) { - VertDataZero(q); - - if (seam) { - avgSharpness = 1.0f; - sharpCount = seamEdges; - allSharp = 1; - } + if(freeF) CCGSUBSURF_free(ss, effectedF); - for (i=0; inumEdges; i++) { - CCGEdge *e = v->edges[i]; - float sharpness = EDGE_getSharpness(e, curLvl); + return eCCGError_None; +} - if (seam) { - if (_edge_isBoundary(e)) - VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); - } else if (sharpness != 0.0) { - VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); - } - } +/* stitch together face grids, averaging coordinates at edges + and vertices, for multires displacements */ +CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF) +{ + CCGVert **effectedV; + CCGEdge **effectedE; + int numEffectedV, numEffectedE, freeF; + int i, S, x, gridSize, cornerIdx, subdivLevels, edgeSize; + int vertDataSize = ss->meshIFC.vertDataSize; - VertDataMulN(q, (float) 1/sharpCount); + subdivLevels = ss->subdivLevels; + lvl = (lvl)? lvl: subdivLevels; + gridSize = 1 + (1<<(lvl-1)); + edgeSize = 1 + (1<1.0) { - avgSharpness = 1.0; - } - } else { - sharpCount = 0; - avgSharpness = 0; - } + VertDataZero(FACE_getCenterData(f)); - if (_edge_isBoundary(e) && (!e->numFaces || sharpCount<2)) { - for (x=1; xnumFaces; i++) { - CCGFace *f = e->faces[i]; - VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize)); - VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize)); - - VertDataAdd(r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize)); - numFaces++; - } - VertDataMulN(q, 1.0/(numFaces*2.0f)); - VertDataMulN(r, 1.0/(2.0f + numFaces)); + for (S=0; SnumVerts; S++) + for (x=0; xnumVerts; S++) { + int prevS = (S+f->numVerts-1)%f->numVerts; + CCGEdge *e = FACE_getEdges(f)[S]; + CCGEdge *prevE = FACE_getEdges(f)[prevS]; - for (ptrIdx=0; ptrIdxnumVerts; S++) { - VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1)); - } - VertDataMulN(q, 1.0f/f->numVerts); - VertDataZero(r); - for (S=0; SnumVerts; S++) { - VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1)); + for (x=1; xnumVerts); - - VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f); - VertDataAdd(FACE_getCenterData(f), q); - VertDataAdd(FACE_getCenterData(f), r); - VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts); - - for (S=0; SnumVerts; S++) { - /* interior face shift - * o old interior face point (shifting) - * o new interior edge midpoints - * o new interior face midpoints - */ - for (x=1; xnumVerts, 1, fx-1), - FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1), - FACE_getIFCo(f, nextLvl, S, fx+1, +1), - FACE_getIFCo(f, nextLvl, S, fx-1, +1)); - VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1), - FACE_getIECo(f, nextLvl, S, fx+1), - FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx), - FACE_getIFCo(f, nextLvl, S, fx, 1)); - - VertDataCopy(nCo, co); - VertDataSub(nCo, q); - VertDataMulN(nCo, 0.25f); - VertDataAdd(nCo, r); - } + for (x=0; xv0, nextLvl)); - VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl)); - } - for (i=0; inumVerts; S++) { - CCGEdge *e = FACE_getEdges(f)[S]; - CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; - - VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f)); - VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f)); - VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl)); - VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx)); - for (x=1; xnumVerts, 0, x), co); - } - for (x=0; xnumFaces); } -#define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset) -#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize) - if (ss->calcVertNormals) { - int lvl = ss->subdivLevels; - int edgeSize = 1 + (1<normalDataOffset; + for (i=0; iv0, lvl)); + VertDataCopy(EDGE_getCo(e, lvl, edgeSize-1), VERT_getCo(e->v1, lvl)); - for (S=0; SnumVerts; S++) { - for (y=0; ynumVerts)%f->numVerts]->flags&Edge_eEffected) - for (x=0; xflags&Edge_eEffected) - for (y=0; yflags&Vert_eEffected) - NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1)); - } - } + for (x=1; xnumFaces); + } - for (ptrIdx=0; ptrIdxnumVerts; S++) { - int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected); - int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected); - int yLimitNext = xLimit; - int xLimitPrev = yLimit; - - for (y=0; yflags&Vert_eEffected) { - NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no); - } - } + VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts); - if (x==0 && y==0) { - int K; + for (S=0; SnumVerts; S++) + for (x=1; xnumVerts, 0, 1), no); - if (!xLimitPrev || 1numVerts)%f->numVerts, 1, 0), no); + for (S=0; SnumVerts; S++) { + int prevS = (S+f->numVerts-1)%f->numVerts; + CCGEdge *e = FACE_getEdges(f)[S]; + CCGEdge *prevE = FACE_getEdges(f)[prevS]; - for (K=0; KnumVerts; K++) { - if (K!=S) { - NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no); - } - } - } else if (y==0) { - NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no); - if (!yLimitNext || xnumVerts, 0, x+1), no); - } else if (x==0) { - NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no); - if (!xLimitPrev || ynumVerts)%f->numVerts, y+1, 0), no); - } - } - } + VertDataCopy(FACE_getIFCo(f, lvl, S, 0, 0), FACE_getCenterData(f)); + VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], lvl)); + + for (x=1; xflags = 0; + for (i=0; iflags = 0; + for (i=0; iflags = 0; - for (i=0; inumFaces; i++) { - CCGFace *f = v->faces[i]; - NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1)); - } + CCGSUBSURF_free(ss, effectedE); + CCGSUBSURF_free(ss, effectedV); + if(freeF) CCGSUBSURF_free(ss, effectedF); - length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]); + return eCCGError_None; +} - if (length>FLT_EPSILON) { - float invLength = 1.0f/length; - no[0] *= invLength; - no[1] *= invLength; - no[2] *= invLength; - } else { - NormZero(no); - } +/* update normals for specified faces */ +CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF) { + CCGVert **effectedV; + CCGEdge **effectedE; + int i, numEffectedV, numEffectedE, freeF; - for (i=0; inumFaces; i++) { - CCGFace *f = v->faces[i]; - NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no); - } - } - for (ptrIdx=0; ptrIdxnumFaces) { - CCGFace *fLast = e->faces[e->numFaces-1]; - int x; + if (ss->calcVertNormals) + ccgSubSurf__calcVertNormals(ss, + effectedV, effectedE, effectedF, + numEffectedV, numEffectedE, numEffectedF); - for (i=0; inumFaces-1; i++) { - CCGFace *f = e->faces[i]; + for (i=0; iflags = 0; + for (i=0; iflags = 0; + for (i=0; iflags = 0; - for (x=1; xnumFaces-1; i++) { - CCGFace *f = e->faces[i]; + return eCCGError_None; +} - for (x=1; xsubdivLevels; - for (S=0; SnumVerts; S++) { - NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1), - FACE_getIFNo(f, lvl, S, gridSize-1, 0)); - } - } - for (ptrIdx=0; ptrIdxnumVerts; S++) { - for (y=0; yFLT_EPSILON) { - float invLength = 1.0f/length; - no[0] *= invLength; - no[1] *= invLength; - no[2] *= invLength; - } else { - NormZero(no); - } - } - } - } - } - } -#undef FACE_getIFNo + ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF); + ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF, + &effectedV, &numEffectedV, &effectedE, &numEffectedE); - for (ptrIdx=0; ptrIdxflags = 0; - } - for (ptrIdx=0; ptrIdxflags = 0; + for (curLvl=lvl; curLvlflags = 0; + for (i=0; iflags = 0; + for (i=0; iflags = 0; - CCGSUBSURF_free(ss, effectedF); CCGSUBSURF_free(ss, effectedE); CCGSUBSURF_free(ss, effectedV); + if(freeF) CCGSUBSURF_free(ss, effectedF); + + return eCCGError_None; } +#undef VERT_getCo +#undef EDGE_getCo +#undef FACE_getIECo +#undef FACE_getIFCo + /*** External API accessor functions ***/ int ccgSubSurf_getNumVerts(CCGSubSurf *ss) { diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index fbd0aecc0a5..d51cf0128c3 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -59,6 +59,11 @@ CCGError ccgSubSurf_syncFaceDel (CCGSubSurf *ss, CCGFaceHDL fHDL); CCGError ccgSubSurf_processSync (CCGSubSurf *ss); +CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces); +CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **faces, int numFaces); +CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces); +CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces); + CCGError ccgSubSurf_setSubdivisionLevels (CCGSubSurf *ss, int subdivisionLevels); CCGError ccgSubSurf_setAllowEdgeCreation (CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData); -- cgit v1.2.3 From a1bf207be31f4bb578e920bc472cc3471a6554ca Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 25 Nov 2009 13:11:44 +0000 Subject: Sculpt: Subsurf * Now uses the CCG DerivedMesh also in object mode, used to be edit mode only. * Create CD_ORIGINDEX layer on demand, to save memory. * Removed ss_to_cdderivedmesh function, and instead create ccgdm and then convert that to cddm, to avoid code duplication. * Added and implement DerivedMesh interface functions to obtain face grids. * Store edge/face flags more memory efficient. * Export CCGDerivedMesh struct in BKE_subsurf.h --- source/blender/blenkernel/BKE_DerivedMesh.h | 18 +- source/blender/blenkernel/BKE_subsurf.h | 53 +- source/blender/blenkernel/intern/DerivedMesh.c | 2 +- source/blender/blenkernel/intern/cdderivedmesh.c | 17 +- source/blender/blenkernel/intern/multires.c | 4 +- source/blender/blenkernel/intern/particle_system.c | 7 +- source/blender/blenkernel/intern/subsurf_ccg.c | 961 +++++++++------------ 7 files changed, 488 insertions(+), 574 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index d9b0c4bc357..6bce7575556 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -67,6 +67,16 @@ struct PBVH; #define SUB_ELEMS_EDGE 2 #define SUB_ELEMS_FACE 4 +typedef struct DMGridData { + float co[3]; + float no[3]; +} DMGridData; + +typedef struct DMGridAdjacency { + int index[4]; + int rotation[4]; +} DMGridAdjacency; + typedef struct DerivedMesh DerivedMesh; struct DerivedMesh { /* Private DerivedMesh data, only for internal DerivedMesh use */ @@ -135,6 +145,12 @@ struct DerivedMesh { void *(*getEdgeDataArray)(DerivedMesh *dm, int type); void *(*getFaceDataArray)(DerivedMesh *dm, int type); + /* optional grid access for subsurf */ + int (*getNumGrids)(DerivedMesh *dm); + int (*getGridSize)(DerivedMesh *dm); + DMGridData **(*getGridData)(DerivedMesh *dm); + DMGridAdjacency *(*getGridAdjacency)(DerivedMesh *dm); + /* Iterate over each mapped vertex in the derived mesh, calling the * given function with the original vert and the mapped vert's new * coordinate and normal. For historical reasons the normal can be @@ -189,7 +205,7 @@ struct DerivedMesh { /* Get the BVH used for paint modes */ - struct PBVH *(*getPBVH)(DerivedMesh *dm); + struct PBVH *(*getPBVH)(struct Object *ob, DerivedMesh *dm); /* Drawing Operations */ diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index f6dc22f650a..7b8adb7cb8e 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -34,21 +34,60 @@ struct DerivedMesh; struct EditMesh; struct MultiresSubsurf; struct SubsurfModifierData; +struct _CCGSubsurf; +struct _CCGVert; +struct _CCGEdge; +struct _CCGFace; +struct PBVH; +struct DMGridData; +struct DMGridAdjacency; -struct DerivedMesh *subsurf_make_derived_from_derived( - struct DerivedMesh *dm, - struct SubsurfModifierData *smd, - int useRenderParams, float (*vertCos)[3], - int isFinalCalc, int editMode); +/**************************** External *****************************/ -struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( +struct DerivedMesh *subsurf_make_derived_from_derived( struct DerivedMesh *dm, struct SubsurfModifierData *smd, - struct MultiresSubsurf *ms, int useRenderParams, float (*vertCos)[3], int isFinalCalc, int editMode); void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]); +/**************************** Internal *****************************/ + +typedef struct CCGDerivedMesh { + DerivedMesh dm; + + struct _CCGSubSurf *ss; + int freeSS; + int drawInteriorEdges, useSubsurfUv; + + struct {int startVert; struct _CCGVert *vert;} *vertMap; + struct {int startVert; int startEdge; struct _CCGEdge *edge;} *edgeMap; + struct {int startVert; int startEdge; + int startFace; struct _CCGFace *face;} *faceMap; + + short *edgeFlags; + char *faceFlags; + + struct PBVH *pbvh; + + struct DMGridData **gridData; + struct DMGridAdjacency *gridAdjacency; + struct _CCGFace **gridFaces; + + struct { + struct MultiresModifierData *mmd; + int local_mmd; + + int lvl, totlvl; + float (*orco)[3]; + + Object *ob; + int modified; + + void (*update)(DerivedMesh*); + } multires; +} CCGDerivedMesh; + #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index f9abaa9da02..5a911fcb13b 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1886,7 +1886,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos mask &= ~CD_MASK_ORCO; DM_set_only_copy(orcodm, mask); - ndm = mti->applyModifier(md, ob, orcodm, useRenderParams, !inputVertexCos); + ndm = mti->applyModifier(md, ob, orcodm, useRenderParams, 0); if(ndm) { /* if the modifier returned a new dm, release the old one */ diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index a07965c2a58..e64d8a24934 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -184,21 +184,21 @@ static ListBase *cdDM_getFaceMap(DerivedMesh *dm) if(!cddm->fmap) { create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, cddm->mface, dm->getNumVerts(dm), dm->getNumFaces(dm)); - printf("rebuild fmap\n"); } return cddm->fmap; } -static struct PBVH *cdDM_getPBVH(DerivedMesh *dm) +static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; - if(!cddm->pbvh) { + if(!cddm->pbvh && ob->type == OB_MESH) { + Mesh *me= ob->data; + cddm->pbvh = BLI_pbvh_new(); - BLI_pbvh_build(cddm->pbvh, cddm->mface, cddm->mvert, - dm->getNumFaces(dm), dm->getNumVerts(dm)); - printf("rebuild pbvh\n"); + BLI_pbvh_build(cddm->pbvh, me->mface, me->mvert, + me->totface, me->totvert); } return cddm->pbvh; @@ -1627,6 +1627,11 @@ DerivedMesh *CDDM_copy(DerivedMesh *source) int numEdges = source->numEdgeData; int numFaces = source->numFaceData; + /* ensure these are created if they are made on demand */ + source->getVertDataArray(source, CD_ORIGINDEX); + source->getEdgeDataArray(source, CD_ORIGINDEX); + source->getFaceDataArray(source, CD_ORIGINDEX); + /* this initializes dm, and copies all non mvert/medge/mface layers */ DM_from_template(dm, source, numVerts, numEdges, numFaces); dm->deformedOnly = source->deformedOnly; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 47b2914b0f5..fc14afaf07f 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -193,7 +193,7 @@ static DerivedMesh *multires_subdisp_pre(DerivedMesh *mrdm, int distance, int si if(simple) smd.subdivType = ME_SIMPLE_SUBSURF; - final = subsurf_make_derived_from_derived_with_multires(mrdm, &smd, NULL, 0, NULL, 0, 0); + final = NULL; // XXX subsurf_make_derived_from_derived_with_multires(mrdm, &smd, NULL, 0, NULL, 0, 0); return final; } @@ -1247,7 +1247,7 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i smd.levels = smd.renderLevels = mmd->lvl - 1; smd.flags |= eSubsurfModifierFlag_SubsurfUv; - result = subsurf_make_derived_from_derived_with_multires(dm, &smd, &ms, useRenderParams, NULL, isFinalCalc, 0); + result = NULL; // XXX subsurf_make_derived_from_derived_with_multires(dm, &smd, &ms, useRenderParams, NULL, isFinalCalc, 0); for(i = 0; i < result->getNumVerts(result); ++i) MultiresDM_get_subco(result)[i] = CDDM_get_verts(result)[i]; multiresModifier_disp_run(result, MultiresDM_get_subco(result), 0); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 075c6f6207f..ffb35d5cf2f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -287,12 +287,12 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) if(psys->part->from == PART_FROM_VERT) { totdmelem= dm->getNumVerts(dm); totelem= me->totvert; - origindex= DM_get_vert_data_layer(dm, CD_ORIGINDEX); + origindex= dm->getVertDataArray(dm, CD_ORIGINDEX); } else { /* FROM_FACE/FROM_VOLUME */ totdmelem= dm->getNumFaces(dm); totelem= me->totface; - origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX); + origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX); } nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems"); @@ -948,7 +948,8 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, if(totpart==0) return 0; - if (!finaldm->deformedOnly && !CustomData_has_layer( &finaldm->faceData, CD_ORIGINDEX ) ) { + if (!finaldm->deformedOnly && !finaldm->getFaceDataArray(finaldm, CD_ORIGINDEX)) { + printf("Can't create particles with the current modifier stack, disable destructive modifiers\n"); // XXX error("Can't paint with the current modifier stack, disable destructive modifiers"); return 0; } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 7197437bfd4..e465d17f498 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -53,11 +53,12 @@ #include "BKE_subsurf.h" #include "BLI_blenlib.h" +#include "BLI_edgehash.h" #include "BLI_editVert.h" -#include "BLI_math.h" #include "BLI_linklist.h" +#include "BLI_math.h" #include "BLI_memarena.h" -#include "BLI_edgehash.h" +#include "BLI_pbvh.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -68,25 +69,6 @@ #include "CCGSubSurf.h" -typedef struct _VertData { - float co[3]; - float no[3]; -} VertData; - -struct CCGDerivedMesh { - DerivedMesh dm; - - CCGSubSurf *ss; - int drawInteriorEdges, useSubsurfUv; - - struct {int startVert; CCGVert *vert;} *vertMap; - struct {int startVert; int startEdge; CCGEdge *edge;} *edgeMap; - struct {int startVert; int startEdge; - int startFace; CCGFace *face;} *faceMap; -}; - -typedef struct CCGDerivedMesh CCGDerivedMesh; - static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v); static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e); static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f); @@ -136,7 +118,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAgin } else { ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8; } - ifc.vertDataSize = sizeof(VertData); + ifc.vertDataSize = sizeof(DMGridData); if (useArena) { CCGAllocatorIFC allocatorIFC; @@ -156,7 +138,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAgin ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8); } - ccgSubSurf_setCalcVertexNormals(ccgSS, 1, BLI_STRUCT_OFFSET(VertData, no)); + ccgSubSurf_setCalcVertexNormals(ccgSS, 1, BLI_STRUCT_OFFSET(DMGridData, no)); return ccgSS; } @@ -340,7 +322,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, if(!dmtface || !tface) return; - /* create a CCGSubsurf from uv's */ + /* create a CCGSubSurf from uv's */ uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 0, 1, 0); if(!ss_sync_from_uv(uvss, ss, dm, dmtface)) { @@ -348,7 +330,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, return; } - /* get some info from CCGSubsurf */ + /* get some info from CCGSubSurf */ totface = ccgSubSurf_getNumFaces(uvss); edgeSize = ccgSubSurf_getEdgeSize(uvss); gridSize = ccgSubSurf_getGridSize(uvss); @@ -372,7 +354,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int numVerts = ccgSubSurf_getFaceNumVerts(f); for (S=0; Sseam) { - flags |= ME_SEAM; - } - } else { - if (edgeIdx!=-1) { - MEdge *origMed = &medge[edgeIdx]; - - if (dlm) { - flags |= origMed->flag&~ME_EDGE_STEPINDEX; - } else { - flags |= (origMed->flag&ME_SEAM)|ME_EDGEDRAW|ME_EDGERENDER; - } - } - } - - return flags; -} -#endif - /* face weighting */ static void calc_ss_weights(int gridFaces, FaceVertWeight **qweight, FaceVertWeight **tweight) @@ -471,360 +422,6 @@ static void calc_ss_weights(int gridFaces, } } -static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, - int drawInteriorEdges, int useSubsurfUv, - DerivedMesh *dm, MultiresSubsurf *ms) -{ - DerivedMesh *result; - int edgeSize = ccgSubSurf_getEdgeSize(ss); - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - int edgeBase, faceBase; - int i, j, k, S, x, y, index; - CCGVertIterator *vi; - CCGEdgeIterator *ei; - CCGFaceIterator *fi; - CCGFace **faceMap2; - CCGEdge **edgeMap2; - CCGVert **vertMap2; - int totvert, totedge, totface; - MVert *mvert; - MEdge *med; - MFace *mf; - int *origIndex; - FaceVertWeight *qweight, *tweight; - - calc_ss_weights(gridFaces, &qweight, &tweight); - - /* vert map */ - totvert = ccgSubSurf_getNumVerts(ss); - vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap"); - vi = ccgSubSurf_getVertIterator(ss); - for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { - CCGVert *v = ccgVertIterator_getCurrent(vi); - - vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v; - } - ccgVertIterator_free(vi); - - totedge = ccgSubSurf_getNumEdges(ss); - edgeMap2 = MEM_mallocN(totedge*sizeof(*edgeMap2), "edgemap"); - ei = ccgSubSurf_getEdgeIterator(ss); - for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(ei); - - edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e; - } - - totface = ccgSubSurf_getNumFaces(ss); - faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap"); - fi = ccgSubSurf_getFaceIterator(ss); - for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(fi); - - faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))] = f; - } - ccgFaceIterator_free(fi); - - if(ms) { - result = MultiresDM_new(ms, dm, ccgSubSurf_getNumFinalVerts(ss), - ccgSubSurf_getNumFinalEdges(ss), - ccgSubSurf_getNumFinalFaces(ss)); - } - else { - if(dm) { - result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss), - ccgSubSurf_getNumFinalEdges(ss), - ccgSubSurf_getNumFinalFaces(ss)); - } else { - result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss), - ccgSubSurf_getNumFinalEdges(ss), - ccgSubSurf_getNumFinalFaces(ss)); - } - } - - // load verts - faceBase = i = 0; - mvert = CDDM_get_verts(result); - origIndex = result->getVertDataArray(result, CD_ORIGINDEX); - - for(index = 0; index < totface; index++) { - CCGFace *f = faceMap2[index]; - int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); - FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight; - int vertIdx[4]; - - for(S = 0; S < numVerts; S++) { - CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S); - - vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); - } - - DM_interp_vert_data(dm, result, vertIdx, weight[0][0], numVerts, i); - copy_v3_v3(mvert->co, ccgSubSurf_getFaceCenterData(f)); - *origIndex = ORIGINDEX_NONE; - ++mvert; - ++origIndex; - i++; - - for(S = 0; S < numVerts; S++) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; - - for(x = 1; x < gridFaces; x++) { - float w[4]; - w[prevS] = weight[x][0][0]; - w[S] = weight[x][0][1]; - w[nextS] = weight[x][0][2]; - w[otherS] = weight[x][0][3]; - DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i); - copy_v3_v3(mvert->co, - ccgSubSurf_getFaceGridEdgeData(ss, f, S, x)); - - *origIndex = ORIGINDEX_NONE; - ++mvert; - ++origIndex; - i++; - } - } - - for(S = 0; S < numVerts; S++) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; - - for(y = 1; y < gridFaces; y++) { - for(x = 1; x < gridFaces; x++) { - float w[4]; - w[prevS] = weight[y * gridFaces + x][0][0]; - w[S] = weight[y * gridFaces + x][0][1]; - w[nextS] = weight[y * gridFaces + x][0][2]; - w[otherS] = weight[y * gridFaces + x][0][3]; - DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i); - copy_v3_v3(mvert->co, - ccgSubSurf_getFaceGridData(ss, f, S, x, y)); - *origIndex = ORIGINDEX_NONE; - ++mvert; - ++origIndex; - i++; - } - } - } - - *((int*)ccgSubSurf_getFaceUserData(ss, f)) = faceBase; - faceBase += 1 + numVerts * ((gridSize-2) + (gridSize-2) * (gridSize-2)); - } - - edgeBase = i; - for(index = 0; index < totedge; index++) { - CCGEdge *e = edgeMap2[index]; - int x; - int vertIdx[2]; - - CCGVert *v; - v = ccgSubSurf_getEdgeVert0(e); - vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); - v = ccgSubSurf_getEdgeVert1(e); - vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); - - for(x = 1; x < edgeSize - 1; x++) { - float w[2]; - w[1] = (float) x / (edgeSize - 1); - w[0] = 1 - w[1]; - DM_interp_vert_data(dm, result, vertIdx, w, 2, i); - copy_v3_v3(mvert->co, ccgSubSurf_getEdgeData(ss, e, x)); - *origIndex = ORIGINDEX_NONE; - ++mvert; - ++origIndex; - i++; - } - - *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = edgeBase; - edgeBase += edgeSize-2; - } - - for(index = 0; index < totvert; index++) { - CCGVert *v = vertMap2[index]; - int vertIdx; - - vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); - - DM_copy_vert_data(dm, result, vertIdx, i, 1); - copy_v3_v3(mvert->co, ccgSubSurf_getVertData(ss, v)); - - *((int*)ccgSubSurf_getVertUserData(ss, v)) = i; - *origIndex = ccgDM_getVertMapIndex(ss, v); - ++mvert; - ++origIndex; - i++; - } - - // load edges - i = 0; - med = CDDM_get_edges(result); - origIndex = result->getEdgeDataArray(result, CD_ORIGINDEX); - - for(index = 0; index < totface; index++) { - CCGFace *f = faceMap2[index]; - int numVerts = ccgSubSurf_getFaceNumVerts(f); - - for(k = 0; k < numVerts; k++) { - for(x = 0; x < gridFaces; x++) { - if(drawInteriorEdges) med->flag = ME_EDGEDRAW | ME_EDGERENDER; - med->v1 = getFaceIndex(ss, f, k, x, 0, edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, k, x+1, 0, edgeSize, gridSize); - *origIndex = ORIGINDEX_NONE; - ++med; - ++origIndex; - i++; - } - - for(x = 1; x < gridFaces; x++) { - for(y = 0; y < gridFaces; y++) { - if(drawInteriorEdges) - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - med->v1 = getFaceIndex(ss, f, k, x, y, edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, k, x, y + 1, - edgeSize, gridSize); - *origIndex = ORIGINDEX_NONE; - ++med; - ++origIndex; - i++; - - if(drawInteriorEdges) - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - med->v1 = getFaceIndex(ss, f, k, y, x, edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, k, y + 1, x, - edgeSize, gridSize); - *origIndex = ORIGINDEX_NONE; - ++med; - ++origIndex; - i++; - } - } - } - } - - for(index = 0; index < totedge; index++) { - CCGEdge *e = edgeMap2[index]; - unsigned int flags = 0; - char bweight = 0; - int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e)); - - if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE; - - - if(edgeIdx != -1 && dm) { - MEdge origMed; - dm->getEdge(dm, edgeIdx, &origMed); - - flags |= origMed.flag; - bweight = origMed.bweight; - } - - for(x = 0; x < edgeSize - 1; x++) { - med->v1 = getEdgeIndex(ss, e, x, edgeSize); - med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); - med->flag = flags; - med->bweight = bweight; - *origIndex = ccgDM_getEdgeMapIndex(ss, e); - ++med; - ++origIndex; - i++; - } - } - - // load faces - i = 0; - mf = CDDM_get_faces(result); - origIndex = result->getFaceDataArray(result, CD_ORIGINDEX); - - for(index = 0; index < totface; index++) { - CCGFace *f = faceMap2[index]; - int numVerts = ccgSubSurf_getFaceNumVerts(f); - int mat_nr; - int flag; - int mapIndex = ccgDM_getFaceMapIndex(ss, f); - int faceIdx = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); - - if(!ssFromEditmesh) { - MFace origMFace; - dm->getFace(dm, faceIdx, &origMFace); - - mat_nr = origMFace.mat_nr; - flag = origMFace.flag; - } else { - EditFace *ef = ccgSubSurf_getFaceFaceHandle(ss, f); - mat_nr = ef->mat_nr; - flag = ef->flag; - } - - for(S = 0; S < numVerts; S++) { - FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight; - - for(y = 0; y < gridFaces; y++) { - for(x = 0; x < gridFaces; x++) { - mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0, - edgeSize, gridSize); - mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1, - edgeSize, gridSize); - mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1, - edgeSize, gridSize); - mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0, - edgeSize, gridSize); - mf->mat_nr = mat_nr; - mf->flag = flag; - - if(dm) { - int prevS = (S - 1 + numVerts) % numVerts; - int nextS = (S + 1) % numVerts; - int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; - FaceVertWeight w; - - for(j = 0; j < 4; ++j) { - w[j][prevS] = (*weight)[j][0]; - w[j][S] = (*weight)[j][1]; - w[j][nextS] = (*weight)[j][2]; - w[j][otherS] = (*weight)[j][3]; - } - - DM_interp_face_data(dm, result, &faceIdx, NULL, - &w, 1, i); - weight++; - } - - *origIndex = mapIndex; - ++mf; - ++origIndex; - i++; - } - } - } - } - - MEM_freeN(faceMap2); - MEM_freeN(edgeMap2); - MEM_freeN(vertMap2); - - MEM_freeN(tweight); - MEM_freeN(qweight); - - if(useSubsurfUv) { - CustomData *fdata = &result->faceData; - CustomData *dmfdata = &dm->faceData; - int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE); - int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE); - - for (i=0; iedgeMap[0].startEdge) / (edgeSize - 1); @@ -1121,7 +719,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) med->v1 = getEdgeIndex(ss, e, x, edgeSize); med->v2 = getEdgeIndex(ss, e, x+1, edgeSize); - edgeFlag = dm->getEdgeData(dm, edgeNum, CD_FLAGS); + edgeFlag = (ccgdm->edgeFlags)? &ccgdm->edgeFlags[i]: NULL; if(edgeFlag) flags |= (*edgeFlag & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER; @@ -1147,7 +745,7 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) int grid; int x, y; int lastface = ccgSubSurf_getNumFaces(ss) - 1; - char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS); + char *faceFlags = ccgdm->faceFlags; memset(mf, 0, sizeof(*mf)); @@ -1169,7 +767,7 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) mf->v3 = getFaceIndex(ss, f, grid, x+1, y+1, edgeSize, gridSize); mf->v4 = getFaceIndex(ss, f, grid, x+1, y+0, edgeSize, gridSize); - if(faceFlags) mf->flag = faceFlags[i*4]; + if(faceFlags) mf->flag = faceFlags[i*2]; else mf->flag = ME_SMOOTH; } @@ -1177,6 +775,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; + DMGridData *vd; int index; int totvert, totedge, totface; int gridSize = ccgSubSurf_getGridSize(ss); @@ -1188,20 +787,25 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) CCGFace *f = ccgdm->faceMap[index].face; int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); - copy_v3_v3(mvert[i++].co, ccgSubSurf_getFaceCenterData(f)); + vd= ccgSubSurf_getFaceCenterData(f); + copy_v3_v3(mvert[i].co, vd->co); + normal_float_to_short_v3(mvert[i].no, vd->no); + i++; for(S = 0; S < numVerts; S++) { - for(x = 1; x < gridSize - 1; x++) { - copy_v3_v3(mvert[i++].co, - ccgSubSurf_getFaceGridEdgeData(ss, f, S, x)); + for(x = 1; x < gridSize - 1; x++, i++) { + vd= ccgSubSurf_getFaceGridEdgeData(ss, f, S, x); + copy_v3_v3(mvert[i].co, vd->co); + normal_float_to_short_v3(mvert[i].no, vd->no); } } for(S = 0; S < numVerts; S++) { for(y = 1; y < gridSize - 1; y++) { - for(x = 1; x < gridSize - 1; x++) { - copy_v3_v3(mvert[i++].co, - ccgSubSurf_getFaceGridData(ss, f, S, x, y)); + for(x = 1; x < gridSize - 1; x++, i++) { + vd= ccgSubSurf_getFaceGridData(ss, f, S, x, y); + copy_v3_v3(mvert[i].co, vd->co); + normal_float_to_short_v3(mvert[i].no, vd->no); } } } @@ -1212,8 +816,10 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) CCGEdge *e = ccgdm->edgeMap[index].edge; int x; - for(x = 1; x < edgeSize - 1; x++) { - copy_v3_v3(mvert[i++].co, ccgSubSurf_getEdgeData(ss, e, x)); + for(x = 1; x < edgeSize - 1; x++, i++) { + vd= ccgSubSurf_getEdgeData(ss, e, x); + copy_v3_v3(mvert[i].co, vd->co); + normal_float_to_short_v3(mvert[i].no, vd->no); } } @@ -1221,8 +827,9 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) for(index = 0; index < totvert; index++) { CCGVert *v = ccgdm->vertMap[index].vert; - copy_v3_v3(mvert[i].co, ccgSubSurf_getVertData(ss, v)); - + vd= ccgSubSurf_getVertData(ss, v); + copy_v3_v3(mvert[i].co, vd->co); + normal_float_to_short_v3(mvert[i].no, vd->no); i++; } } @@ -1236,7 +843,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); int i = 0; - int *edgeFlags = dm->getEdgeDataArray(dm, CD_FLAGS); + short *edgeFlags = ccgdm->edgeFlags; totface = ccgSubSurf_getNumFaces(ss); for(index = 0; index < totface; index++) { @@ -1291,7 +898,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) if(edgeFlags) { if(edgeIdx != -1) { - flags |= (edgeFlags[i] & (ME_SEAM | ME_SHARP)) + flags |= (edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER; } } else { @@ -1317,7 +924,7 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); int i = 0; - char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS); + char *faceFlags = ccgdm->faceFlags; totface = ccgSubSurf_getNumFaces(ss); for(index = 0; index < totface; index++) { @@ -1339,7 +946,7 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edgeSize, gridSize); mf->mat_nr = mat_nr; - if(faceFlags) mf->flag = faceFlags[index*4]; + if(faceFlags) mf->flag = faceFlags[index*2]; else mf->flag = flag; i++; @@ -1438,7 +1045,7 @@ static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { CCGVert *v = ccgVertIterator_getCurrent(vi); - VertData *vd = ccgSubSurf_getVertData(ccgdm->ss, v); + DMGridData *vd = ccgSubSurf_getVertData(ccgdm->ss, v); int index = ccgDM_getVertMapIndex(ccgdm->ss, v); if (index!=-1) @@ -1455,7 +1062,7 @@ static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { CCGEdge *e = ccgEdgeIterator_getCurrent(ei); - VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); + DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); int index = ccgDM_getEdgeMapIndex(ss, e); if (index!=-1) { @@ -1524,7 +1131,7 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) { for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { CCGEdge *e = ccgEdgeIterator_getCurrent(ei); - VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); + DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); if (!drawLooseEdges && !ccgSubSurf_getEdgeNumFaces(e)) continue; @@ -1552,7 +1159,7 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) { int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); for (S=0; Sss; - CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); + CCGFaceIterator *fi; int gridSize = ccgSubSurf_getGridSize(ss); - char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS); + char *faceFlags = ccgdm->faceFlags; + int step = 1; //(fast)? gridSize-1: 1; +#if 0 + if(ccgdm->pbvh && ccgdm->multires.mmd && !fast) { + CCGFace **faces; + int totface; + + BLI_pbvh_get_grid_updates(ccgdm->pbvh, (void***)&faces, &totface); + if(totface) { + ccgSubSurf_updateFromFaces(ss, 0, faces, totface); + ccgSubSurf_updateNormals(ss, faces, totface); + MEM_freeN(faces); + } + + /* should be per face */ + if(faceFlags && faceFlags[0] & ME_SMOOTH) + glShadeModel(GL_SMOOTH); + + BLI_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL); + + glShadeModel(GL_FLAT); + + return; + } +#endif + + fi = ccgSubSurf_getFaceIterator(ss); for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { CCGFace *f = ccgFaceIterator_getCurrent(fi); int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); @@ -1629,8 +1262,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) int drawSmooth, mat_nr; if(faceFlags) { - drawSmooth = (faceFlags[index*4] & ME_SMOOTH); - mat_nr= faceFlags[index*4 + 1]; + drawSmooth = (faceFlags[index*2] & ME_SMOOTH); + mat_nr= faceFlags[index*2 + 1]; } else { drawSmooth = 1; @@ -1642,14 +1275,14 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); for (S=0; Sno); glVertex3fv(a->co); @@ -1660,12 +1293,12 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) } } else { glBegin(GL_QUADS); - for (y=0; yfaceFlags; int a, b, i, doDraw, numVerts, matnr, new_matnr, totface; doDraw = 0; @@ -1737,8 +1370,8 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v numVerts = ccgSubSurf_getFaceNumVerts(f); if(faceFlags) { - drawSmooth = (faceFlags[index*4] & ME_SMOOTH); - new_matnr= faceFlags[index*4 + 1] + 1; + drawSmooth = (faceFlags[index*2] & ME_SMOOTH); + new_matnr= faceFlags[index*2 + 1] + 1; } else { drawSmooth = 1; @@ -1770,8 +1403,8 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); for (S=0; Sss; MCol *mcol = DM_get_face_data_layer(dm, CD_MCOL); MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); - char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS); + char *faceFlags = ccgdm->faceFlags; int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; @@ -1932,8 +1565,8 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, int mat_nr; if(faceFlags) { - drawSmooth = (faceFlags[origIndex*4] & ME_SMOOTH); - mat_nr= faceFlags[origIndex*4 + 1]; + drawSmooth = (faceFlags[origIndex*2] & ME_SMOOTH); + mat_nr= faceFlags[origIndex*2 + 1]; } else { drawSmooth = 1; @@ -1958,8 +1591,8 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, } for (S=0; Sss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); int i, gridSize = ccgSubSurf_getGridSize(ss); - char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS); + char *faceFlags = ccgdm->faceFlags; for (i=0; !ccgFaceIterator_isStopped(fi); i++,ccgFaceIterator_next(fi)) { CCGFace *f = ccgFaceIterator_getCurrent(fi); @@ -2099,7 +1732,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); - if(faceFlags) drawSmooth = (faceFlags[origIndex*4] & ME_SMOOTH); + if(faceFlags) drawSmooth = (faceFlags[origIndex*2] & ME_SMOOTH); else drawSmooth = 1; if (index!=-1) { @@ -2113,14 +1746,14 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u } for (S=0; Sno); glVertex3fv(a->co); @@ -2174,7 +1807,7 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *u for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { CCGEdge *e = ccgEdgeIterator_getCurrent(ei); - VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); + DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); int index = ccgDM_getEdgeMapIndex(ss, e); glBegin(GL_LINE_STRIP); @@ -2204,7 +1837,7 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(v for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { CCGEdge *e = ccgEdgeIterator_getCurrent(ei); - VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); + DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); int index = ccgDM_getEdgeMapIndex(ss, e); glBegin(GL_LINE_STRIP); @@ -2236,7 +1869,7 @@ static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *us if (index!=-1) { /* Face center data normal isn't updated atm. */ - VertData *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0); + DMGridData *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0); func(userData, index, vd->co, vd->no); } @@ -2249,6 +1882,22 @@ static void ccgDM_release(DerivedMesh *dm) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; if (DM_release(dm)) { + /* Before freeing, need to update the displacement map */ + if(ccgdm->multires.modified) { + /* Check that mmd still exists */ + if(!ccgdm->multires.local_mmd && BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0) + ccgdm->multires.mmd = NULL; + if(ccgdm->multires.mmd) + ccgdm->multires.update(dm); + } + + if(ccgdm->pbvh) BLI_pbvh_free(ccgdm->pbvh); + if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces); + if(ccgdm->gridData) MEM_freeN(ccgdm->gridData); + if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency); + if(ccgdm->freeSS) ccgSubSurf_free(ccgdm->ss); + MEM_freeN(ccgdm->edgeFlags); + MEM_freeN(ccgdm->faceFlags); MEM_freeN(ccgdm->vertMap); MEM_freeN(ccgdm->edgeMap); MEM_freeN(ccgdm->faceMap); @@ -2256,6 +1905,262 @@ static void ccgDM_release(DerivedMesh *dm) { } } +static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type) +{ + if(type == CD_ORIGINDEX) { + /* create origindex on demand to save memory */ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= ccgdm->ss; + int *origindex; + int a, index, totnone, totorig; + + DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); + origindex= DM_get_vert_data_layer(dm, CD_ORIGINDEX); + + totorig = ccgSubSurf_getNumVerts(ss); + totnone= dm->numVertData - totorig; + + /* original vertices are at the end */ + for(a=0; avertMap[index].vert; + origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v); + } + + return origindex; + } + + return DM_get_vert_data_layer(dm, type); +} + +static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type) +{ + if(type == CD_ORIGINDEX) { + /* create origindex on demand to save memory */ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= ccgdm->ss; + int *origindex; + int a, i, index, totnone, totorig, totedge; + int edgeSize= ccgSubSurf_getEdgeSize(ss); + + DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); + origindex= DM_get_edge_data_layer(dm, CD_ORIGINDEX); + + totedge= ccgSubSurf_getNumEdges(ss); + totorig= totedge*(edgeSize - 1); + totnone= dm->numEdgeData - totorig; + + /* original edges are at the end */ + for(a=0; aedgeMap[index].edge; + int mapIndex= ccgDM_getEdgeMapIndex(ss, e); + + for(i = 0; i < edgeSize - 1; i++, a++) + origindex[a]= mapIndex; + } + + return origindex; + } + + return DM_get_edge_data_layer(dm, type); +} + +static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type) +{ + if(type == CD_ORIGINDEX) { + /* create origindex on demand to save memory */ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= ccgdm->ss; + int *origindex; + int a, i, index, totface; + int gridFaces = ccgSubSurf_getGridSize(ss) - 1; + + DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); + origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX); + + totface= ccgSubSurf_getNumFaces(ss); + + for(a=0, index=0; indexfaceMap[index].face; + int numVerts = ccgSubSurf_getFaceNumVerts(f); + int mapIndex = ccgDM_getFaceMapIndex(ss, f); + + for(i=0; iss); + numGrids= 0; + + for(index=0; indexfaceMap[index].face; + numGrids += ccgSubSurf_getFaceNumVerts(f); + } + + return numGrids; +} + +static int ccgDM_getGridSize(DerivedMesh *dm) +{ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + return ccgSubSurf_getGridSize(ccgdm->ss); +} + +static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset) +{ + CCGFace *adjf; + CCGEdge *e; + int i, j= 0, numFaces, fIndex, numEdges= 0; + + e = ccgSubSurf_getFaceEdge(ss, f, S); + numFaces = ccgSubSurf_getEdgeNumFaces(e); + + if(numFaces != 2) + return -1; + + for(i = 0; i < numFaces; i++) { + adjf = ccgSubSurf_getEdgeFace(e, i); + + if(adjf != f) { + numEdges = ccgSubSurf_getFaceNumVerts(adjf); + for(j = 0; j < numEdges; j++) + if(ccgSubSurf_getFaceEdge(ss, adjf, j) == e) + break; + + if(j != numEdges) + break; + } + } + + fIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, adjf)); + + return gridOffset[fIndex] + (j + offset)%numEdges; +} + +static void ccgdm_create_grids(DerivedMesh *dm) +{ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + CCGSubSurf *ss= ccgdm->ss; + DMGridData **gridData; + DMGridAdjacency *gridAdjacency, *adj; + CCGFace **gridFaces; + int *gridOffset; + int index, numFaces, numGrids, S, gIndex, gridSize; + + if(ccgdm->gridData) + return; + + numGrids = ccgDM_getNumGrids(dm); + numFaces = ccgSubSurf_getNumFaces(ss); + gridSize = ccgDM_getGridSize(dm); + + /* compute offset into grid array for each face */ + gridOffset = MEM_mallocN(sizeof(int)*numFaces, "ccgdm.gridOffset"); + + for(gIndex = 0, index = 0; index < numFaces; index++) { + CCGFace *f = ccgdm->faceMap[index].face; + int numVerts = ccgSubSurf_getFaceNumVerts(f); + + gridOffset[index] = gIndex; + gIndex += numVerts; + } + + /* compute grid data */ + gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "ccgdm.gridData"); + gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "ccgdm.gridAdjacency"); + gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "ccgdm.gridFaces"); + + for(gIndex = 0, index = 0; index < numFaces; index++) { + CCGFace *f = ccgdm->faceMap[index].face; + int numVerts = ccgSubSurf_getFaceNumVerts(f); + + for(S = 0; S < numVerts; S++, gIndex++) { + int prevS = (S - 1 + numVerts) % numVerts; + int nextS = (S + 1 + numVerts) % numVerts; + + gridData[gIndex] = ccgSubSurf_getFaceGridDataArray(ss, f, S); + gridFaces[gIndex] = f; + + adj = &gridAdjacency[gIndex]; + + adj->index[0] = gIndex - S + nextS; + adj->rotation[0] = 3; + adj->index[1] = ccgdm_adjacent_grid(ss, gridOffset, f, prevS, 0); + adj->rotation[1] = 1; + adj->index[2] = ccgdm_adjacent_grid(ss, gridOffset, f, S, 1); + adj->rotation[2] = 3; + adj->index[3] = gIndex - S + prevS; + adj->rotation[3] = 1; + } + } + + ccgdm->gridData = gridData; + ccgdm->gridFaces = gridFaces; + ccgdm->gridAdjacency = gridAdjacency; + MEM_freeN(gridOffset); +} + +static DMGridData **ccgDM_getGridData(DerivedMesh *dm) +{ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + + ccgdm_create_grids(dm); + return ccgdm->gridData; +} + +static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm) +{ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + + ccgdm_create_grids(dm); + return ccgdm->gridAdjacency; +} + +static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) +{ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + //int gridSize, numGrids; + + if(ccgdm->pbvh) + return ccgdm->pbvh; + + /*if(ccgdm->multires.mmd) { + ccgdm_create_grids(dm); + + gridSize = ccgDM_getGridSize(dm); + numGrids = ccgDM_getNumGrids(dm); + + ccgdm->pbvh = BLI_pbvh_new(); + BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, numGrids, gridSize, + (void**)ccgdm->gridFaces); + } + else*/ if(ob->type == OB_MESH) { + Mesh *me= ob->data; + + ccgdm->pbvh = BLI_pbvh_new(); + BLI_pbvh_build(ccgdm->pbvh, me->mface, me->mvert, + me->totface, me->totvert); + } + + return ccgdm->pbvh; +} + static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int drawInteriorEdges, int useSubsurfUv, @@ -2268,17 +2173,14 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int index, totvert, totedge, totface; int i; int vertNum, edgeNum, faceNum; - int *vertOrigIndex, *faceOrigIndex; /* *edgeOrigIndex - as yet, unused */ - int *edgeFlags; + short *edgeFlags; char *faceFlags; int edgeSize; int gridSize; int gridFaces; int gridSideVerts; - /*int gridInternalVerts; - as yet unused */ int gridSideEdges; int gridInternalEdges; - /* MVert *mvert = NULL; - as yet unused */ MEdge *medge = NULL; MFace *mface = NULL; FaceVertWeight *qweight, *tweight; @@ -2286,11 +2188,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, DM_from_template(&ccgdm->dm, dm, ccgSubSurf_getNumFinalVerts(ss), ccgSubSurf_getNumFinalEdges(ss), ccgSubSurf_getNumFinalFaces(ss)); - DM_add_face_layer(&ccgdm->dm, CD_FLAGS, CD_CALLOC, NULL); - DM_add_edge_layer(&ccgdm->dm, CD_FLAGS, CD_CALLOC, NULL); - - CustomData_set_layer_flag(&ccgdm->dm.faceData, CD_FLAGS, CD_FLAG_NOCOPY); - CustomData_set_layer_flag(&ccgdm->dm.edgeData, CD_FLAGS, CD_FLAG_NOCOPY); ccgdm->dm.getMinMax = ccgDM_getMinMax; ccgdm->dm.getNumVerts = ccgDM_getNumVerts; @@ -2306,9 +2203,14 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.getVertData = DM_get_vert_data; ccgdm->dm.getEdgeData = DM_get_edge_data; ccgdm->dm.getFaceData = DM_get_face_data; - ccgdm->dm.getVertDataArray = DM_get_vert_data_layer; - ccgdm->dm.getEdgeDataArray = DM_get_edge_data_layer; - ccgdm->dm.getFaceDataArray = DM_get_face_data_layer; + ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer; + ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer; + ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer; + ccgdm->dm.getNumGrids = ccgDM_getNumGrids; + ccgdm->dm.getGridSize = ccgDM_getGridSize; + ccgdm->dm.getGridData = ccgDM_getGridData; + ccgdm->dm.getGridAdjacency = ccgDM_getGridAdjacency; + ccgdm->dm.getPBVH = ccgDM_getPBVH; ccgdm->dm.getVertCos = ccgdm_getVertCos; ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert; @@ -2383,17 +2285,12 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, medge = dm->getEdgeArray(dm); mface = dm->getFaceArray(dm); - vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX); - /*edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);*/ - faceOrigIndex = DM_get_face_data_layer(&ccgdm->dm, CD_ORIGINDEX); - - faceFlags = DM_get_face_data_layer(&ccgdm->dm, CD_FLAGS); + faceFlags = ccgdm->faceFlags = MEM_callocN(sizeof(char)*2*totface, "faceFlags"); for(index = 0; index < totface; ++index) { CCGFace *f = ccgdm->faceMap[index].face; int numVerts = ccgSubSurf_getFaceNumVerts(f); int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges); - int mapIndex = ccgDM_getFaceMapIndex(ss, f); int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight; int S, x, y; @@ -2414,8 +2311,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0], numVerts, vertNum); - *vertOrigIndex = ORIGINDEX_NONE; - ++vertOrigIndex; ++vertNum; for(S = 0; S < numVerts; S++) { @@ -2430,8 +2325,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, w[otherS] = weight[x][0][3]; DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, numVerts, vertNum); - *vertOrigIndex = ORIGINDEX_NONE; - ++vertOrigIndex; ++vertNum; } } @@ -2449,17 +2342,11 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, w[otherS] = weight[y * gridFaces + x][0][3]; DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, numVerts, vertNum); - *vertOrigIndex = ORIGINDEX_NONE; - ++vertOrigIndex; ++vertNum; } } } - for(i = 0; i < numFinalEdges; ++i) - *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i, - CD_ORIGINDEX) = ORIGINDEX_NONE; - for(S = 0; S < numVerts; S++) { int prevS = (S - 1 + numVerts) % numVerts; int nextS = (S + 1) % numVerts; @@ -2483,16 +2370,13 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, &w, 1, faceNum); weight++; - *faceOrigIndex = mapIndex; - - ++faceOrigIndex; ++faceNum; } } } - faceFlags[index*4] = mface[origIndex].flag; - faceFlags[index*4 + 1] = mface[origIndex].mat_nr; + faceFlags[index*2] = mface[origIndex].flag; + faceFlags[index*2 + 1] = mface[origIndex].mat_nr; edgeNum += numFinalEdges; } @@ -2507,12 +2391,11 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, set_subsurf_uv(ss, dm, &ccgdm->dm, i); } - edgeFlags = DM_get_edge_data_layer(&ccgdm->dm, CD_FLAGS); + edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "edgeFlags"); for(index = 0; index < totedge; ++index) { CCGEdge *e = ccgdm->edgeMap[index].edge; int numFinalEdges = edgeSize - 1; - int mapIndex = ccgDM_getEdgeMapIndex(ss, e); int x; int vertIdx[2]; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e)); @@ -2534,25 +2417,16 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, w[1] = (float) x / (edgeSize - 1); w[0] = 1 - w[1]; DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum); - *vertOrigIndex = ORIGINDEX_NONE; - ++vertOrigIndex; ++vertNum; } - for(i = 0; i < numFinalEdges; ++i) { - if(edgeIdx >= 0 && edgeFlags) - edgeFlags[edgeNum + i] = medge[edgeIdx].flag; - - *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i, - CD_ORIGINDEX) = mapIndex; - } + edgeFlags[index]= medge[edgeIdx].flag; edgeNum += numFinalEdges; } for(index = 0; index < totvert; ++index) { CCGVert *v = ccgdm->vertMap[index].vert; - int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v); int vertIdx; vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); @@ -2564,8 +2438,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1); - *vertOrigIndex = mapIndex; - ++vertOrigIndex; ++vertNum; } @@ -2577,10 +2449,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, /***/ -struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( +struct DerivedMesh *subsurf_make_derived_from_derived( struct DerivedMesh *dm, struct SubsurfModifierData *smd, - struct MultiresSubsurf *ms, int useRenderParams, float (*vertCos)[3], int isFinalCalc, int editMode) { @@ -2588,16 +2459,16 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr; int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv; int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges); - DerivedMesh *result; + CCGDerivedMesh *result; if(editMode) { smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0, useSimple); ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple); - return (DerivedMesh *)getCCGDerivedMesh(smd->emCache, - drawInteriorEdges, - useSubsurfUv, dm); + result = getCCGDerivedMesh(smd->emCache, + drawInteriorEdges, + useSubsurfUv, dm); } else if(useRenderParams) { /* Do not use cache in render mode. */ CCGSubSurf *ss; @@ -2611,12 +2482,10 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); - result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm, ms); + result = getCCGDerivedMesh(ss, + drawInteriorEdges, useSubsurfUv, dm); - ccgSubSurf_free(ss); - - return result; + result->freeSS = 1; } else { int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental); int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr; @@ -2641,13 +2510,9 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); - - return ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm, ms); - - /*return (DerivedMesh *)getCCGDerivedMesh(smd->mCache, - drawInteriorEdges, - useSubsurfUv, dm);*/ + result = getCCGDerivedMesh(smd->mCache, + drawInteriorEdges, + useSubsurfUv, dm); } else { if (smd->mCache && isFinalCalc) { ccgSubSurf_free(smd->mCache); @@ -2657,28 +2522,16 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( ss = _getSubSurf(NULL, smd->levels, 0, 1, useSimple); ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); - /*smd->mCache = ss; - result = (DerivedMesh *)getCCGDerivedMesh(smd->mCache, - drawInteriorEdges, - useSubsurfUv, dm);*/ - - result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm, ms); + result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm); - ccgSubSurf_free(ss); - - return result; + if(isFinalCalc) + smd->mCache = ss; + else + result->freeSS = 1; } } -} -struct DerivedMesh *subsurf_make_derived_from_derived( - struct DerivedMesh *dm, - struct SubsurfModifierData *smd, - int useRenderParams, float (*vertCos)[3], - int isFinalCalc, int editMode) -{ - return subsurf_make_derived_from_derived_with_multires(dm, smd, NULL, useRenderParams, vertCos, isFinalCalc, editMode); + return (DerivedMesh*)result; } void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) -- cgit v1.2.3 From 134935a8db7fe6137bb8a508771757beeb68b2b3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 25 Nov 2009 13:40:43 +0000 Subject: Sculpt: Grid based PBVH * PBVH can now be created contain both from face grids or standard meshes. The former is much quicker to build for high res meshes. * Moved some drawing code into pbvh (mostly for the frustum test). * Moved ray intersection code into pbvh. * GPU buffers also can be built from either mesh or grids now. * Updated sculpt code to work with this. The ugly part is that there is now a macro for iterating over vertices, to handle both cases, and some duplicated code for e.g. undo. * Smooth brush does not work yet with grids. --- source/blender/blenkernel/intern/cdderivedmesh.c | 73 +----------------------- source/blender/blenkernel/intern/subsurf_ccg.c | 13 ++--- 2 files changed, 8 insertions(+), 78 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index e64d8a24934..3007564e333 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -197,7 +197,7 @@ static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) Mesh *me= ob->data; cddm->pbvh = BLI_pbvh_new(); - BLI_pbvh_build(cddm->pbvh, me->mface, me->mvert, + BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert, me->totface, me->totvert); } @@ -393,60 +393,6 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) } } -static int nodes_drawn = 0; -static int is_partial = 0; -/* XXX: Just a temporary replacement for the real drawing code */ -static void draw_partial_cb(PBVHNode *node, void *data) -{ - /* XXX: Just some quick code to show leaf nodes in different colors */ - /*float col[3]; int i; - if(is_partial) { - col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6; - } - else { - srand((long long)data_v); - for(i = 0; i < 3; ++i) - col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7; - } - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); - - glColor3f(1, 0, 0);*/ - GPU_draw_buffers(BLI_pbvh_node_get_draw_buffers(node)); - ++nodes_drawn; -} - -/* Adapted from: - http://www.gamedev.net/community/forums/topic.asp?topic_id=512123 - Returns true if the AABB is at least partially within the frustum - (ok, not a real frustum), false otherwise. -*/ -int planes_contain_AABB(PBVHNode *node, void *data) -{ - float (*planes)[4] = data; - int i, axis; - float vmin[3], vmax[3], bb_min[3], bb_max[3]; - - BLI_pbvh_node_get_BB(node, bb_min, bb_max); - - for(i = 0; i < 4; ++i) { - for(axis = 0; axis < 3; ++axis) { - if(planes[i][axis] > 0) { - vmin[axis] = bb_min[axis]; - vmax[axis] = bb_max[axis]; - } - else { - vmin[axis] = bb_max[axis]; - vmax[axis] = bb_min[axis]; - } - } - - if(dot_v3v3(planes[i], vmin) + planes[i][3] > 0) - return 0; - } - - return 1; -} - static void cdDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)) @@ -468,26 +414,11 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, if(cddm->pbvh) { float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL); - BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals|PBVH_UpdateDrawBuffers, - face_nors); - /* should be per face */ if(dm->numFaceData && mface->flag & ME_SMOOTH) glShadeModel(GL_SMOOTH); - if(partial_redraw_planes) { - BLI_pbvh_search_callback(cddm->pbvh, planes_contain_AABB, - partial_redraw_planes, draw_partial_cb, NULL); - } - else { - BLI_pbvh_search_callback(cddm->pbvh, NULL, NULL, - draw_partial_cb, NULL); - } - - is_partial = !!partial_redraw_planes; - - //printf("nodes drawn=%d\n", nodes_drawn); - nodes_drawn = 0; + BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors); glShadeModel(GL_FLAT); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index e465d17f498..30766931a0b 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -819,6 +819,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) for(x = 1; x < edgeSize - 1; x++, i++) { vd= ccgSubSurf_getEdgeData(ss, e, x); copy_v3_v3(mvert[i].co, vd->co); + /* TODO CCGSubsurf does not set these */ normal_float_to_short_v3(mvert[i].no, vd->no); } } @@ -1230,8 +1231,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) char *faceFlags = ccgdm->faceFlags; int step = 1; //(fast)? gridSize-1: 1; -#if 0 - if(ccgdm->pbvh && ccgdm->multires.mmd && !fast) { + if(ccgdm->pbvh && ccgdm->multires.mmd) { // && !fast) { CCGFace **faces; int totface; @@ -1252,7 +1252,6 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) return; } -#endif fi = ccgSubSurf_getFaceIterator(ss); for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { @@ -2135,12 +2134,12 @@ static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm) static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) { CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; - //int gridSize, numGrids; + int gridSize, numGrids; if(ccgdm->pbvh) return ccgdm->pbvh; - /*if(ccgdm->multires.mmd) { + if(ccgdm->multires.mmd) { ccgdm_create_grids(dm); gridSize = ccgDM_getGridSize(dm); @@ -2150,11 +2149,11 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, numGrids, gridSize, (void**)ccgdm->gridFaces); } - else*/ if(ob->type == OB_MESH) { + else if(ob->type == OB_MESH) { Mesh *me= ob->data; ccgdm->pbvh = BLI_pbvh_new(); - BLI_pbvh_build(ccgdm->pbvh, me->mface, me->mvert, + BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert, me->totface, me->totvert); } -- cgit v1.2.3 From fffce6c5545c3072d2dd266dfe5c133b760baebe Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 25 Nov 2009 14:07:12 +0000 Subject: Sculpt: Multires * Displacement coordinates are now stored differently, as a grid per face corner. This means there is duplication of coordinates, especially at low subdivision levels, but the simpler implementation justifies it I think. * ToDo: conversion of existing multires files (2.4x or 2.5x), loading them may even crash now. * Editmode preservation/interpolation code also has not been updated yet. * Multires now works on the CCGDerivedMesh grids instead of CDDerivedMesh, which should be more memory efficient. * There are still bad memory peaks (if you're using 32bit) when subdividing or propagating displacements. Though at least there should be no huge memory blocks allocated, which windows is now to have trouble with. * Still found some weird spike artifacts at lower multires levels, some also happening before this commit. Perhaps computation of tangents needs to be tweaked more. * Multires modifier now has viewport, sculpt and render levels. Also the levels have been made consistent with subsurf, previously the same level of subdivision was one less for multires. * Both multires and subsurf modifier now can have their subdivision level set to 0 for no subdivision. --- source/blender/blenkernel/BKE_modifier.h | 2 +- source/blender/blenkernel/BKE_multires.h | 20 +- source/blender/blenkernel/intern/DerivedMesh.c | 2 +- source/blender/blenkernel/intern/cdderivedmesh.c | 212 ---- source/blender/blenkernel/intern/customdata.c | 8 + source/blender/blenkernel/intern/displist.c | 6 +- source/blender/blenkernel/intern/lattice.c | 2 +- source/blender/blenkernel/intern/modifier.c | 95 +- source/blender/blenkernel/intern/multires.c | 1396 +++++++--------------- 9 files changed, 504 insertions(+), 1239 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 245db7e35ff..3018f89178e 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -228,7 +228,7 @@ typedef struct ModifierTypeInfo { * * This function is optional (assumes never disabled if not present). */ - int (*isDisabled)(struct ModifierData *md); + int (*isDisabled)(struct ModifierData *md, int userRenderParams); /* Add the appropriate relations to the DEP graph depending on the * modifier data. diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index a331479cad1..53ead3a5eda 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -39,23 +39,6 @@ typedef struct MultiresSubsurf { int local_mmd; } MultiresSubsurf; -/* MultiresDM */ -struct Object *MultiresDM_get_object(struct DerivedMesh *dm); -struct Mesh *MultiresDM_get_mesh(struct DerivedMesh *dm); -struct DerivedMesh *MultiresDM_new(struct MultiresSubsurf *, struct DerivedMesh*, int, int, int); -void *MultiresDM_get_vertnorm(struct DerivedMesh *); -void *MultiresDM_get_orco(struct DerivedMesh *); -struct MVert *MultiresDM_get_subco(struct DerivedMesh *); -struct ListBase *MultiresDM_get_vert_face_map(struct DerivedMesh *); -struct ListBase *MultiresDM_get_vert_edge_map(struct DerivedMesh *); -int *MultiresDM_get_face_offsets(struct DerivedMesh *); -int MultiresDM_get_totlvl(struct DerivedMesh *); -int MultiresDM_get_lvl(struct DerivedMesh *); -void MultiresDM_set_update(struct DerivedMesh *, void (*)(struct DerivedMesh*)); - -/* The displacements will only be updated when - the MultiresDM has been marked as modified */ -void MultiresDM_mark_as_modified(struct DerivedMesh *); void multires_mark_as_modified(struct Object *ob); void multires_force_update(struct Object *ob); @@ -64,10 +47,9 @@ struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData* struct Object *, int, int); struct MultiresModifierData *find_multires_modifier(struct Object *ob); -int multiresModifier_switch_level(struct Object *, const int); void multiresModifier_join(struct Object *); void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction); -void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int distance, +void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple); int multiresModifier_reshape(struct MultiresModifierData *mmd, struct Object *dst, struct Object *src); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 5a911fcb13b..b715b1531de 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1535,7 +1535,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier md->scene= scene; if (!(md->mode&eModifierMode_Realtime)) return NULL; - if (mti->isDisabled && mti->isDisabled(md)) return NULL; + if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL; if (mti->type==eModifierTypeType_OnlyDeform) { int numVerts; diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 3007564e333..b3e75549028 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1810,215 +1810,3 @@ MFace *CDDM_get_faces(DerivedMesh *dm) return ((CDDerivedMesh*)dm)->mface; } -/* Multires DerivedMesh, extends CDDM */ -typedef struct MultiresDM { - CDDerivedMesh cddm; - - MultiresModifierData *mmd; - int local_mmd; - - int lvl, totlvl; - float (*orco)[3]; - MVert *subco; - - ListBase *vert_face_map, *vert_edge_map; - IndexNode *vert_face_map_mem, *vert_edge_map_mem; - int *face_offsets; - - Object *ob; - int modified; - - void (*update)(DerivedMesh*); -} MultiresDM; - -static void MultiresDM_release(DerivedMesh *dm) -{ - MultiresDM *mrdm = (MultiresDM*)dm; - int mvert_layer; - - /* Before freeing, need to update the displacement map */ - if(dm->needsFree && mrdm->modified) { - /* Check that mmd still exists */ - if(!mrdm->local_mmd && BLI_findindex(&mrdm->ob->modifiers, mrdm->mmd) < 0) - mrdm->mmd = NULL; - if(mrdm->mmd) - mrdm->update(dm); - } - - /* If the MVert data is being used as the sculpt undo store, don't free it */ - mvert_layer = CustomData_get_layer_index(&dm->vertData, CD_MVERT); - if(mvert_layer != -1) { - CustomDataLayer *cd = &dm->vertData.layers[mvert_layer]; - if(mrdm->mmd && cd->data == mrdm->mmd->undo_verts) - cd->flag |= CD_FLAG_NOFREE; - } - - if(DM_release(dm)) { - cdDM_free_internal(&mrdm->cddm); - MEM_freeN(mrdm->subco); - MEM_freeN(mrdm->orco); - if(mrdm->vert_face_map) - MEM_freeN(mrdm->vert_face_map); - if(mrdm->vert_face_map_mem) - MEM_freeN(mrdm->vert_face_map_mem); - if(mrdm->vert_edge_map) - MEM_freeN(mrdm->vert_edge_map); - if(mrdm->vert_edge_map_mem) - MEM_freeN(mrdm->vert_edge_map_mem); - if(mrdm->face_offsets) - MEM_freeN(mrdm->face_offsets); - MEM_freeN(mrdm); - } -} - -DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts, int numEdges, int numFaces) -{ - MultiresDM *mrdm = MEM_callocN(sizeof(MultiresDM), "MultiresDM"); - CDDerivedMesh *cddm = cdDM_create("MultiresDM CDDM"); - DerivedMesh *dm = NULL; - - mrdm->cddm = *cddm; - MEM_freeN(cddm); - dm = &mrdm->cddm.dm; - - mrdm->mmd = ms->mmd; - mrdm->ob = ms->ob; - mrdm->local_mmd = ms->local_mmd; - - if(dm) { - MDisps *disps; - MVert *mvert; - int i; - - DM_from_template(dm, orig, numVerts, numEdges, numFaces); - CustomData_free_layers(&dm->faceData, CD_MDISPS, numFaces); - - disps = CustomData_get_layer(&orig->faceData, CD_MDISPS); - if(disps) - CustomData_add_layer(&dm->faceData, CD_MDISPS, CD_REFERENCE, disps, numFaces); - - - mvert = CustomData_get_layer(&orig->vertData, CD_MVERT); - mrdm->orco = MEM_callocN(sizeof(float) * 3 * orig->getNumVerts(orig), "multires orco"); - for(i = 0; i < orig->getNumVerts(orig); ++i) - copy_v3_v3(mrdm->orco[i], mvert[i].co); - } - else - DM_init(dm, numVerts, numEdges, numFaces); - - if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) - CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); - if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX)) - CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); - if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) - CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); - - CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); - CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); - CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); - - mrdm->cddm.mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); - mrdm->cddm.medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); - mrdm->cddm.mface = CustomData_get_layer(&dm->faceData, CD_MFACE); - - mrdm->lvl = ms->mmd->lvl; - mrdm->totlvl = ms->mmd->totlvl; - mrdm->subco = MEM_callocN(sizeof(MVert)*numVerts, "multires subdivided verts"); - mrdm->modified = 0; - - dm->release = MultiresDM_release; - - return dm; -} - -Mesh *MultiresDM_get_mesh(DerivedMesh *dm) -{ - return get_mesh(((MultiresDM*)dm)->ob); -} - -Object *MultiresDM_get_object(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->ob; -} - -void *MultiresDM_get_orco(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->orco; - -} - -MVert *MultiresDM_get_subco(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->subco; -} - -int MultiresDM_get_totlvl(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->totlvl; -} - -int MultiresDM_get_lvl(DerivedMesh *dm) -{ - return ((MultiresDM*)dm)->lvl; -} - -void MultiresDM_set_orco(DerivedMesh *dm, float (*orco)[3]) -{ - ((MultiresDM*)dm)->orco = orco; -} - -void MultiresDM_set_update(DerivedMesh *dm, void (*update)(DerivedMesh*)) -{ - ((MultiresDM*)dm)->update = update; -} - -ListBase *MultiresDM_get_vert_face_map(DerivedMesh *dm) -{ - MultiresDM *mrdm = (MultiresDM*)dm; - Mesh *me = mrdm->ob->data; - - if(!mrdm->vert_face_map) - create_vert_face_map(&mrdm->vert_face_map, &mrdm->vert_face_map_mem, me->mface, - me->totvert, me->totface); - - return mrdm->vert_face_map; -} - -ListBase *MultiresDM_get_vert_edge_map(DerivedMesh *dm) -{ - MultiresDM *mrdm = (MultiresDM*)dm; - Mesh *me = mrdm->ob->data; - - if(!mrdm->vert_edge_map) - create_vert_edge_map(&mrdm->vert_edge_map, &mrdm->vert_edge_map_mem, me->medge, - me->totvert, me->totedge); - - return mrdm->vert_edge_map; -} - -int *MultiresDM_get_face_offsets(DerivedMesh *dm) -{ - MultiresDM *mrdm = (MultiresDM*)dm; - Mesh *me = mrdm->ob->data; - int i, accum = 0; - - if(!mrdm->face_offsets) { - int len = (int)pow(2, mrdm->lvl - 2) - 1; - int area = len * len; - int t = 1 + len * 3 + area * 3, q = t + len + area; - - mrdm->face_offsets = MEM_callocN(sizeof(int) * me->totface, "mrdm face offsets"); - for(i = 0; i < me->totface; ++i) { - mrdm->face_offsets[i] = accum; - - accum += (me->mface[i].v4 ? q : t); - } - } - - return mrdm->face_offsets; -} - -void MultiresDM_mark_as_modified(DerivedMesh *dm) -{ - ((MultiresDM*)dm)->modified = 1; -} diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 7b754025b6c..4844595513f 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -381,6 +381,7 @@ static void layerDefault_origspace_face(void *data, int count) osf[i] = default_osf; } +#if 0 /* Adapted from sculptmode.c */ static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) { @@ -426,9 +427,12 @@ static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, fl add_v3_v3v3(out, d2[0], d2[1]); } +#endif static void layerSwap_mdisps(void *data, int *ci) { + // XXX +#if 0 MDisps *s = data; float (*d)[3] = NULL; int x, y, st; @@ -447,11 +451,14 @@ static void layerSwap_mdisps(void *data, int *ci) if(s->disps) MEM_freeN(s->disps); s->disps = d; +#endif } static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights, int count, void *dest) { + // XXX +#if 0 MDisps *d = dest; MDisps *s = NULL; int st, stl; @@ -496,6 +503,7 @@ static void layerInterp_mdisps(void **sources, float *weights, float *sub_weight copy_v3_v3(d->disps[y * st + x], srcdisp); } } +#endif } static void layerCopy_mdisps(const void *source, void *dest, int count) diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 48fb283c404..b35cf917895 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1225,7 +1225,7 @@ static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int ed ModifierTypeInfo *mti = modifierType_getInfo(md->type); if ((md->mode & required_mode) != required_mode) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { preTesselatePoint = md; @@ -1275,7 +1275,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl md->scene= scene; if ((md->mode & required_mode) != required_mode) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; if (mti->type!=eModifierTypeType_OnlyDeform) continue; if (!deformedVerts) { @@ -1330,7 +1330,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba md->scene= scene; if ((md->mode & required_mode) != required_mode) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; if (mti->type!=eModifierTypeType_OnlyDeform && mti->type!=eModifierTypeType_DeformOrConstruct) continue; /* need to put all verts in 1 block for curve deform */ diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index dc548edbb25..e963b2e9fb6 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -1002,7 +1002,7 @@ void lattice_calc_modifiers(Scene *scene, Object *ob) if (!(md->mode&eModifierMode_Realtime)) continue; if (editmode && !(md->mode&eModifierMode_Editmode)) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, 0)) continue; if (mti->type!=eModifierTypeType_OnlyDeform) continue; if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 50c907fd1ca..d8c05c30cfe 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -187,7 +187,7 @@ static DerivedMesh *get_original_dm(Scene *scene, Object *ob, float (*vertexCos) /***/ -static int noneModifier_isDisabled(ModifierData *md) +static int noneModifier_isDisabled(ModifierData *md, int userRenderParams) { return 1; } @@ -222,7 +222,7 @@ static CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *m return dataMask; } -static int curveModifier_isDisabled(ModifierData *md) +static int curveModifier_isDisabled(ModifierData *md, int userRenderParams) { CurveModifierData *cmd = (CurveModifierData*) md; @@ -298,7 +298,7 @@ static CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData return dataMask; } -static int latticeModifier_isDisabled(ModifierData *md) +static int latticeModifier_isDisabled(ModifierData *md, int userRenderParams) { LatticeModifierData *lmd = (LatticeModifierData*) md; @@ -402,6 +402,13 @@ static void subsurfModifier_freeData(ModifierData *md) } } +static int subsurfModifier_isDisabled(ModifierData *md, int useRenderParams) +{ + SubsurfModifierData *smd = (SubsurfModifierData*) md; + + return (useRenderParams)? (smd->renderLevels == 0): (smd->levels == 0); +} + static DerivedMesh *subsurfModifier_applyModifier( ModifierData *md, Object *ob, DerivedMesh *derivedData, int useRenderParams, int isFinalCalc) @@ -410,8 +417,13 @@ static DerivedMesh *subsurfModifier_applyModifier( DerivedMesh *result; result = subsurf_make_derived_from_derived(derivedData, smd, - useRenderParams, NULL, - isFinalCalc, 0); + useRenderParams, NULL, isFinalCalc, 0); + + if(useRenderParams || !isFinalCalc) { + DerivedMesh *cddm= CDDM_copy(result); + result->release(result); + result= cddm; + } return result; } @@ -3524,7 +3536,7 @@ static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob, displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } -static int displaceModifier_isDisabled(ModifierData *md) +static int displaceModifier_isDisabled(ModifierData *md, int useRenderParams) { DisplaceModifierData *dmd = (DisplaceModifierData*) md; @@ -4268,7 +4280,7 @@ static void smoothModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tsmd->defgrp_name, smd->defgrp_name, 32); } -static int smoothModifier_isDisabled(ModifierData *md) +static int smoothModifier_isDisabled(ModifierData *md, int useRenderParams) { SmoothModifierData *smd = (SmoothModifierData*) md; short flag; @@ -4498,7 +4510,7 @@ static void castModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32); } -static int castModifier_isDisabled(ModifierData *md) +static int castModifier_isDisabled(ModifierData *md, int useRenderParams) { CastModifierData *cmd = (CastModifierData*) md; short flag; @@ -5487,7 +5499,7 @@ static CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData return dataMask; } -static int armatureModifier_isDisabled(ModifierData *md) +static int armatureModifier_isDisabled(ModifierData *md, int useRenderParams) { ArmatureModifierData *amd = (ArmatureModifierData*) md; @@ -5610,7 +5622,7 @@ static void hookModifier_freeData(ModifierData *md) if (hmd->indexar) MEM_freeN(hmd->indexar); } -static int hookModifier_isDisabled(ModifierData *md) +static int hookModifier_isDisabled(ModifierData *md, int useRenderParams) { HookModifierData *hmd = (HookModifierData*) md; @@ -6308,7 +6320,7 @@ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) tbmd->operation = bmd->operation; } -static int booleanModifier_isDisabled(ModifierData *md) +static int booleanModifier_isDisabled(ModifierData *md, int useRenderParams) { BooleanModifierData *bmd = (BooleanModifierData*) md; @@ -7757,7 +7769,7 @@ static CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierDa return dataMask; } -static int meshdeformModifier_isDisabled(ModifierData *md) +static int meshdeformModifier_isDisabled(ModifierData *md, int useRenderParams) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; @@ -8047,15 +8059,10 @@ static void multiresModifier_initData(ModifierData *md) { MultiresModifierData *mmd = (MultiresModifierData*)md; - mmd->lvl = mmd->totlvl = 1; -} - -static void multiresModifier_freeData(ModifierData *md) -{ - MultiresModifierData *mmd = (MultiresModifierData*)md; - - if(mmd->undo_verts) - MEM_freeN(mmd->undo_verts); + mmd->lvl = 0; + mmd->sculptlvl = 0; + mmd->renderlvl = 0; + mmd->totlvl = 0; } static void multiresModifier_copyData(ModifierData *md, ModifierData *target) @@ -8063,37 +8070,35 @@ static void multiresModifier_copyData(ModifierData *md, ModifierData *target) MultiresModifierData *mmd = (MultiresModifierData*) md; MultiresModifierData *tmmd = (MultiresModifierData*) target; - tmmd->totlvl = mmd->totlvl; tmmd->lvl = mmd->lvl; + tmmd->sculptlvl = mmd->sculptlvl; + tmmd->renderlvl = mmd->renderlvl; + tmmd->totlvl = mmd->totlvl; } static DerivedMesh *multiresModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { MultiresModifierData *mmd = (MultiresModifierData*)md; - DerivedMesh *final; + DerivedMesh *result; - /* TODO: for now just skip a level1 mesh */ - if(mmd->lvl == 1) - return dm; + result = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams, isFinalCalc); - final = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams, isFinalCalc); - if(mmd->undo_signal && mmd->undo_verts && mmd->undo_verts_tot == final->getNumVerts(final)) { - int i; - MVert *dst = CDDM_get_verts(final); - for(i = 0; i < mmd->undo_verts_tot; ++i) { - copy_v3_v3(dst[i].co, mmd->undo_verts[i].co); - } - CDDM_calc_normals(final); - - MultiresDM_mark_as_modified(final); + if(result == dm) + return dm; - MEM_freeN(mmd->undo_verts); - mmd->undo_signal = 0; - mmd->undo_verts = NULL; + if(useRenderParams || !isFinalCalc) { + DerivedMesh *cddm= CDDM_copy(result); + result->release(result); + result= cddm; + } + else if(ob->mode & OB_MODE_SCULPT) { + /* would be created on the fly too, just nicer this + way on first stroke after e.g. switching levels */ + result->getPBVH(ob, result); } - return final; + return result; } /* Shrinkwrap */ @@ -8142,7 +8147,7 @@ static CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierDa return dataMask; } -static int shrinkwrapModifier_isDisabled(ModifierData *md) +static int shrinkwrapModifier_isDisabled(ModifierData *md, int useRenderParams) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; return !smd->target; @@ -8438,6 +8443,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->initData = subsurfModifier_initData; mti->copyData = subsurfModifier_copyData; mti->freeData = subsurfModifier_freeData; + mti->isDisabled = subsurfModifier_isDisabled; mti->applyModifier = subsurfModifier_applyModifier; mti->applyModifierEM = subsurfModifier_applyModifierEM; @@ -8770,7 +8776,6 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData; mti->initData = multiresModifier_initData; - mti->freeData = multiresModifier_freeData; mti->copyData = multiresModifier_copyData; mti->applyModifier = multiresModifier_applyModifier; @@ -8920,7 +8925,7 @@ int modifier_couldBeCage(ModifierData *md) return ( (md->mode & eModifierMode_Realtime) && (md->mode & eModifierMode_Editmode) && - (!mti->isDisabled || !mti->isDisabled(md)) && + (!mti->isDisabled || !mti->isDisabled(md, 0)) && modifier_supportsMapping(md)); } @@ -8957,7 +8962,7 @@ int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r, int virtual if (!(md->mode & eModifierMode_Realtime)) continue; if (!(md->mode & eModifierMode_Editmode)) continue; - if (mti->isDisabled && mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md, 0)) continue; if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue; if (md->mode & eModifierMode_DisableTemporary) continue; @@ -8999,7 +9004,7 @@ int modifier_isEnabled(ModifierData *md, int required_mode) ModifierTypeInfo *mti = modifierType_getInfo(md->type); if((md->mode & required_mode) != required_mode) return 0; - if(mti->isDisabled && mti->isDisabled(md)) return 0; + if(mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return 0; if(md->mode & eModifierMode_DisableTemporary) return 0; if(required_mode & eModifierMode_Editmode) if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index fc14afaf07f..2518d4bc3ca 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -40,6 +40,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BKE_btex.h" #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" @@ -50,14 +51,19 @@ #include "BKE_multires.h" #include "BKE_object.h" #include "BKE_subsurf.h" +#include "BKE_utildefines.h" + +#include "CCGSubSurf.h" #include #include /* MULTIRES MODIFIER */ static const int multires_max_levels = 13; -static const int multires_quad_tot[] = {4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; -static const int multires_side_tot[] = {2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; +static const int multires_grid_tot[] = {1, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; +static const int multires_side_tot[] = {1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; + +static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl); MultiresModifierData *find_multires_modifier(Object *ob) { @@ -72,23 +78,32 @@ MultiresModifierData *find_multires_modifier(Object *ob) } return mmd; +} +static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render) +{ + if(render) + return mmd->renderlvl; + else if(ob->mode == OB_MODE_SCULPT) + return mmd->sculptlvl; + else + return mmd->lvl; } -int multiresModifier_switch_level(Object *ob, const int distance) +static void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl) { - MultiresModifierData *mmd = find_multires_modifier(ob); - - if(mmd) { - mmd->lvl += distance; - if(mmd->lvl < 1) mmd->lvl = 1; - else if(mmd->lvl > mmd->totlvl) mmd->lvl = mmd->totlvl; - /* XXX: DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - object_handle_update(ob);*/ - return 1; + mmd->totlvl = lvl; + + if(ob->mode != OB_MODE_SCULPT) { + mmd->lvl = MAX2(mmd->lvl, lvl); + CLAMP(mmd->lvl, 0, mmd->totlvl); } - else - return 0; + + mmd->sculptlvl = MAX2(mmd->sculptlvl, lvl); + CLAMP(mmd->sculptlvl, 0, mmd->totlvl); + + mmd->renderlvl = MAX2(mmd->renderlvl, lvl); + CLAMP(mmd->renderlvl, 0, mmd->totlvl); } /* XXX */ @@ -156,6 +171,8 @@ void multiresModifier_join(Object *ob) /* Returns 0 on success, 1 if the src's totvert doesn't match */ int multiresModifier_reshape(MultiresModifierData *mmd, Object *dst, Object *src) { + /* XXX */ +#if 0 Mesh *src_me = get_mesh(src); DerivedMesh *mrdm = dst->derivedFinal; @@ -172,319 +189,139 @@ int multiresModifier_reshape(MultiresModifierData *mmd, Object *dst, Object *src return 0; } +#endif return 1; } -static void Mat3FromColVecs(float mat[][3], float v1[3], float v2[3], float v3[3]) +static void column_vectors_to_mat3(float mat[][3], float v1[3], float v2[3], float v3[3]) { copy_v3_v3(mat[0], v1); copy_v3_v3(mat[1], v2); copy_v3_v3(mat[2], v3); } -static DerivedMesh *multires_subdisp_pre(DerivedMesh *mrdm, int distance, int simple) +static void multires_copy_grid(float (*gridA)[3], float (*gridB)[3], int sizeA, int sizeB) { - DerivedMesh *final; - SubsurfModifierData smd; - - memset(&smd, 0, sizeof(SubsurfModifierData)); - smd.levels = distance; - if(simple) - smd.subdivType = ME_SIMPLE_SUBSURF; + int x, y, j, skip; - final = NULL; // XXX subsurf_make_derived_from_derived_with_multires(mrdm, &smd, NULL, 0, NULL, 0, 0); + if(sizeA > sizeB) { + skip = (sizeA-1)/(sizeB-1); - return final; -} + for(j = 0, y = 0; y < sizeB; y++) + for(x = 0; x < sizeB; x++, j++) + copy_v3_v3(gridA[y*skip*sizeA + x*skip], gridB[j]); + } + else { + skip = (sizeB-1)/(sizeA-1); -static void VecAddUf(float a[3], float b[3]) -{ - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; + for(j = 0, y = 0; y < sizeA; y++) + for(x = 0; x < sizeA; x++, j++) + copy_v3_v3(gridA[j], gridB[y*skip*sizeB + x*skip]); + } } -static void multires_subdisp(DerivedMesh *orig, Object *ob, DerivedMesh *final, int lvl, int totlvl, - int totsubvert, int totsubedge, int totsubface, int addverts) +static void multires_copy_dm_grid(DMGridData *gridA, DMGridData *gridB, int sizeA, int sizeB) { - DerivedMesh *mrdm; - Mesh *me = ob->data; - MultiresModifierData mmd_sub; - MVert *mvs = CDDM_get_verts(final); - MVert *mvd, *mvd_f1, *mvs_f1, *mvd_f3, *mvd_f4; - MVert *mvd_f2, *mvs_f2, *mvs_e1, *mvd_e1, *mvs_e2; - int totvert; - int slo1 = multires_side_tot[lvl - 1]; - int sll = slo1 / 2; - int slo2 = multires_side_tot[totlvl - 2]; - int shi2 = multires_side_tot[totlvl - 1]; - int skip = multires_side_tot[totlvl - lvl] - 1; - int i, j, k; - - memset(&mmd_sub, 0, sizeof(MultiresModifierData)); - mmd_sub.lvl = mmd_sub.totlvl = totlvl; - mrdm = multires_dm_create_from_derived(&mmd_sub, 1, orig, ob, 0, 0); - - mvd = CDDM_get_verts(mrdm); - /* Need to map from ccg to mrdm */ - totvert = mrdm->getNumVerts(mrdm); - - if(!addverts) { - for(i = 0; i < totvert; ++i) { - float z[3] = {0,0,0}; - copy_v3_v3(mvd[i].co, z); - } - } - - /* Load base verts */ - for(i = 0; i < me->totvert; ++i) - VecAddUf(mvd[totvert - me->totvert + i].co, mvs[totvert - me->totvert + i].co); - - mvd_f1 = mvd; - mvs_f1 = mvs; - mvd_f2 = mvd; - mvs_f2 = mvs + totvert - totsubvert; - mvs_e1 = mvs + totsubface * (skip-1) * (skip-1); - - for(i = 0; i < me->totface; ++i) { - const int end = me->mface[i].v4 ? 4 : 3; - int x, y, x2, y2, mov= 0; - - mvd_f1 += 1 + end * (slo2-2); //center+edgecross - mvd_f3 = mvd_f4 = mvd_f1; - - for(j = 0; j < end; ++j) { - mvd_f1 += (skip/2 - 1) * (slo2 - 2) + (skip/2 - 1); - /* Update sub faces */ - for(y = 0; y < sll; ++y) { - for(x = 0; x < sll; ++x) { - /* Face center */ - VecAddUf(mvd_f1->co, mvs_f1->co); - mvs_f1 += 1; - - /* Now we hold the center of the subface at mvd_f1 - and offset it to the edge cross and face verts */ - - /* Edge cross */ - for(k = 0; k < 4; ++k) { - if(k == 0) mov = -1; - else if(k == 1) mov = slo2 - 2; - else if(k == 2) mov = 1; - else if(k == 3) mov = -(slo2 - 2); - - for(x2 = 1; x2 < skip/2; ++x2) { - VecAddUf((mvd_f1 + mov * x2)->co, mvs_f1->co); - ++mvs_f1; - } - } + int x, y, j, skip; - /* Main face verts */ - for(k = 0; k < 4; ++k) { - int movx= 0, movy= 0; - - if(k == 0) { movx = -1; movy = -(slo2 - 2); } - else if(k == 1) { movx = slo2 - 2; movy = -1; } - else if(k == 2) { movx = 1; movy = slo2 - 2; } - else if(k == 3) { movx = -(slo2 - 2); movy = 1; } - - for(y2 = 1; y2 < skip/2; ++y2) { - for(x2 = 1; x2 < skip/2; ++x2) { - VecAddUf((mvd_f1 + movy * y2 + movx * x2)->co, mvs_f1->co); - ++mvs_f1; - } - } - } - - mvd_f1 += skip; - } - mvd_f1 += (skip - 1) * (slo2 - 2) - 1; - } - mvd_f1 -= (skip - 1) * (slo2 - 2) - 1 + skip; - mvd_f1 += (slo2 - 2) * (skip/2-1) + skip/2-1 + 1; - } - - /* update face center verts */ - VecAddUf(mvd_f2->co, mvs_f2->co); - - mvd_f2 += 1; - mvs_f2 += 1; - - /* update face edge verts */ - for(j = 0; j < end; ++j) { - MVert *restore; - - /* Super-face edge cross */ - for(k = 0; k < skip-1; ++k) { - VecAddUf(mvd_f2->co, mvs_e1->co); - mvd_f2++; - mvs_e1++; - } - for(x = 1; x < sll; ++x) { - VecAddUf(mvd_f2->co, mvs_f2->co); - mvd_f2++; - mvs_f2++; - - for(k = 0; k < skip-1; ++k) { - VecAddUf(mvd_f2->co, mvs_e1->co); - mvd_f2++; - mvs_e1++; - } - } - - restore = mvs_e1; - for(y = 0; y < sll - 1; ++y) { - for(x = 0; x < sll; ++x) { - for(k = 0; k < skip - 1; ++k) { - VecAddUf(mvd_f3[(skip-1)+(y*skip) + (x*skip+k)*(slo2-2)].co, - mvs_e1->co); - ++mvs_e1; - } - mvs_e1 += skip-1; - } - } - - mvs_e1 = restore + skip - 1; - for(y = 0; y < sll - 1; ++y) { - for(x = 0; x < sll; ++x) { - for(k = 0; k < skip - 1; ++k) { - VecAddUf(mvd_f3[(slo2-2)*(skip-1)+(x*skip)+k + y*skip*(slo2-2)].co, - mvs_e1->co); - ++mvs_e1; - } - mvs_e1 += skip - 1; - } - } - - mvd_f3 += (slo2-2)*(slo2-2); - mvs_e1 -= skip - 1; - } + if(sizeA > sizeB) { + skip = (sizeA-1)/(sizeB-1); - /* update base (2) face verts */ - for(j = 0; j < end; ++j) { - mvd_f2 += (slo2 - 1) * (skip - 1); - for(y = 0; y < sll - 1; ++y) { - for(x = 0; x < sll - 1; ++x) { - VecAddUf(mvd_f2->co, mvs_f2->co); - mvd_f2 += skip; - ++mvs_f2; - } - mvd_f2 += (slo2 - 1) * (skip - 1); - } - mvd_f2 -= (skip - 1); - } + for(j = 0, y = 0; y < sizeB; y++) + for(x = 0; x < sizeB; x++, j++) + copy_v3_v3(gridA[y*skip*sizeA + x*skip].co, gridB[j].co); } + else { + skip = (sizeB-1)/(sizeA-1); - /* edges */ - mvd_e1 = mvd + totvert - me->totvert - me->totedge * (shi2-2); - mvs_e2 = mvs + totvert - me->totvert - me->totedge * (slo1-2); - for(i = 0; i < me->totedge; ++i) { - for(j = 0; j < skip - 1; ++j) { - VecAddUf(mvd_e1->co, mvs_e1->co); - mvd_e1++; - mvs_e1++; - } - for(j = 0; j < slo1 - 2; j++) { - VecAddUf(mvd_e1->co, mvs_e2->co); - mvd_e1++; - mvs_e2++; - - for(k = 0; k < skip - 1; ++k) { - VecAddUf(mvd_e1->co, mvs_e1->co); - mvd_e1++; - mvs_e1++; - } - } + for(j = 0, y = 0; y < sizeA; y++) + for(x = 0; x < sizeA; x++, j++) + copy_v3_v3(gridA[j].co, gridB[y*skip*sizeB + x*skip].co); } - - final->needsFree = 1; - final->release(final); - mrdm->needsFree = 1; - MultiresDM_mark_as_modified(mrdm); - mrdm->release(mrdm); } /* direction=1 for delete higher, direction=0 for lower (not implemented yet) */ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object *ob, int direction) { Mesh *me = get_mesh(ob); - int distance = mmd->totlvl - mmd->lvl; - MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + int lvl = multires_get_level(ob, mmd, 0); + int levels = mmd->totlvl - lvl; + MDisps *mdisps; + + // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); multires_force_update(ob); - if(mdisps && distance > 0 && direction == 1) { - int skip = multires_side_tot[distance] - 1; - int st = multires_side_tot[mmd->totlvl - 1]; - int totdisp = multires_quad_tot[mmd->lvl - 1]; - int i, j, x, y; + if(mdisps && levels > 0 && direction == 1) { + int nsize = multires_side_tot[lvl]; + int hsize = multires_side_tot[mmd->totlvl]; + int i; for(i = 0; i < me->totface; ++i) { - float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires del disps"); - - for(j = 0, y = 0; y < st; y += skip) { - for(x = 0; x < st; x += skip) { - copy_v3_v3(disps[j], mdisps[i].disps[y * st + x]); - ++j; - } + MDisps *mdisp= &mdisps[i]; + float (*disps)[3], (*ndisps)[3], (*hdisps)[3]; + int nvert = (me->mface[i].v4)? 4: 3; + int totdisp = multires_grid_tot[lvl]*nvert; + int S; + + disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + + ndisps = disps; + hdisps = mdisp->disps; + + for(S = 0; S < nvert; S++) { + multires_copy_grid(ndisps, hdisps, nsize, hsize); + + ndisps += nsize*nsize; + hdisps += hsize*hsize; } - MEM_freeN(mdisps[i].disps); - mdisps[i].disps = disps; - mdisps[i].totdisp = totdisp; + MEM_freeN(mdisp->disps); + mdisp->disps = disps; + mdisp->totdisp = totdisp; } } - mmd->totlvl = mmd->lvl; + multires_set_tot_level(ob, mmd, lvl); } -void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int distance, int updateblock, int simple) +static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple) { - DerivedMesh *final = NULL; - int totsubvert = 0, totsubface = 0, totsubedge = 0; - Mesh *me = get_mesh(ob); - MDisps *mdisps; - int i; + MultiresModifierData mmd; - if(distance == 0) - return; + memset(&mmd, 0, sizeof(MultiresModifierData)); + mmd.lvl = lvl; + mmd.sculptlvl = lvl; + mmd.renderlvl = lvl; + mmd.totlvl = totlvl; + mmd.simple = simple; - if(mmd->totlvl > multires_max_levels) - mmd->totlvl = multires_max_levels; - if(mmd->lvl > multires_max_levels) - mmd->lvl = multires_max_levels; + return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0); +} - multires_force_update(ob); +static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple) +{ + SubsurfModifierData smd; - mmd->lvl = mmd->totlvl; - mmd->totlvl += distance; + memset(&smd, 0, sizeof(SubsurfModifierData)); + smd.levels = smd.renderLevels = lvl; + smd.flags |= eSubsurfModifierFlag_SubsurfUv; + if(simple) + smd.subdivType = ME_SIMPLE_SUBSURF; - mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); - if(!mdisps) - mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); + return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0); +} - if(mdisps->disps && !updateblock && mmd->totlvl > 2) { - DerivedMesh *orig, *mrdm; - MultiresModifierData mmd_sub; - - orig = CDDM_from_mesh(me, NULL); - memset(&mmd_sub, 0, sizeof(MultiresModifierData)); - mmd_sub.lvl = mmd_sub.totlvl = mmd->lvl; - mmd_sub.simple = simple; - mrdm = multires_dm_create_from_derived(&mmd_sub, 1, orig, ob, 0, 0); - totsubvert = mrdm->getNumVerts(mrdm); - totsubedge = mrdm->getNumEdges(mrdm); - totsubface = mrdm->getNumFaces(mrdm); - orig->needsFree = 1; - orig->release(orig); - - final = multires_subdisp_pre(mrdm, distance, simple); - mrdm->needsFree = 1; - mrdm->release(mrdm); - } +static void multires_reallocate_mdisps(Mesh *me, MDisps *mdisps, int lvl) +{ + int i; + /* reallocate displacements to be filled in */ for(i = 0; i < me->totface; ++i) { - const int totdisp = multires_quad_tot[mmd->totlvl - 1]; + int nvert = (me->mface[i].v4)? 4: 3; + int totdisp = multires_grid_tot[lvl]*nvert; float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); if(mdisps[i].disps) @@ -493,732 +330,353 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int dista mdisps[i].disps = disps; mdisps[i].totdisp = totdisp; } - - - if(final) { - DerivedMesh *orig; - - orig = CDDM_from_mesh(me, NULL); - - multires_subdisp(orig, ob, final, mmd->lvl, mmd->totlvl, totsubvert, totsubedge, totsubface, 0); - - orig->needsFree = 1; - orig->release(orig); - } - - mmd->lvl = mmd->totlvl; } -typedef struct DisplacerEdges { - /* DerivedMesh index at the start of each edge (using face x/y directions to define the start) */ - int base[4]; - /* 1 if edge moves in the positive x or y direction, -1 otherwise */ - int dir[4]; -} DisplacerEdges; - -typedef struct DisplacerSpill { - /* Index of face (in base mesh), -1 for none */ - int face; - - /* Spill flag */ - /* 1 = Negative variable axis */ - /* 2 = Near fixed axis */ - /* 4 = Flip axes */ - int f; - - /* Neighboring edges */ - DisplacerEdges edges; -} DisplacerSpill; - -typedef struct MultiresDisplacer { - Mesh *me; - MDisps *grid; - MFace *face; - - int dm_first_base_vert_index; - - int spacing; - int sidetot, interior_st, disp_st; - int sidendx; - int type; - int invert; - MVert *subco; - int subco_index, face_index; - float weight; - - /* Valence for each corner */ - int valence[4]; - - /* Neighboring edges for current face */ - DisplacerEdges edges_primary; - - /* Neighboring faces */ - DisplacerSpill spill_x, spill_y; - - int *face_offsets; - - int x, y, ax, ay; -} MultiresDisplacer; - -static int mface_v(MFace *f, int v) +void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple) { - return v == 0 ? f->v1 : v == 1 ? f->v2 : v == 2 ? f->v3 : v == 3 ? f->v4 : -1; -} + Mesh *me = ob->data; + MDisps *mdisps; + int lvl= mmd->totlvl; + int totlvl= mmd->totlvl+1; -/* Get the edges (and their directions) */ -static void find_displacer_edges(MultiresDisplacer *d, DerivedMesh *dm, DisplacerEdges *de, MFace *f) -{ - ListBase *emap = MultiresDM_get_vert_edge_map(dm); - IndexNode *n; - int i, end = f->v4 ? 4 : 3; - int offset = dm->getNumVerts(dm) - d->me->totvert - d->me->totedge * d->interior_st; + if(totlvl > multires_max_levels) + return; - for(i = 0; i < end; ++i) { - int vcur = mface_v(f, i); - int vnext = mface_v(f, i == end - 1 ? 0 : i + 1); + multires_force_update(ob); - de->dir[i] = 1; - - for(n = emap[vcur].first; n; n = n->next) { - MEdge *e = &d->me->medge[n->index]; - - if(e->v1 == vnext || e->v2 == vnext) { - de->base[i] = n->index * d->interior_st; - if(((i == 0 || i == 1) && e->v1 == vnext) || - ((i == 2 || i == 3) && e->v2 == vnext)) { - de->dir[i] = -1; - de->base[i] += d->interior_st - 1; - } - de->base[i] += offset; - break; - } - } - } -} + mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + if(!mdisps) + mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); -/* Returns in out the corners [0-3] that use v1 and v2 */ -static void find_face_corners(MFace *f, int v1, int v2, int out[2]) -{ - int i, end = f->v4 ? 4 : 3; - - for(i = 0; i < end; ++i) { - int corner = mface_v(f, i); - if(corner == v1) - out[0] = i; - if(corner == v2) - out[1] = i; - } -} + if(mdisps->disps && !updateblock && totlvl > 1) { + /* upsample */ + DerivedMesh *lowdm, *cddm, *highdm; + DMGridData **highGridData, **lowGridData, **subGridData; + CCGSubSurf *ss; + int i, numGrids, highGridSize, lowGridSize; + + /* create subsurf DM from original mesh at high level */ + cddm = CDDM_from_mesh(me, NULL); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple); + + /* create multires DM from original mesh at low level */ + lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple); + cddm->release(cddm); + + /* copy subsurf grids and replace them with low displaced grids */ + numGrids = highdm->getNumGrids(highdm); + highGridSize = highdm->getGridSize(highdm); + highGridData = highdm->getGridData(highdm); + lowGridSize = lowdm->getGridSize(lowdm); + lowGridData = lowdm->getGridData(lowdm); + + subGridData = MEM_callocN(sizeof(float*)*numGrids, "subGridData*"); + + for(i = 0; i < numGrids; ++i) { + /* backup subsurf grids */ + subGridData[i] = MEM_callocN(sizeof(DMGridData)*highGridSize*highGridSize, "subGridData"); + memcpy(subGridData[i], highGridData[i], sizeof(DMGridData)*highGridSize*highGridSize); + + /* overwrite with current displaced grids */ + multires_copy_dm_grid(highGridData[i], lowGridData[i], highGridSize, lowGridSize); + } -static void multires_displacer_get_spill_faces(MultiresDisplacer *d, DerivedMesh *dm, MFace *mface) -{ - ListBase *map = MultiresDM_get_vert_face_map(dm); - IndexNode *n1, *n2; - int v4 = d->face->v4 ? d->face->v4 : d->face->v1; - int crn[2], lv; + /* low lower level dm no longer needed at this point */ + lowdm->release(lowdm); - memset(&d->spill_x, 0, sizeof(DisplacerSpill)); - memset(&d->spill_y, 0, sizeof(DisplacerSpill)); - d->spill_x.face = d->spill_y.face = -1; + /* subsurf higher levels again with displaced data */ + ss= ((CCGDerivedMesh*)highdm)->ss; + ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0); + ccgSubSurf_updateLevels(ss, lvl, NULL, 0); - for(n1 = map[d->face->v3].first; n1; n1 = n1->next) { - if(n1->index == d->face_index) - continue; + /* reallocate displacements */ + multires_reallocate_mdisps(me, mdisps, totlvl); - for(n2 = map[d->face->v2].first; n2; n2 = n2->next) { - if(n1->index == n2->index) - d->spill_x.face = n1->index; - } - for(n2 = map[v4].first; n2; n2 = n2->next) { - if(n1->index == n2->index) - d->spill_y.face = n1->index; - } - } + /* compute displacements */ + multiresModifier_disp_run(highdm, me, 1, 0, subGridData, totlvl); - if(d->spill_x.face != -1) { - /* Neighbor of v2/v3 found, find flip and orientation */ - find_face_corners(&mface[d->spill_x.face], d->face->v2, d->face->v3, crn); - lv = mface[d->spill_x.face].v4 ? 3 : 2; - - if(crn[0] == 0 && crn[1] == lv) - d->spill_x.f = 0+2+0; - else if(crn[0] == lv && crn[1] == 0) - d->spill_x.f = 1+2+0; - else if(crn[0] == 1 && crn[1] == 0) - d->spill_x.f = 1+2+4; - else if(crn[0] == 0 && crn[1] == 1) - d->spill_x.f = 0+2+4; - else if(crn[0] == 2 && crn[1] == 1) - d->spill_x.f = 1+0+0; - else if(crn[0] == 1 && crn[1] == 2) - d->spill_x.f = 0+0+0; - else if(crn[0] == 3 && crn[1] == 2) - d->spill_x.f = 0+0+4; - else if(crn[0] == 2 && crn[1] == 3) - d->spill_x.f = 1+0+4; - - find_displacer_edges(d, dm, &d->spill_x.edges, &mface[d->spill_x.face]); + /* free */ + highdm->release(highdm); + for(i = 0; i < numGrids; ++i) + MEM_freeN(subGridData[i]); + MEM_freeN(subGridData); } - - if(d->spill_y.face != -1) { - /* Neighbor of v3/v4 found, find flip and orientation */ - find_face_corners(&mface[d->spill_y.face], d->face->v3, v4, crn); - lv = mface[d->spill_y.face].v4 ? 3 : 2; - - if(crn[0] == 1 && crn[1] == 0) - d->spill_y.f = 1+2+0; - else if(crn[0] == 0 && crn[1] == 1) - d->spill_y.f = 0+2+0; - else if(crn[0] == 2 && crn[1] == 1) - d->spill_y.f = 1+0+4; - else if(crn[0] == 1 && crn[1] == 2) - d->spill_y.f = 0+0+4; - else if(crn[0] == 3 && crn[1] == 2) - d->spill_y.f = 0+0+0; - else if(crn[0] == 2 && crn[1] == 3) - d->spill_y.f = 1+0+0; - else if(crn[0] == 0 && crn[1] == lv) - d->spill_y.f = 0+2+4; - else if(crn[0] == lv && crn[1] == 0) - d->spill_y.f = 1+2+4; - - find_displacer_edges(d, dm, &d->spill_y.edges, &mface[d->spill_y.face]); + else { + /* only reallocate, nothing to upsample */ + multires_reallocate_mdisps(me, mdisps, totlvl); } -} - -static void find_corner_valences(MultiresDisplacer *d, DerivedMesh *dm) -{ - int i; - - d->valence[3] = -1; - /* Set the vertex valence for the corners */ - for(i = 0; i < (d->face->v4 ? 4 : 3); ++i) - d->valence[i] = BLI_countlist(&MultiresDM_get_vert_edge_map(dm)[mface_v(d->face, i)]); + multires_set_tot_level(ob, mmd, totlvl); } -static void multires_displacer_init(MultiresDisplacer *d, DerivedMesh *dm, - const int face_index, const int invert) +static void grid_adjacent_rotate(int rotation, int gridSize, int *x, int *y) { - Mesh *me = MultiresDM_get_mesh(dm); - - d->me = me; - d->face = me->mface + face_index; - d->face_index = face_index; - d->face_offsets = MultiresDM_get_face_offsets(dm); - /* Get the multires grid from customdata */ - d->grid = CustomData_get_layer(&me->fdata, CD_MDISPS); - if(d->grid) - d->grid += face_index; - - d->spacing = pow(2, MultiresDM_get_totlvl(dm) - MultiresDM_get_lvl(dm)); - d->sidetot = multires_side_tot[MultiresDM_get_lvl(dm) - 1]; - d->interior_st = d->sidetot - 2; - d->disp_st = multires_side_tot[MultiresDM_get_totlvl(dm) - 1]; - d->invert = invert; - - multires_displacer_get_spill_faces(d, dm, me->mface); - find_displacer_edges(d, dm, &d->edges_primary, d->face); - find_corner_valences(d, dm); - - d->dm_first_base_vert_index = dm->getNumVerts(dm) - me->totvert; -} + /* we rotate (rotation * 90°) counterclockwise around center */ + int nx, ny; + + switch(rotation) { + case 0: nx = *x; ny = *y; break; + case 1: nx = *y; ny = *x; break; + case 2: nx = *x; ny = *y; break; //gridSize - 1 - *x; ny = gridSize - 1 - *y; break; + case 3: nx = *y; ny = *x; break; + } -static void multires_displacer_weight(MultiresDisplacer *d, const float w) -{ - d->weight = w; + *x = nx; + *y = ny; } -static void multires_displacer_anchor(MultiresDisplacer *d, const int type, const int side_index) +static void grid_adjacent_jump(DMGridAdjacency *adj, int gridSize, int *index, int *x, int *y) { - d->sidendx = side_index; - d->x = d->y = d->sidetot / 2; - d->type = type; - - if(type == 2) { - if(side_index == 0) - d->y -= 1; - else if(side_index == 1) - d->x += 1; - else if(side_index == 2) - d->y += 1; - else if(side_index == 3) - d->x -= 1; - } - else if(type == 3) { - if(side_index == 0) { - d->x -= 1; - d->y -= 1; + if(*x < 0) { + if(adj->index[3] == -1) { + /* no adjacent grid, clamp */ + *x = 0; } - else if(side_index == 1) { - d->x += 1; - d->y -= 1; + else { + /* jump to adjacent grid */ + *index = adj->index[3]; + *x += gridSize; + grid_adjacent_rotate(adj->rotation[3], gridSize, x, y); } - else if(side_index == 2) { - d->x += 1; - d->y += 1; + } + else if(*x >= gridSize) { + if(adj->index[1] == -1) { + /* no adjacent grid, take a step back */ + *x = gridSize - 1; } - else if(side_index == 3) { - d->x -= 1; - d->y += 1; + else { + /* jump to adjacent grid */ + *index = adj->index[1]; + *x -= gridSize; + grid_adjacent_rotate(adj->rotation[1], gridSize, x, y); } } - - d->ax = d->x; - d->ay = d->y; -} - -static void multires_displacer_anchor_edge(MultiresDisplacer *d, int v1, int v2, int x) -{ - d->type = 4; - - if(v1 == d->face->v1) { - d->x = 0; - d->y = 0; - if(v2 == d->face->v2) - d->x += x; - else if(v2 == d->face->v3) { - if(x < d->sidetot / 2) - d->y = x; - else { - d->x = x; - d->y = d->sidetot - 1; - } + else if(*y < 0) { + if(adj->index[0] == -1) { + /* no adjacent grid, clamp */ + *y = 0; } - else - d->y += x; - } - else if(v1 == d->face->v2) { - d->x = d->sidetot - 1; - d->y = 0; - if(v2 == d->face->v1) - d->x -= x; - else - d->y += x; - } - else if(v1 == d->face->v3) { - d->x = d->sidetot - 1; - d->y = d->sidetot - 1; - if(v2 == d->face->v2) - d->y -= x; - else if(v2 == d->face->v1) { - if(x < d->sidetot / 2) - d->x -= x; - else { - d->x = 0; - d->y -= x; - } + else { + /* jump to adjacent grid */ + *index = adj->index[0]; + *y += gridSize; + grid_adjacent_rotate(adj->rotation[0], gridSize, x, y); } - else - d->x -= x; } - else if(v1 == d->face->v4) { - d->x = 0; - d->y = d->sidetot - 1; - if(v2 == d->face->v3) - d->x += x; - else - d->y -= x; + else if(*y >= gridSize) { + if(adj->index[2] == -1) { + /* no adjacent grid, take a step back */ + *y = gridSize - 1; + } + else { + /* jump to adjacent grid */ + *index = adj->index[2]; + *y -= gridSize; + grid_adjacent_rotate(adj->rotation[2], gridSize, x, y); + } } } -static void multires_displacer_anchor_vert(MultiresDisplacer *d, const int v) -{ - const int e = d->sidetot - 1; - - d->type = 5; - - d->x = d->y = 0; - if(v == d->face->v2) - d->x = e; - else if(v == d->face->v3) - d->x = d->y = e; - else if(v == d->face->v4) - d->y = e; -} - -static void multires_displacer_jump(MultiresDisplacer *d) +static void grid_tangent(DMGridAdjacency *adj, int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3]) { - if(d->sidendx == 0) { - d->x -= 1; - d->y = d->ay; - } - else if(d->sidendx == 1) { - d->x = d->ax; - d->y -= 1; - } - else if(d->sidendx == 2) { - d->x += 1; - d->y = d->ay; - } - else if(d->sidendx == 3) { - d->x = d->ax; - d->y += 1; + int jindex = index, jx = x, jy = y; + + if(axis == 0) { + if(adj->index[1] == -1 && x == gridSize - 1) { + if(adj->index[2] == -1 && y == gridSize - 1) + sub_v3_v3v3(t, gridData[index][x + gridSize*(y - 1)].co, gridData[index][x - 1 + gridSize*(y - 1)].co); + else + sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x - 1 + gridSize*y].co); + } + else { + jx += 1; + grid_adjacent_jump(adj, gridSize, &jindex, &jx, &jy); + sub_v3_v3v3(t, gridData[jindex][jx + gridSize*jy].co, gridData[index][x + gridSize*y].co); + } } -} - -/* Treating v1 as (0,0) and v3 as (st-1,st-1), - returns the index of the vertex at (x,y). - If x or y is >= st, wraps over to the adjacent face, - or if there is no adjacent face, returns -2. */ -static int multires_index_at_loc(int face_index, int x, int y, MultiresDisplacer *d, DisplacerEdges *de) -{ - int coord_edge = d->sidetot - 1; /* Max value of x/y at edge of grid */ - int mid = d->sidetot / 2; - int lim = mid - 1; - int qtot = lim * lim; - int base = d->face_offsets[face_index]; - - /* Edge spillover */ - if(x == d->sidetot || y == d->sidetot) { - int flags, v_axis, f_axis, lx, ly; - - if(x == d->sidetot && d->spill_x.face != -1) { - flags = d->spill_x.f; - - /* Handle triangle seam between v1 and v3 */ - if(!d->me->mface[d->spill_x.face].v4 && - ((flags == 2 && y >= mid) || (flags == 3 && y < mid))) - flags += 2; - - v_axis = (flags & 1) ? d->sidetot - 1 - y : y; - f_axis = (flags & 2) ? 1 : d->sidetot - 2; - lx = f_axis, ly = v_axis; - - if(flags & 4) { - lx = v_axis; - ly = f_axis; + else if(axis == 1) { + if(adj->index[2] == -1 && y == gridSize - 1) { + if(adj->index[1] == -1 && x == gridSize - 1) { + sub_v3_v3v3(t, gridData[index][x - 1 + gridSize*y].co, gridData[index][x - 1 + gridSize*(y - 1)].co); } - - return multires_index_at_loc(d->spill_x.face, lx, ly, d, &d->spill_x.edges); - } - else if(y == d->sidetot && d->spill_y.face != -1) { - flags = d->spill_y.f; - - /* Handle triangle seam between v1 and v3 */ - if(!d->me->mface[d->spill_y.face].v4 && - ((flags == 6 && x >= mid) || (flags == 7 && x < mid))) - flags = ~flags; - - v_axis = (flags & 1) ? x : d->sidetot - 1 - x; - f_axis = (flags & 2) ? 1 : d->sidetot - 2; - lx = v_axis, ly = f_axis; - - if(flags & 4) { - lx = f_axis; - ly = v_axis; + else { + sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x + gridSize*(y - 1)].co); } - - return multires_index_at_loc(d->spill_y.face, lx, ly, d, &d->spill_y.edges); } - else - return -2; - } - /* Corners */ - else if(x == 0 && y == 0) - return d->dm_first_base_vert_index + d->face->v1; - else if(x == coord_edge && y == 0) - return d->dm_first_base_vert_index + d->face->v2; - else if(x == coord_edge && y == coord_edge) - return d->dm_first_base_vert_index + d->face->v3; - else if(x == 0 && y == coord_edge) - return d->dm_first_base_vert_index + d->face->v4; - /* Edges */ - else if(x == 0) { - if(d->face->v4) - return de->base[3] + de->dir[3] * (y - 1); - else - return de->base[2] + de->dir[2] * (y - 1); - } - else if(y == 0) - return de->base[0] + de->dir[0] * (x - 1); - else if(x == d->sidetot - 1) - return de->base[1] + de->dir[1] * (y - 1); - else if(y == d->sidetot - 1) - return de->base[2] + de->dir[2] * (x - 1); - /* Face center */ - else if(x == mid && y == mid) - return base; - /* Cross */ - else if(x == mid && y < mid) - return base + (mid - y); - else if(y == mid && x > mid) - return base + lim + (x - mid); - else if(x == mid && y > mid) - return base + lim*2 + (y - mid); - else if(y == mid && x < mid) { - if(d->face->v4) - return base + lim*3 + (mid - x); - else - return base + lim*2 + (mid - x); - } - /* Quarters */ - else { - int offset = base + lim * (d->face->v4 ? 4 : 3); - if(x < mid && y < mid) - return offset + ((mid - x - 1)*lim + (mid - y)); - else if(x > mid && y < mid) - return offset + qtot + ((mid - y - 1)*lim + (x - mid)); - else if(x > mid && y > mid) - return offset + qtot*2 + ((x - mid - 1)*lim + (y - mid)); - else if(x < mid && y > mid) - return offset + qtot*3 + ((y - mid - 1)*lim + (mid - x)); - } - - return -1; -} - -/* Calculate the TS matrix used for applying displacements. - Uses the undisplaced subdivided mesh's curvature to find a - smoothly normal and tangents. */ -static void calc_disp_mat(MultiresDisplacer *d, float mat[3][3]) -{ - int u = multires_index_at_loc(d->face_index, d->x + 1, d->y, d, &d->edges_primary); - int v = multires_index_at_loc(d->face_index, d->x, d->y + 1, d, &d->edges_primary); - float norm[3], t1[3], t2[3], inv[3][3]; - MVert *base = d->subco + d->subco_index; - - //printf("f=%d, x=%d, y=%d, i=%d, u=%d, v=%d ", d->face_index, d->x, d->y, d->subco_index, u, v); - - norm[0] = base->no[0] / 32767.0f; - norm[1] = base->no[1] / 32767.0f; - norm[2] = base->no[2] / 32767.0f; - - /* Special handling for vertices of valence 3 */ - if(d->valence[1] == 3 && d->x == d->sidetot - 1 && d->y == 0) - u = -1; - else if(d->valence[2] == 3 && d->x == d->sidetot - 1 && d->y == d->sidetot - 1) - u = v = -1; - else if(d->valence[3] == 3 && d->x == 0 && d->y == d->sidetot - 1) - v = -1; - - /* If either u or v is -2, it's on a boundary. In this - case, back up by one row/column and use the same - vector as the preceeding sub-edge. */ - - if(u < 0) { - u = multires_index_at_loc(d->face_index, d->x - 1, d->y, d, &d->edges_primary); - sub_v3_v3v3(t1, base->co, d->subco[u].co); - } - else - sub_v3_v3v3(t1, d->subco[u].co, base->co); - - if(v < 0) { - v = multires_index_at_loc(d->face_index, d->x, d->y - 1, d, &d->edges_primary); - sub_v3_v3v3(t2, base->co, d->subco[v].co); - } - else - sub_v3_v3v3(t2, d->subco[v].co, base->co); - - //printf("uu=%d, vv=%d\n", u, v); - - normalize_v3(t1); - normalize_v3(t2); - Mat3FromColVecs(mat, t1, t2, norm); - - if(d->invert) { - invert_m3_m3(inv, mat); - copy_m3_m3(mat, inv); + else { + jy += 1; + grid_adjacent_jump(adj, gridSize, &jindex, &jx, &jy); + sub_v3_v3v3(t, gridData[jindex][jx + gridSize*jy].co, gridData[index][x + gridSize*y].co); + } } } -static void multires_displace(MultiresDisplacer *d, float co[3]) +static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl) { - float disp[3], mat[3][3]; - float *data; - MVert *subco = &d->subco[d->subco_index]; - - if(!d->grid || !d->grid->disps) return; - - data = d->grid->disps[(d->y * d->spacing) * d->disp_st + (d->x * d->spacing)]; - - if(d->invert) - sub_v3_v3v3(disp, co, subco->co); - else - copy_v3_v3(disp, data); - - - /* Apply ts matrix to displacement */ - calc_disp_mat(d, mat); - mul_m3_v3(mat, disp); - - if(d->invert) { - copy_v3_v3(data, disp); - - } - else { - if(d->type == 4 || d->type == 5) - mul_v3_fl(disp, d->weight); - add_v3_v3v3(co, co, disp); - } + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; + DMGridData **gridData, **subGridData; + DMGridAdjacency *gridAdjacency; + MFace *mface = me->mface; + MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + int i, S, x, y, numGrids, gIndex, gridSize, dGridSize, dSkip; - if(d->type == 2) { - if(d->sidendx == 0) - d->y -= 1; - else if(d->sidendx == 1) - d->x += 1; - else if(d->sidendx == 2) - d->y += 1; - else if(d->sidendx == 3) - d->x -= 1; - } - else if(d->type == 3) { - if(d->sidendx == 0) - d->y -= 1; - else if(d->sidendx == 1) - d->x += 1; - else if(d->sidendx == 2) - d->y += 1; - else if(d->sidendx == 3) - d->x -= 1; - } -} + numGrids = dm->getNumGrids(dm); + gridSize = dm->getGridSize(dm); + gridData = dm->getGridData(dm); + gridAdjacency = dm->getGridAdjacency(dm); + subGridData = (oldGridData)? oldGridData: gridData; -static void multiresModifier_disp_run(DerivedMesh *dm, MVert *subco, int invert) -{ - const int lvl = MultiresDM_get_lvl(dm); - const int gridFaces = multires_side_tot[lvl - 2] - 1; - const int edgeSize = multires_side_tot[lvl - 1] - 1; - MVert *mvert = CDDM_get_verts(dm); - MEdge *medge = MultiresDM_get_mesh(dm)->medge; - MFace *mface = MultiresDM_get_mesh(dm)->mface; - ListBase *map = MultiresDM_get_vert_face_map(dm); - Mesh *me = MultiresDM_get_mesh(dm); - MultiresDisplacer d; - int i, S, x, y; - - d.subco = subco; - d.subco_index = 0; + dGridSize = multires_side_tot[totlvl]; + dSkip = (dGridSize-1)/(gridSize-1); - for(i = 0; i < me->totface; ++i) { + for(gIndex = 0, i = 0; i < me->totface; ++i) { const int numVerts = mface[i].v4 ? 4 : 3; - - /* Center */ - multires_displacer_init(&d, dm, i, invert); - multires_displacer_anchor(&d, 1, 0); - multires_displace(&d, mvert->co); - ++mvert; - ++d.subco_index; - - /* Cross */ - for(S = 0; S < numVerts; ++S) { - multires_displacer_anchor(&d, 2, S); - for(x = 1; x < gridFaces; ++x) { - multires_displace(&d, mvert->co); - ++mvert; - ++d.subco_index; - } - } - - /* Quarters */ - for(S = 0; S < numVerts; S++) { - multires_displacer_anchor(&d, 3, S); - for(y = 1; y < gridFaces; y++) { - for(x = 1; x < gridFaces; x++) { - multires_displace(&d, mvert->co); - ++mvert; - ++d.subco_index; - } - multires_displacer_jump(&d); - } - } - } - - for(i = 0; i < me->totedge; ++i) { - const MEdge *e = &medge[i]; - for(x = 1; x < edgeSize; ++x) { - IndexNode *n1, *n2; - int numFaces = 0; - for(n1 = map[e->v1].first; n1; n1 = n1->next) { - for(n2 = map[e->v2].first; n2; n2 = n2->next) { - if(n1->index == n2->index) - ++numFaces; - } - } - multires_displacer_weight(&d, 1.0f / numFaces); - /* TODO: Better to have these loops outside the x loop */ - for(n1 = map[e->v1].first; n1; n1 = n1->next) { - for(n2 = map[e->v2].first; n2; n2 = n2->next) { - if(n1->index == n2->index) { - multires_displacer_init(&d, dm, n1->index, invert); - multires_displacer_anchor_edge(&d, e->v1, e->v2, x); - multires_displace(&d, mvert->co); + MDisps *mdisp = &mdisps[i]; + + for(S = 0; S < numVerts; ++S, ++gIndex) { + DMGridData *grid = gridData[gIndex]; + DMGridData *subgrid = subGridData[gIndex]; + DMGridAdjacency *adj = &gridAdjacency[gIndex]; + float (*dispgrid)[3] = &mdisp->disps[S*dGridSize*dGridSize]; + + for(y = 0; y < gridSize; y++) { + for(x = 0; x < gridSize; x++) { + float *co = grid[x + y*gridSize].co; + float *sco = subgrid[x + y*gridSize].co; + float *no = subgrid[x + y*gridSize].no; + float *data = dispgrid[dGridSize*y*dSkip + x*dSkip]; + float mat[3][3], tx[3], ty[3], disp[3], d[3]; + + /* construct tangent space matrix */ + grid_tangent(adj, gridSize, gIndex, x, y, 0, subGridData, tx); + normalize_v3(tx); + + grid_tangent(adj, gridSize, gIndex, x, y, 1, subGridData, ty); + normalize_v3(ty); + + column_vectors_to_mat3(mat, tx, ty, no); + + if(!invert) { + /* convert to object space and add */ + mul_v3_m3v3(disp, mat, data); + add_v3_v3v3(co, sco, disp); + } + else if(!add) { + /* convert difference to tangent space */ + sub_v3_v3v3(disp, co, sco); + invert_m3(mat); + mul_v3_m3v3(data, mat, disp); + } + else { + /* convert difference to tangent space */ + invert_m3(mat); + mul_v3_m3v3(d, mat, co); + add_v3_v3(data, d); } } } - ++mvert; - ++d.subco_index; - } - } - - for(i = 0; i < me->totvert; ++i) { - IndexNode *n; - multires_displacer_weight(&d, 1.0f / BLI_countlist(&map[i])); - for(n = map[i].first; n; n = n->next) { - multires_displacer_init(&d, dm, n->index, invert); - multires_displacer_anchor_vert(&d, i); - multires_displace(&d, mvert->co); } - ++mvert; - ++d.subco_index; } - if(!invert) - CDDM_calc_normals(dm); + if(!invert) { + ccgSubSurf_stitchFaces(ccgdm->ss, 0, NULL, 0); + ccgSubSurf_updateNormals(ccgdm->ss, NULL, 0); + } } static void multiresModifier_update(DerivedMesh *dm) { + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; Object *ob; Mesh *me; MDisps *mdisps; + MultiresModifierData *mmd; - ob = MultiresDM_get_object(dm); - me = MultiresDM_get_mesh(dm); + ob = ccgdm->multires.ob; + me = ccgdm->multires.ob->data; + mmd = ccgdm->multires.mmd; + // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); if(mdisps) { - const int lvl = MultiresDM_get_lvl(dm); - const int totlvl = MultiresDM_get_totlvl(dm); + int lvl = ccgdm->multires.lvl; + int totlvl = ccgdm->multires.totlvl; if(lvl < totlvl) { - /* Propagate disps upwards */ - DerivedMesh *final, *subco_dm, *orig; - MVert *verts_new = NULL, *cur_lvl_orig_verts = NULL; - MultiresModifierData mmd; - int i; - - orig = CDDM_from_mesh(me, NULL); - - /* Regenerate the current level's vertex coordinates - (includes older displacements but not new sculpts) */ - mmd.totlvl = totlvl; - mmd.lvl = lvl; - subco_dm = multires_dm_create_from_derived(&mmd, 1, orig, ob, 0, 0); - cur_lvl_orig_verts = CDDM_get_verts(subco_dm); - - /* Subtract the original vertex cos from the new vertex cos */ - verts_new = CDDM_get_verts(dm); - for(i = 0; i < dm->getNumVerts(dm); ++i) - sub_v3_v3v3(verts_new[i].co, verts_new[i].co, cur_lvl_orig_verts[i].co); - - final = multires_subdisp_pre(dm, totlvl - lvl, 0); - - multires_subdisp(orig, ob, final, lvl, totlvl, dm->getNumVerts(dm), dm->getNumEdges(dm), - dm->getNumFaces(dm), 1); - - subco_dm->release(subco_dm); - orig->release(orig); + Mesh *me = ob->data; + DerivedMesh *lowdm, *cddm, *highdm; + DMGridData **highGridData, **lowGridData, **subGridData, **gridData, *diffGrid; + CCGSubSurf *ss; + int i, j, numGrids, highGridSize, lowGridSize; + + /* create subsurf DM from original mesh at high level */ + cddm = CDDM_from_mesh(me, NULL); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple); + + /* create multires DM from original mesh and displacements */ + lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple); + cddm->release(cddm); + + /* gather grid data */ + numGrids = highdm->getNumGrids(highdm); + highGridSize = highdm->getGridSize(highdm); + highGridData = highdm->getGridData(highdm); + lowGridSize = lowdm->getGridSize(lowdm); + lowGridData = lowdm->getGridData(lowdm); + gridData = dm->getGridData(dm); + + subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*"); + diffGrid = MEM_callocN(sizeof(DMGridData)*lowGridSize*lowGridSize, "diff"); + + for(i = 0; i < numGrids; ++i) { + /* backup subsurf grids */ + subGridData[i] = MEM_callocN(sizeof(DMGridData)*highGridSize*highGridSize, "subGridData"); + memcpy(subGridData[i], highGridData[i], sizeof(DMGridData)*highGridSize*highGridSize); + + /* write difference of subsurf and displaced low level into high subsurf */ + for(j = 0; j < lowGridSize*lowGridSize; ++j) + sub_v3_v3v3(diffGrid[j].co, gridData[i][j].co, lowGridData[i][j].co); + + multires_copy_dm_grid(highGridData[i], diffGrid, highGridSize, lowGridSize); + } + + /* lower level dm no longer needed at this point */ + MEM_freeN(diffGrid); + lowdm->release(lowdm); + + /* subsurf higher levels again with difference of coordinates */ + ss= ((CCGDerivedMesh*)highdm)->ss; + ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0); + ccgSubSurf_updateLevels(ss, lvl, NULL, 0); + + /* add to displacements */ + multiresModifier_disp_run(highdm, me, 1, 1, subGridData, mmd->totlvl); + + /* free */ + highdm->release(highdm); + for(i = 0; i < numGrids; ++i) + MEM_freeN(subGridData[i]); + MEM_freeN(subGridData); + } + else { + DerivedMesh *cddm, *subdm; + + cddm = CDDM_from_mesh(me, NULL); + subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple); + cddm->release(cddm); + + multiresModifier_disp_run(dm, me, 1, 0, subdm->getGridData(subdm), mmd->totlvl); + + subdm->release(subdm); } - else - multiresModifier_disp_run(dm, MultiresDM_get_subco(dm), 1); } } void multires_mark_as_modified(struct Object *ob) { if(ob && ob->derivedFinal) { - MultiresDM_mark_as_modified(ob->derivedFinal); + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)ob->derivedFinal; + ccgdm->multires.modified = 1; } } @@ -1234,24 +692,47 @@ void multires_force_update(Object *ob) struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob, int useRenderParams, int isFinalCalc) { - SubsurfModifierData smd; - MultiresSubsurf ms; + //Mesh *me= ob->data; DerivedMesh *result; - int i; + CCGDerivedMesh *ccgdm; + DMGridData **gridData, **subGridData; + int lvl= multires_get_level(ob, mmd, useRenderParams); + int i, gridSize, numGrids; + + if(lvl == 0) + return dm; + + result = subsurf_dm_create_local(ob, dm, lvl, 0); + + if(!local_mmd) { + ccgdm = (CCGDerivedMesh*)result; + + ccgdm->multires.ob = ob; + ccgdm->multires.mmd = mmd; + ccgdm->multires.local_mmd = local_mmd; + ccgdm->multires.lvl = lvl; + ccgdm->multires.totlvl = mmd->totlvl; + ccgdm->multires.modified = 0; + ccgdm->multires.update = multiresModifier_update; + } - ms.mmd = mmd; - ms.ob = ob; - ms.local_mmd = local_mmd; + numGrids = result->getNumGrids(result); + gridSize = result->getGridSize(result); + gridData = result->getGridData(result); - memset(&smd, 0, sizeof(SubsurfModifierData)); - smd.levels = smd.renderLevels = mmd->lvl - 1; - smd.flags |= eSubsurfModifierFlag_SubsurfUv; + subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*"); - result = NULL; // XXX subsurf_make_derived_from_derived_with_multires(dm, &smd, &ms, useRenderParams, NULL, isFinalCalc, 0); - for(i = 0; i < result->getNumVerts(result); ++i) - MultiresDM_get_subco(result)[i] = CDDM_get_verts(result)[i]; - multiresModifier_disp_run(result, MultiresDM_get_subco(result), 0); - MultiresDM_set_update(result, multiresModifier_update); + for(i = 0; i < numGrids; i++) { + subGridData[i] = MEM_callocN(sizeof(DMGridData)*gridSize*gridSize, "subGridData"); + memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize); + } + + // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl); + + for(i = 0; i < numGrids; i++) + MEM_freeN(subGridData[i]); + MEM_freeN(subGridData); return result; } @@ -1425,9 +906,9 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) MultiresLevel *lvl, *lvl1; MVert *vsrc, *vdst; int src, dst; - int totlvl = MultiresDM_get_totlvl(dm); - int st = multires_side_tot[totlvl - 2] - 1; - int extedgelen = multires_side_tot[totlvl - 1] - 2; + int totlvl = 2; // XXX MultiresDM_get_totlvl(dm); + int st = multires_side_tot[totlvl - 1] - 1; + int extedgelen = multires_side_tot[totlvl] - 2; int *vvmap; // inorder for dst, map to src int crossedgelen; int i, j, s, x, totvert, tottri, totquad; @@ -1454,9 +935,9 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) lvl = lvl1->next; for(j = 2; j <= mr->level_count; ++j) { - int base = multires_side_tot[totlvl - j] - 2; - int skip = multires_side_tot[totlvl - j + 1] - 1; - int st = multires_side_tot[j - 2] - 1; + int base = multires_side_tot[totlvl - j + 1] - 2; + int skip = multires_side_tot[totlvl - j + 2] - 1; + int st = multires_side_tot[j - 1] - 1; for(x = 0; x < st; ++x) vvmap[ldst + base + x * skip] = lsrc + st * i + x; @@ -1483,7 +964,7 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) /* Face edge cross */ tottri = totquad = 0; - crossedgelen = multires_side_tot[totlvl - 2] - 2; + crossedgelen = multires_side_tot[totlvl - 1] - 2; dst = 0; for(i = 0; i < lvl1->totface; ++i) { int sides = lvl1->faces[i].v[3] ? 4 : 3; @@ -1492,8 +973,8 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) ++dst; for(j = 3; j <= mr->level_count; ++j) { - int base = multires_side_tot[totlvl - j] - 2; - int skip = multires_side_tot[totlvl - j + 1] - 1; + int base = multires_side_tot[totlvl - j + 1] - 2; + int skip = multires_side_tot[totlvl - j + 2] - 1; int st = pow(2, j - 2); int st2 = pow(2, j - 3); int lsrc = lvl->prev->totvert; @@ -1541,8 +1022,8 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) int ldst = dst + 1 + sides * (st - 1); for(s = 0; s < sides; ++s) { - int st2 = multires_side_tot[totlvl - 2] - 2; - int st3 = multires_side_tot[totlvl - 3] - 2; + int st2 = multires_side_tot[totlvl - 1] - 2; + int st3 = multires_side_tot[totlvl - 2] - 2; int st4 = st3 == 0 ? 1 : (st3 + 1) / 2; int mid = ldst + st2 * st3 + st3; int cv = lvl1->faces[j].v[s]; @@ -1583,3 +1064,4 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) MEM_freeN(vvmap); } + -- cgit v1.2.3 From 436969ce49bc17573e8f87a87ef89d1d036d5f4e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 25 Nov 2009 14:13:43 +0000 Subject: Sculpt: Fast Navigate option for multires. This will show the lowest multires level when rotating/panning/zooming the viewport, and only draw the full thing at the end, to make the viewport more interactive. --- source/blender/blenkernel/BKE_DerivedMesh.h | 2 +- source/blender/blenkernel/intern/cdderivedmesh.c | 2 +- source/blender/blenkernel/intern/subsurf_ccg.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 6bce7575556..bb14ac7e803 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -232,7 +232,7 @@ struct DerivedMesh { * Also called for *final* editmode DerivedMeshes */ void (*drawFacesSolid)(DerivedMesh *dm, float (*partial_redraw_planes)[4], - int (*setMaterial)(int, void *attribs)); + int fast, int (*setMaterial)(int, void *attribs)); /* Draw all faces * o If useTwoSided, draw front and back using col arrays diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index b3e75549028..77ad9fb7a7b 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -395,7 +395,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) static void cdDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], - int (*setMaterial)(int, void *attribs)) + int fast, int (*setMaterial)(int, void *attribs)) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mvert = cddm->mvert; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 30766931a0b..716229e6ead 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1223,15 +1223,15 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) } /* Only used by non-editmesh types */ -static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4]/*, int fast*/, int (*setMaterial)(int, void *attribs)) { +static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int fast, int (*setMaterial)(int, void *attribs)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; CCGFaceIterator *fi; int gridSize = ccgSubSurf_getGridSize(ss); char *faceFlags = ccgdm->faceFlags; - int step = 1; //(fast)? gridSize-1: 1; + int step = (fast)? gridSize-1: 1; - if(ccgdm->pbvh && ccgdm->multires.mmd) { // && !fast) { + if(ccgdm->pbvh && ccgdm->multires.mmd && !fast) { CCGFace **faces; int totface; -- cgit v1.2.3 From 077edbb384e3845f27cc06618046a08c7101cc4c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 25 Nov 2009 14:27:50 +0000 Subject: Sculpt: external file storage for multires * This is experimental, the file format may change still! * Helps reduce memory usage, keeps .blend files smaller, and makes saving quicker when not editing multires. * This is implemented at the customdata level, currently only the multires displacements can be stored externally. ToDo * Better integration with object duplication/removal/.. * Memory is not yet freed when exiting sculpt mode. * Loading only lower levels is not supported yet. --- source/blender/blenkernel/BKE_btex.h | 64 ++++ source/blender/blenkernel/BKE_customdata.h | 16 + source/blender/blenkernel/intern/btex.c | 482 ++++++++++++++++++++++++++ source/blender/blenkernel/intern/customdata.c | 305 +++++++++++++++- source/blender/blenkernel/intern/multires.c | 8 +- source/blender/blenkernel/intern/pointcache.c | 9 +- 6 files changed, 865 insertions(+), 19 deletions(-) create mode 100644 source/blender/blenkernel/BKE_btex.h create mode 100644 source/blender/blenkernel/intern/btex.c (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_btex.h b/source/blender/blenkernel/BKE_btex.h new file mode 100644 index 00000000000..cb73fd160d7 --- /dev/null +++ b/source/blender/blenkernel/BKE_btex.h @@ -0,0 +1,64 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BKE_BTEX_H +#define BKE_BTEX_H + +#define BTEX_TYPE_IMAGE 0 +#define BTEX_TYPE_MESH 1 + +#define BTEX_LAYER_NAME_MAX 64 + +typedef struct BTex BTex; +typedef struct BTexLayer BTexLayer; + +/* Create/Free */ + +BTex *btex_create(int type); +void btex_free(BTex *btex); + +/* File read/write/remove */ + +int btex_read_open(BTex *btex, char *filename); +int btex_read_layer(BTex *btex, BTexLayer *blay); +int btex_read_data(BTex *btex, int size, void *data); +void btex_read_close(BTex *btex); + +int btex_write_open(BTex *btex, char *filename); +int btex_write_layer(BTex *btex, BTexLayer *blay); +int btex_write_data(BTex *btex, int size, void *data); +void btex_write_close(BTex *btex); + +void btex_remove(char *filename); + +/* Layers */ + +BTexLayer *btex_layer_find(BTex *btex, int type, char *name); +BTexLayer *btex_layer_add(BTex *btex, int type, char *name); +void btex_layer_remove(BTex *btex, BTexLayer *blay); + +/* Mesh */ + +void btex_mesh_set_grids(BTex *btex, int totgrid, int gridsize, int datasize); + +#endif /* BKE_BTEX_H */ + diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 95ee918a888..5ce4b396f0e 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -278,4 +278,20 @@ int CustomData_verify_versions(struct CustomData *data, int index); void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total); void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize); + +/* External file storage */ + +void CustomData_external_add(struct CustomData *data, + int type, const char *name, int totelem); +void CustomData_external_remove(struct CustomData *data, + int type, int totelem); +void CustomData_external_remove_object(struct CustomData *data); +int CustomData_external_test(struct CustomData *data, int type); + +void CustomData_external_write(struct CustomData *data, + CustomDataMask mask, int totelem, int free); +void CustomData_external_read(struct CustomData *data, + CustomDataMask mask, int totelem); + #endif + diff --git a/source/blender/blenkernel/intern/btex.c b/source/blender/blenkernel/intern/btex.c new file mode 100644 index 00000000000..363e515f6e2 --- /dev/null +++ b/source/blender/blenkernel/intern/btex.c @@ -0,0 +1,482 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_fileops.h" +#include "BLI_string.h" + +#include "BKE_btex.h" +#include "BKE_global.h" +#include "BKE_utildefines.h" + +/************************* File Format Definitions ***************************/ + +#define BTEX_ENDIAN_LITTLE 0 +#define BTEX_ENDIAN_BIG 1 + +#define BTEX_DATA_FLOAT 0 + +typedef struct BTexHeader { + char ID[4]; /* "BTEX" */ + char endian; /* little, big */ + char version; /* non-compatible versions */ + char subversion; /* compatible sub versions */ + char pad; /* padding */ + + int structbytes; /* size of this struct in bytes */ + int type; /* image, mesh */ + int totlayer; /* number of layers in the file */ +} BTexHeader; + +typedef struct BTexImageHeader { + int structbytes; /* size of this struct in bytes */ + int width; /* image width */ + int height; /* image height */ + int tile_size; /* tile size (required power of 2) */ +} BTexImageHeader; + +typedef struct BTexMeshHeader { + int structbytes; /* size of this struct in bytes */ + int totgrid; /* number of grids */ + int gridsize; /* width of grids */ +} BTexMeshHeader; + +struct BTexLayer { + int structbytes; /* size of this struct in bytes */ + int datatype; /* only float for now */ + int datasize; /* size of data in layer */ + int type; /* layer type */ + char name[BTEX_LAYER_NAME_MAX]; /* layer name */ +}; + +/**************************** Other Definitions ******************************/ + +#define BTEX_VERSION 0 +#define BTEX_SUBVERSION 0 +#define BTEX_TILE_SIZE 64 + +struct BTex { + int type; + + BTexHeader header; + union { + BTexImageHeader image; + BTexMeshHeader mesh; + } btype; + + BTexLayer *layer; + int totlayer; + + FILE *readf; + FILE *writef; + int switchendian; + size_t dataoffset; +}; + +/********************************* Create/Free *******************************/ + +static int btex_endian(void) +{ + if(ENDIAN_ORDER == L_ENDIAN) + return BTEX_ENDIAN_LITTLE; + else + return BTEX_ENDIAN_BIG; +} + +/*static int btex_data_type_size(int datatype) +{ + if(datatype == BTEX_DATA_FLOAT) + return sizeof(float); + + return 0; +}*/ + +BTex *btex_create(int type) +{ + BTex *btex= MEM_callocN(sizeof(BTex), "BTex"); + + btex->type= type; + + return btex; +} + +void btex_free(BTex *btex) +{ + btex_read_close(btex); + btex_write_close(btex); + + if(btex->layer) + MEM_freeN(btex->layer); + + MEM_freeN(btex); +} + +/********************************* Read/Write ********************************/ + +static int btex_read_header(BTex *btex) +{ + BTexHeader *header; + BTexImageHeader *image; + BTexMeshHeader *mesh; + BTexLayer *layer; + FILE *f= btex->readf; + size_t offset = 0; + int a; + + header= &btex->header; + + if(!fread(header, sizeof(BTexHeader), 1, btex->readf)) + return 0; + + if(memcmp(header->ID, "BTEX", sizeof(header->ID)) != 0) + return 0; + if(header->version > BTEX_VERSION) + return 0; + + btex->switchendian= header->endian != btex_endian(); + header->endian= btex_endian(); + + if(btex->switchendian) { + SWITCH_INT(header->type); + SWITCH_INT(header->totlayer); + SWITCH_INT(header->structbytes); + } + + if(!ELEM(header->type, BTEX_TYPE_IMAGE, BTEX_TYPE_MESH)) + return 0; + + offset += header->structbytes; + header->structbytes= sizeof(BTexHeader); + + if(fseek(f, offset, SEEK_SET) != 0) + return 0; + + if(header->type == BTEX_TYPE_IMAGE) { + image= &btex->btype.image; + if(!fread(image, sizeof(BTexImageHeader), 1, f)) + return 0; + + if(btex->switchendian) { + SWITCH_INT(image->width); + SWITCH_INT(image->height); + SWITCH_INT(image->tile_size); + SWITCH_INT(image->structbytes); + } + + offset += image->structbytes; + image->structbytes= sizeof(BTexImageHeader); + } + else if(header->type == BTEX_TYPE_MESH) { + mesh= &btex->btype.mesh; + if(!fread(mesh, sizeof(BTexMeshHeader), 1, f)) + return 0; + + if(btex->switchendian) { + SWITCH_INT(mesh->totgrid); + SWITCH_INT(mesh->gridsize); + SWITCH_INT(mesh->structbytes); + } + + offset += mesh->structbytes; + mesh->structbytes= sizeof(BTexMeshHeader); + } + + if(fseek(f, offset, SEEK_SET) != 0) + return 0; + + btex->layer= MEM_callocN(sizeof(BTexLayer)*header->totlayer, "BTexLayer"); + btex->totlayer= header->totlayer; + + for(a=0; atotlayer; a++) { + layer= &btex->layer[a]; + + if(!fread(layer, sizeof(BTexLayer), 1, f)) + return 0; + + if(btex->switchendian) { + SWITCH_INT(layer->type); + SWITCH_INT(layer->datatype); + SWITCH_INT(layer->datasize); + SWITCH_INT(layer->structbytes); + } + + if(layer->datatype != BTEX_DATA_FLOAT) + return 0; + + offset += layer->structbytes; + layer->structbytes= sizeof(BTexLayer); + + if(fseek(f, offset, SEEK_SET) != 0) + return 0; + } + + btex->dataoffset= offset; + + return 1; +} + +static int btex_write_header(BTex *btex) +{ + BTexHeader *header; + BTexImageHeader *image; + BTexMeshHeader *mesh; + BTexLayer *layer; + FILE *f= btex->writef; + int a; + + header= &btex->header; + + if(!fwrite(header, sizeof(BTexHeader), 1, f)) + return 0; + + if(header->type == BTEX_TYPE_IMAGE) { + image= &btex->btype.image; + if(!fwrite(image, sizeof(BTexImageHeader), 1, f)) + return 0; + } + else if(header->type == BTEX_TYPE_MESH) { + mesh= &btex->btype.mesh; + if(!fwrite(mesh, sizeof(BTexMeshHeader), 1, f)) + return 0; + } + + for(a=0; atotlayer; a++) { + layer= &btex->layer[a]; + + if(!fwrite(layer, sizeof(BTexLayer), 1, f)) + return 0; + } + + return 1; +} + +int btex_read_open(BTex *btex, char *filename) +{ + FILE *f; + + f= fopen(filename, "rb"); + if(!f) + return 0; + + btex->readf= f; + + if(!btex_read_header(btex)) { + btex_read_close(btex); + return 0; + } + + if(btex->header.type != btex->type) { + btex_read_close(btex); + return 0; + } + + return 1; +} + +int btex_read_layer(BTex *btex, BTexLayer *blay) +{ + size_t offset; + int a; + + /* seek to right location in file */ + offset= btex->dataoffset; + for(a=0; atotlayer; a++) { + if(&btex->layer[a] == blay) + break; + else + offset += btex->layer[a].datasize; + } + + return (fseek(btex->readf, offset, SEEK_SET) == 0); +} + +int btex_read_data(BTex *btex, int size, void *data) +{ + float *fdata; + int a; + + /* read data */ + if(!fread(data, size, 1, btex->readf)) + return 0; + + /* switch endian if necessary */ + if(btex->switchendian) { + fdata= data; + + for(a=0; areadf) { + fclose(btex->readf); + btex->readf= NULL; + } +} + +int btex_write_open(BTex *btex, char *filename) +{ + BTexHeader *header; + BTexImageHeader *image; + BTexMeshHeader *mesh; + FILE *f; + + f= fopen(filename, "wb"); + if(!f) + return 0; + + btex->writef= f; + + /* fill header */ + header= &btex->header; + strcpy(header->ID, "BTEX"); + header->endian= btex_endian(); + header->version= BTEX_VERSION; + header->subversion= BTEX_SUBVERSION; + + header->structbytes= sizeof(BTexHeader); + header->type= btex->type; + header->totlayer= btex->totlayer; + + if(btex->type == BTEX_TYPE_IMAGE) { + /* fill image header */ + image= &btex->btype.image; + image->structbytes= sizeof(BTexImageHeader); + image->tile_size= BTEX_TILE_SIZE; + } + else if(btex->type == BTEX_TYPE_MESH) { + /* fill mesh header */ + mesh= &btex->btype.mesh; + mesh->structbytes= sizeof(BTexMeshHeader); + } + + btex_write_header(btex); + + return 1; +} + +int btex_write_layer(BTex *btex, BTexLayer *blay) +{ + return 1; +} + +int btex_write_data(BTex *btex, int size, void *data) +{ + /* write data */ + if(!fwrite(data, size, 1, btex->writef)) + return 0; + + return 1; +} + +void btex_write_close(BTex *btex) +{ + if(btex->writef) { + fclose(btex->writef); + btex->writef= NULL; + } +} + +void btex_remove(char *filename) +{ + BLI_delete(filename, 0, 0); +} + +/********************************** Layers ***********************************/ + +BTexLayer *btex_layer_find(BTex *btex, int type, char *name) +{ + BTexLayer *layer; + int a; + + for(a=0; atotlayer; a++) { + layer= &btex->layer[a]; + + if(layer->type == type && strcmp(layer->name, name) == 0) + return layer; + } + + return NULL; +} + +BTexLayer *btex_layer_add(BTex *btex, int type, char *name) +{ + BTexLayer *newlayer, *layer; + + /* expand array */ + newlayer= MEM_callocN(sizeof(BTexLayer)*(btex->totlayer+1), "BTexLayer"); + memcpy(newlayer, btex->layer, sizeof(BTexLayer)*btex->totlayer); + btex->layer= newlayer; + + btex->totlayer++; + + /* fill in new layer */ + layer= &btex->layer[btex->totlayer-1]; + layer->structbytes= sizeof(BTexLayer); + layer->datatype= BTEX_DATA_FLOAT; + layer->type= type; + BLI_strncpy(layer->name, name, BTEX_LAYER_NAME_MAX); + + return layer; +} + +void btex_layer_remove(BTex *btex, BTexLayer *layer) +{ + BTexLayer *newlayer; + int index= layer - btex->layer; + + /* expand array */ + newlayer= MEM_callocN(sizeof(BTexLayer)*(btex->totlayer-1), "BTexLayer"); + if(index > 0) + memcpy(newlayer, btex->layer, sizeof(BTexLayer)*index); + if(index+1 < btex->totlayer) + memcpy(newlayer+index, btex->layer+index+1, sizeof(BTexLayer)*(btex->totlayer-(index+1))); + btex->layer= newlayer; + + btex->totlayer--; +} + +/********************************* Mesh **************************************/ + +void btex_mesh_set_grids(BTex *btex, int totgrid, int gridsize, int datasize) +{ + BTexLayer *layer; + int a; + + btex->btype.mesh.totgrid= totgrid; + btex->btype.mesh.gridsize= gridsize; + + for(a=0; atotlayer; a++) { + layer= &btex->layer[a]; + layer->datasize= datasize; + } +} + diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 4844595513f..8f167310741 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -32,21 +32,26 @@ * */ -#include "BKE_customdata.h" -#include "BKE_utildefines.h" // CLAMP -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_linklist.h" -#include "BLI_mempool.h" +#include +#include + +#include "MEM_guardedalloc.h" #include "DNA_customdata_types.h" #include "DNA_listBase.h" #include "DNA_meshdata_types.h" +#include "DNA_ID.h" -#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "BLI_linklist.h" +#include "BLI_math.h" +#include "BLI_mempool.h" +#include "BLI_string.h" -#include -#include +#include "BKE_btex.h" +#include "BKE_customdata.h" +#include "BKE_global.h" +#include "BKE_utildefines.h" /* number of layers to add when growing a CustomData object */ #define CUSTOMDATA_GROW 5 @@ -89,6 +94,12 @@ typedef struct LayerTypeInfo { /* a function to set a layer's data to default values. if NULL, the default is assumed to be all zeros */ void (*set_default)(void *data, int count); + + /* a function to read data from a btex file */ + int (*read)(BTex *btex, void *data, int count); + + /* a function to write data to a btex file */ + int (*write)(BTex *btex, void *data, int count); } LayerTypeInfo; static void layerCopy_mdeformvert(const void *source, void *dest, @@ -538,6 +549,39 @@ static void layerFree_mdisps(void *data, int count, int size) } } +static int layerRead_mdisps(BTex *btex, void *data, int count) +{ + MDisps *d = data; + int i; + + for(i = 0; i < count; ++i) { + if(!d[i].disps) + d[i].disps = MEM_callocN(sizeof(float)*3*d[i].totdisp, "mdisps read"); + + if(!btex_read_data(btex, d[i].totdisp*3*sizeof(float), d[i].disps)) { + printf("failed to read %d/%d %d\n", i, count, d[i].totdisp); + return 0; + } + } + + return 1; +} + +static int layerWrite_mdisps(BTex *btex, void *data, int count) +{ + MDisps *d = data; + int i; + + for(i = 0; i < count; ++i) { + if(!btex_write_data(btex, d[i].totdisp*3*sizeof(float), d[i].disps)) { + printf("failed to write %d/%d %d\n", i, count, d[i].totdisp); + return 0; + } + } + + return 1; +} + /* --------- */ static void layerDefault_mloopcol(void *data, int count) @@ -731,7 +775,7 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, - layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL}, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps}, {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, @@ -793,6 +837,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataLayer *layer, *newlayer; int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0; + CustomData_external_read(dest, mask, totelem); + for(i = 0; i < source->totlayer; ++i) { layer = &source->layers[i]; typeInfo = layerType_getInfo(layer->type); @@ -853,6 +899,14 @@ static void customData_free_layer__internal(CustomDataLayer *layer, int totelem) } } +static void CustomData_external_free(CustomData *data) +{ + if(data->external) { + MEM_freeN(data->external); + data->external= NULL; + } +} + void CustomData_free(CustomData *data, int totelem) { int i; @@ -863,6 +917,8 @@ void CustomData_free(CustomData *data, int totelem) if(data->layers) MEM_freeN(data->layers); + CustomData_external_free(data); + memset(data, 0, sizeof(*data)); } @@ -2238,3 +2294,232 @@ int CustomData_verify_versions(struct CustomData *data, int index) return keeplayer; } +/****************************** External Files *******************************/ + +static void customdata_external_filename(char filename[FILE_MAX], CustomDataExternal *external) +{ + BLI_strncpy(filename, external->filename, FILE_MAX); + BLI_convertstringcode(filename, G.sce); +} + +void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem) +{ + CustomDataExternal *external= data->external; + CustomDataLayer *layer; + BTex *btex; + BTexLayer *blay; + char filename[FILE_MAX]; + const LayerTypeInfo *typeInfo; + int i, update = 0; + + if(!external) + return; + + for(i=0; itotlayer; i++) { + layer = &data->layers[i]; + typeInfo = layerType_getInfo(layer->type); + + if(!(mask & (1<type))); + else if(layer->flag & CD_FLAG_IN_MEMORY); + else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) + update= 1; + } + + if(!update) + return; + + customdata_external_filename(filename, external); + + btex= btex_create(BTEX_TYPE_MESH); + if(!btex_read_open(btex, filename)) + return; + + for(i=0; itotlayer; i++) { + layer = &data->layers[i]; + typeInfo = layerType_getInfo(layer->type); + + if(!(mask & (1<type))); + else if(layer->flag & CD_FLAG_IN_MEMORY); + else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) { + blay= btex_layer_find(btex, layer->type, layer->name); + + if(blay) { + if(btex_read_layer(btex, blay)) { + if(typeInfo->read(btex, layer->data, totelem)); + else break; + layer->flag |= CD_FLAG_IN_MEMORY; + } + else + break; + } + } + } + + btex_read_close(btex); + btex_free(btex); +} + +void CustomData_external_write(CustomData *data, CustomDataMask mask, int totelem, int free) +{ + CustomDataExternal *external= data->external; + CustomDataLayer *layer; + BTex *btex; + BTexLayer *blay; + const LayerTypeInfo *typeInfo; + int i, update = 0; + char filename[FILE_MAX]; + + if(!external) + return; + + for(i=0; itotlayer; i++) { + layer = &data->layers[i]; + typeInfo = layerType_getInfo(layer->type); + + if(!(mask & (1<type))); + else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) + update= 1; + } + + if(!update) + return; + + CustomData_external_read(data, mask, totelem); + + btex= btex_create(BTEX_TYPE_MESH); + + for(i=0; itotlayer; i++) { + layer = &data->layers[i]; + typeInfo = layerType_getInfo(layer->type); + + if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) + btex_layer_add(btex, layer->type, layer->name); + } + + customdata_external_filename(filename, external); + if(!btex_write_open(btex, filename)) + return; + + for(i=0; itotlayer; i++) { + layer = &data->layers[i]; + typeInfo = layerType_getInfo(layer->type); + + if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { + blay= btex_layer_find(btex, layer->type, layer->name); + + if(btex_write_layer(btex, blay)) { + if(typeInfo->write(btex, layer->data, totelem)); + else break; + } + else + break; + } + } + + if(i != data->totlayer) { + btex_free(btex); + return; + } + + for(i=0; itotlayer; i++) { + layer = &data->layers[i]; + typeInfo = layerType_getInfo(layer->type); + + if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { + if(free) { + if(typeInfo->free) + typeInfo->free(layer->data, totelem, typeInfo->size); + layer->flag &= ~CD_FLAG_IN_MEMORY; + } + } + } + + btex_write_close(btex); + btex_free(btex); +} + +void CustomData_external_add(CustomData *data, int type, const char *name, int totelem) +{ + CustomDataExternal *external= data->external; + CustomDataLayer *layer; + int layer_index; + + layer_index = CustomData_get_active_layer_index(data, type); + if(layer_index < 0) return; + + layer = &data->layers[layer_index]; + + if(layer->flag & CD_FLAG_EXTERNAL) + return; + + if(!external) { + char hex[MAX_ID_NAME*2]; + + external= MEM_callocN(sizeof(CustomDataExternal), "CustomDataExternal"); + BLI_strhex(hex, sizeof(hex), name); + BLI_snprintf(external->filename, sizeof(external->filename), "//%s_mesh.btex", hex); + data->external= external; + } + + layer->flag |= CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY; +} + +void CustomData_external_remove(CustomData *data, int type, int totelem) +{ + CustomDataExternal *external= data->external; + CustomDataLayer *layer; + char filename[FILE_MAX]; + int layer_index, i, remove_file; + + layer_index = CustomData_get_active_layer_index(data, type); + if(layer_index < 0) return; + + layer = &data->layers[layer_index]; + + if(!external) + return; + + if(layer->flag & CD_FLAG_EXTERNAL) { + if(!(layer->flag & CD_FLAG_IN_MEMORY)) + CustomData_external_read(data, (1<type), totelem); + + layer->flag &= ~CD_FLAG_EXTERNAL; + + remove_file= 1; + for(i=0; itotlayer; i++) + if(data->layers[i].flag & CD_FLAG_EXTERNAL) + remove_file= 0; + + if(remove_file) { + customdata_external_filename(filename, external); + btex_remove(filename); + CustomData_external_free(data); + } + } +} + +int CustomData_external_test(CustomData *data, int type) +{ + CustomDataLayer *layer; + int layer_index; + + layer_index = CustomData_get_active_layer_index(data, type); + if(layer_index < 0) return 0; + + layer = &data->layers[layer_index]; + return (layer->flag & CD_FLAG_EXTERNAL); +} + +void CustomData_external_remove_object(CustomData *data) +{ + CustomDataExternal *external= data->external; + char filename[FILE_MAX]; + + if(!external) + return; + + customdata_external_filename(filename, external); + btex_remove(filename); + CustomData_external_free(data); +} + diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 2518d4bc3ca..a709b45f60c 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -249,7 +249,7 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object int levels = mmd->totlvl - lvl; MDisps *mdisps; - // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); multires_force_update(ob); @@ -595,7 +595,7 @@ static void multiresModifier_update(DerivedMesh *dm) ob = ccgdm->multires.ob; me = ccgdm->multires.ob->data; mmd = ccgdm->multires.mmd; - // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); if(mdisps) { @@ -692,7 +692,7 @@ void multires_force_update(Object *ob) struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob, int useRenderParams, int isFinalCalc) { - //Mesh *me= ob->data; + Mesh *me= ob->data; DerivedMesh *result; CCGDerivedMesh *ccgdm; DMGridData **gridData, **subGridData; @@ -727,7 +727,7 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize); } - // XXX CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl); for(i = 0; i < numGrids; i++) diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index c2798b4a746..e552f08f350 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1075,12 +1075,11 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho } if(strcmp(pid->cache->name, "")==0 && (pid->cache->flag & PTCACHE_EXTERNAL)==0) { idname = (pid->ob->id.name+2); + /* convert chars to hex so they are always a valid filename */ - while('\0' != *idname) { - snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++)); - newname+=2; - len += 2; - } + BLI_strhex(newname, MAX_PTCACHE_FILE - len, idname); + len += strlen(newname); + newname = filename + len; } else { int temp = (int)strlen(pid->cache->name); -- cgit v1.2.3 From b129ccf000382028c932d663695326acf1be9140 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 25 Nov 2009 14:59:02 +0000 Subject: Pose Bone "Local Location" option. This is enabled by default, disabling it puts the bone location in pose space rather than local bone space. --- source/blender/blenkernel/intern/armature.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 7a1a2eec95b..f9def718a4b 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2247,7 +2247,12 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti mul_serie_m4(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); } else { - mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat); + if(bone->flag & BONE_NO_LOCAL_LOCATION) { + mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat); + add_v3_v3v3(pchan->pose_mat[3], bone->arm_mat[3], pchan->chan_mat[3]); + } + else + mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat); /* only rootbones get the cyclic offset (unless user doesn't want that) */ if ((bone->flag & BONE_NO_CYCLICOFFSET) == 0) -- cgit v1.2.3 From 553374bd4c9833b13072bcf697b5776f95366407 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Nov 2009 15:00:29 +0000 Subject: selected_pchans --> selected_pose_bones, same for visible_pchans added use_ prefix to bools offset --> use_offset, tail --> use_tail for eg. --- source/blender/blenkernel/BKE_context.h | 4 ++-- source/blender/blenkernel/intern/context.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 947ec914fa4..aa9c9b2721e 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -249,8 +249,8 @@ int CTX_data_visible_bones(const bContext *C, ListBase *list); int CTX_data_editable_bones(const bContext *C, ListBase *list); struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C); -int CTX_data_selected_pchans(const bContext *C, ListBase *list); -int CTX_data_visible_pchans(const bContext *C, ListBase *list); +int CTX_data_selected_pose_bones(const bContext *C, ListBase *list); +int CTX_data_visible_bose_bones(const bContext *C, ListBase *list); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 164e7a23d92..fc1ef4aede9 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -883,13 +883,13 @@ struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C) return ctx_data_pointer_get(C, "active_pose_bone"); } -int CTX_data_selected_pchans(const bContext *C, ListBase *list) +int CTX_data_selected_pose_bones(const bContext *C, ListBase *list) { - return ctx_data_collection_get(C, "selected_pchans", list); + return ctx_data_collection_get(C, "selected_pose_bones", list); } -int CTX_data_visible_pchans(const bContext *C, ListBase *list) +int CTX_data_visible_pose_bones(const bContext *C, ListBase *list) { - return ctx_data_collection_get(C, "visible_pchans", list); + return ctx_data_collection_get(C, "visible_pose_bones", list); } -- cgit v1.2.3 From 323aa656715f9f40e151acd0b61305384ae0970d Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Wed, 25 Nov 2009 17:46:10 +0000 Subject: Verlet integration method for particles (patch provided by farsthary). --- source/blender/blenkernel/intern/particle_system.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 075c6f6207f..809b5f2090c 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2287,6 +2287,9 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra case PART_INT_RK4: steps=4; break; + case PART_INT_VERLET: + steps=1; + break; } copy_particle_key(states,&pa->state,1); @@ -2392,6 +2395,13 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra VECADDFAC(pa->state.vel,pa->state.vel,dv[3],1.0f/6.0f); } break; + case PART_INT_VERLET: /* Verlet integration */ + VECADDFAC(pa->state.vel,pa->state.vel,force,dtime); + VECADDFAC(pa->state.co,pa->state.co,pa->state.vel,dtime); + + VECSUB(pa->state.vel,pa->state.co,pa->prev_state.co); + mul_v3_fl(pa->state.vel,1.0f/dtime); + break; } } -- cgit v1.2.3 From 2b121e65991763fc9631e466be885fe0755a4087 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 25 Nov 2009 18:48:29 +0000 Subject: Pose Bone Local Location: now also works for non-connected bones with parents. --- source/blender/blenkernel/intern/armature.c | 44 ++++++++++++++++------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f9def718a4b..f70bdc8636b 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2220,39 +2220,43 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti /* the rotation of the parent restposition */ copy_m4_m4(tmat, parbone->arm_mat); - - /* the location of actual parent transform */ - VECCOPY(tmat[3], offs_bone[3]); - offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; - mul_m4_v3(parchan->pose_mat, tmat[3]); - mul_serie_m4(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); } else if(bone->flag & BONE_NO_SCALE) { float orthmat[4][4]; - /* get the official transform, but we only use the vector from it (optimize...) */ - mul_serie_m4(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); - VECCOPY(vec, pchan->pose_mat[3]); - - /* do this again, but with an ortho-parent matrix */ + /* do transform, with an ortho-parent matrix */ copy_m4_m4(orthmat, parchan->pose_mat); normalize_m4(orthmat); mul_serie_m4(pchan->pose_mat, orthmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); - - /* copy correct transform */ - VECCOPY(pchan->pose_mat[3], vec); } - else + else mul_serie_m4(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); + + /* in these cases we need to compute location separately */ + if(bone->flag & (BONE_HINGE|BONE_NO_SCALE|BONE_NO_LOCAL_LOCATION)) { + float bone_loc[3], chan_loc[3]; + + mul_v3_m4v3(bone_loc, parchan->pose_mat, offs_bone[3]); + copy_v3_v3(chan_loc, pchan->chan_mat[3]); + + /* no local location is not transformed by bone matrix */ + if(!(bone->flag & BONE_NO_LOCAL_LOCATION)) + mul_mat3_m4_v3(offs_bone, chan_loc); + + /* for hinge we use armature instead of pose mat */ + if(bone->flag & BONE_HINGE) mul_m4_v3(parbone->arm_mat, chan_loc); + else mul_m4_v3(parchan->pose_mat, chan_loc); + + add_v3_v3v3(pchan->pose_mat[3], bone_loc, chan_loc); + } } else { - if(bone->flag & BONE_NO_LOCAL_LOCATION) { - mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat); + mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat); + + /* optional location without arm_mat rotation */ + if(bone->flag & BONE_NO_LOCAL_LOCATION) add_v3_v3v3(pchan->pose_mat[3], bone->arm_mat[3], pchan->chan_mat[3]); - } - else - mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat); /* only rootbones get the cyclic offset (unless user doesn't want that) */ if ((bone->flag & BONE_NO_CYCLICOFFSET) == 0) -- cgit v1.2.3 From 12968cdd8a0141aa57e196256e7161ff11dd1ec3 Mon Sep 17 00:00:00 2001 From: Jens Ole Wund Date: Wed, 25 Nov 2009 23:54:21 +0000 Subject: adding function vcloud_estimate_transform(..) to math library comments there (@math_geom.c) should explain what it does -- removing attached clutter from softbody.c --- source/blender/blenkernel/intern/softbody.c | 174 ++++------------------------ 1 file changed, 22 insertions(+), 152 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 557f326e951..f53700976fd 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3752,6 +3752,7 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo } } + /* void SB_estimate_transform */ /* input Object *ob out (says any object that can do SB like mesh,lattice,curve ) output float lloc[3],float lrot[3][3],float lscale[3][3] @@ -3764,164 +3765,40 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo lloc,lrot,lscale are allowed to be NULL, just in case you don't need it. should be pretty useful for pythoneers :) not! velocity .. 2nd order stuff + vcloud_estimate_transform see */ -/* can't believe there is none in math utils */ -float _det_m3(float m2[3][3]) -{ - float det = 0.f; - if (m2){ - det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1]) - -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1]) - +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]); - } - return det; -} - void SB_estimate_transform(Object *ob,float lloc[3],float lrot[3][3],float lscale[3][3]) { BodyPoint *bp; ReferenceVert *rp; - float accu_pos[3] = {0.0f,0.0f,0.0f}; - float com[3],va[3],vb[3],rcom[3]; - float accu_mass = 0.0f,la = 0.0f,lb = 0.0f,eps = 0.000001f; SoftBody *sb = 0; - int a,i=0,imax=16; - int _localdebug; - - if (lloc) zero_v3(lloc); - if (lrot) zero_m3(lrot); - if (lscale) zero_m3(lscale); - + float (*opos)[3]; + float (*rpos)[3]; + float com[3],rcom[3]; + int a; if(!ob ||!ob->soft) return; /* why did we get here ? */ sb= ob->soft; - /*for threading there should be a lock */ - /* sb-> lock; */ - /* calculate center of mass */ if(!sb || !sb->bpoint) return; - _localdebug=sb->solverflags & SBSO_MONITOR; /* turn this on/off if you (don't) want to see progress on console */ - for(a=0,bp=sb->bpoint; atotpoint; a++, bp++) { - VECADD(accu_pos,accu_pos,bp->pos); - accu_mass += bp->mass; + opos= MEM_callocN( (sb->totpoint)*3*sizeof(float), "SB_OPOS"); + rpos= MEM_callocN( (sb->totpoint)*3*sizeof(float), "SB_RPOS"); + /* might filter vertex selection with a vertex group */ + for(a=0, bp=sb->bpoint, rp=sb->scratch->Ref.ivert; atotpoint; a++, bp++, rp++) { + VECCOPY(rpos[a],rp->pos); + VECCOPY(opos[a],bp->pos); } - VECCOPY(com,accu_pos); - mul_v3_fl(com,1.0f/accu_mass); - /* center of mass done*/ - if (sb->scratch){ - float dcom[3],stunt[3]; - float m[3][3],mr[3][3],q[3][3],qi[3][3]; - float odet,ndet; - zero_m3(m); - zero_m3(mr); - VECSUB(dcom,com,sb->scratch->Ref.com); - VECCOPY(rcom,sb->scratch->Ref.com); - if (_localdebug) { - printf("DCOM %f %f %f\n",dcom[0],dcom[1],dcom[2]); - } - if (lloc) VECCOPY(lloc,dcom); - VECCOPY(sb->lcom,dcom); - /* build 'projection' matrix */ - for(a=0, bp=sb->bpoint, rp=sb->scratch->Ref.ivert; atotpoint; a++, bp++, rp++) { - VECSUB(va,rp->pos,rcom); - la += len_v3(va); - /* mul_v3_fl(va,bp->mass); mass needs renormalzation here ?? */ - VECSUB(vb,bp->pos,com); - lb += len_v3(vb); - /* mul_v3_fl(va,rp->mass); */ - m[0][0] += va[0] * vb[0]; - m[0][1] += va[0] * vb[1]; - m[0][2] += va[0] * vb[2]; - - m[1][0] += va[1] * vb[0]; - m[1][1] += va[1] * vb[1]; - m[1][2] += va[1] * vb[2]; - - m[2][0] += va[2] * vb[0]; - m[2][1] += va[2] * vb[1]; - m[2][2] += va[2] * vb[2]; - - /* building the referenc matrix on the fly - needed to scale properly later*/ - - mr[0][0] += va[0] * va[0]; - mr[0][1] += va[0] * va[1]; - mr[0][2] += va[0] * va[2]; - - mr[1][0] += va[1] * va[0]; - mr[1][1] += va[1] * va[1]; - mr[1][2] += va[1] * va[2]; - - mr[2][0] += va[2] * va[0]; - mr[2][1] += va[2] * va[1]; - mr[2][2] += va[2] * va[2]; - } - /* we are pretty much set up here and we could return that raw mess containing essential information - but being nice fellows we proceed: - knowing we did split off the tanslational part to the center of mass (com) part - however let's do some more reverse engeneering and see if we can split - rotation from scale ->Polardecompose - */ - copy_m3_m3(q,m); - stunt[0] = q[0][0]; stunt[1] = q[1][1]; stunt[2] = q[2][2]; - /* nothing to see here but renormalizing works nicely - printf("lenght stunt %5.3f a %5.3f b %5.3f %5.3f\n",len_v3(stunt),la,lb,sqrt(la*lb)); - */ - mul_m3_fl(q,1.f/len_v3(stunt)); - /* not too much to see here - if(_localdebug){ - printf("q0 %5.3f %5.3f %5.3f\n",q[0][0],q[0][1],q[0][2]); - printf("q1 %5.3f %5.3f %5.3f\n",q[1][0],q[1][1],q[1][2]); - printf("q2 %5.3f %5.3f %5.3f\n",q[2][0],q[2][1],q[2][2]); - } - */ - /* this is pretty much Polardecompose 'inline' the algo based on Higham's thesis */ - /* without the far case !!! but seems to work here pretty neat */ - odet = 0.f; - ndet = _det_m3(q); - while((odet-ndet)*(odet-ndet) > eps && ilrot,q); - if(_localdebug){ - printf("Rot .. i %d\n",i); - printf("!q0 %5.3f %5.3f %5.3f\n",q[0][0],q[0][1],q[0][2]); - printf("!q1 %5.3f %5.3f %5.3f\n",q[1][0],q[1][1],q[1][2]); - printf("!q2 %5.3f %5.3f %5.3f\n",q[2][0],q[2][1],q[2][2]); - } - invert_m3_m3(irot,q); - /* now that's where we need mr to get scaling right */ - invert_m3_m3(qi,mr); - mul_m3_m3m3(q,m,qi); - - //mul_m3_m3m3(scale,q,irot); - mul_m3_m3m3(scale,irot,q); /* i always have a problem with this C functions left/right operator applies first*/ - mul_m3_fl(scale,lb/la); /* 0 order scale was normalized away so put it back here dunno if that is needed here ???*/ - - if(lscale) copy_m3_m3(lscale,scale); - copy_m3_m3(sb->lscale,scale); - if(_localdebug){ - printf("Scale .. \n"); - printf("!s0 %5.3f %5.3f %5.3f\n",scale[0][0],scale[0][1],scale[0][2]); - printf("!s1 %5.3f %5.3f %5.3f\n",scale[1][0],scale[1][1],scale[1][2]); - printf("!s2 %5.3f %5.3f %5.3f\n",scale[2][0],scale[2][1],scale[2][2]); - } - - } - } - /*for threading there should be a unlock */ - /* sb-> unlock; */ + vcloud_estimate_transform(sb->totpoint, opos, NULL, rpos, NULL, com, rcom,lrot,lscale); + //VECSUB(com,com,rcom); + if (lloc) VECCOPY(lloc,com); + VECCOPY(sb->lcom,com); + if (lscale) copy_m3_m3(sb->lscale,lscale); + if (lrot) copy_m3_m3(sb->lrot,lrot); + + + MEM_freeN(opos); + MEM_freeN(rpos); } static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts) @@ -4182,10 +4059,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i dtime = timescale; softbody_update_positions(ob, sb, vertexCos, numVerts); softbody_step(scene, ob, sb, dtime); - if(sb->solverflags & SBSO_MONITOR ){ - printf("Picked from cache continue_physics %d\n",framenr); - } - softbody_to_object(ob, vertexCos, numVerts, 0); return; } @@ -4210,9 +4083,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { - if(sb->solverflags & SBSO_MONITOR ){ - printf("Picked from cache at frame %d\n",framenr); - } softbody_to_object(ob, vertexCos, numVerts, sb->local); cache->simframe= framenr; -- cgit v1.2.3 From 1fcffd1aa0d03722dbaa8990bfe09b38f194b565 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 26 Nov 2009 03:43:39 +0000 Subject: Bugfix #20041: Drivers don't work on bone visiblity - Drivers on added to the 'armature' datablock (i.e. keyframing some settings for a "Bone" as opposed to "PoseBone") now evaluate correctly. Added proper recalcs for this case too. - Also fixed some memory leaks and loading problems I encountered with the test file provided. After having problems loading the test file, I ended up reproducing and finding the error. --- source/blender/blenkernel/intern/armature.c | 8 ++++++++ source/blender/blenkernel/intern/object.c | 10 ++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f70bdc8636b..23b08007d1f 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -37,6 +37,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_action_types.h" #include "DNA_curve_types.h" @@ -49,6 +50,7 @@ #include "DNA_scene_types.h" #include "DNA_view3d_types.h" +#include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_action.h" #include "BKE_anim.h" @@ -127,6 +129,12 @@ void free_armature(bArmature *arm) freeSketch(arm->sketch); arm->sketch = NULL; } + + /* free animation data */ + if (arm->adt) { + BKE_free_animdata(&arm->id); + arm->adt= NULL; + } } } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 078ff9d6eeb..c537f9f57b0 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2364,6 +2364,9 @@ void object_handle_update(Scene *scene, Object *ob) } if(ob->recalc & OB_RECALC_DATA) { + ID *data_id= (ID *)ob->data; + AnimData *adt= BKE_animdata_from_id(data_id); + float ctime= (float)scene->r.cfra; // XXX this is bad... if (G.f & G_DEBUG) printf("recalcdata %s\n", ob->id.name+2); @@ -2386,10 +2389,6 @@ void object_handle_update(Scene *scene, Object *ob) makeDispListCurveTypes(scene, ob, 0); } else if(ELEM(ob->type, OB_CAMERA, OB_LAMP)) { - ID *data_id= (ID *)ob->data; - AnimData *adt= BKE_animdata_from_id(data_id); - float ctime= (float)scene->r.cfra; // XXX this is bad... - /* evaluate drivers */ BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS); } @@ -2402,6 +2401,9 @@ void object_handle_update(Scene *scene, Object *ob) if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC)) armature_rebuild_pose(ob, ob->data); + /* evaluate drivers */ + BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS); + if(ob->id.lib && ob->proxy_from) { copy_pose_result(ob->pose, ob->proxy_from->pose); // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name); -- cgit v1.2.3 From 802cc77f71d6a1deb1e4773f135653f836e84e15 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 26 Nov 2009 11:13:10 +0000 Subject: Patch #20037: Use named components for Drivers instead of array_index This patch, by Elia Sarti (vekoon), simply adds the possibility to specify the final array component of the RNA path in the path itself, e.g. using location[0] or location["x"] or even location.x, instead of specifying this using an "array_index" This should be easier for users to understand the driver system. The array-indices have been kept (but hidden from the UI under standard situations) since they are theoretically a tad faster than the in-path lookups still, and are easier for internal-tools to set for now... --- source/blender/blenkernel/intern/fcurve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index e90fccf6b29..0623a5cbe5e 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -822,7 +822,7 @@ float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar) } /* get property to read from, and get value as appropriate */ - if (RNA_path_resolve(&id_ptr, path, &ptr, &prop)) { + if (RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) { switch (RNA_property_type(prop)) { case PROP_BOOLEAN: if (RNA_property_array_length(&ptr, prop)) -- cgit v1.2.3 From 7828f822dfd73f5ef6bc8127961c9a4a10fd9f38 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 26 Nov 2009 11:38:28 +0000 Subject: Bugfix: pose bone was doing double translation in some cases, due to my commit yesterday. --- source/blender/blenkernel/intern/armature.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 23b08007d1f..a570697dfda 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2253,8 +2253,8 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti mul_mat3_m4_v3(offs_bone, chan_loc); /* for hinge we use armature instead of pose mat */ - if(bone->flag & BONE_HINGE) mul_m4_v3(parbone->arm_mat, chan_loc); - else mul_m4_v3(parchan->pose_mat, chan_loc); + if(bone->flag & BONE_HINGE) mul_mat3_m4_v3(parbone->arm_mat, chan_loc); + else mul_mat3_m4_v3(parchan->pose_mat, chan_loc); add_v3_v3v3(pchan->pose_mat[3], bone_loc, chan_loc); } -- cgit v1.2.3 From 3764c1ea26e79861eac2399536d55892d882f0de Mon Sep 17 00:00:00 2001 From: Elia Sarti Date: Thu, 26 Nov 2009 17:20:02 +0000 Subject: Fixed typo --- source/blender/blenkernel/BKE_context.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index aa9c9b2721e..2c013a5231a 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -250,7 +250,7 @@ int CTX_data_editable_bones(const bContext *C, ListBase *list); struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C); int CTX_data_selected_pose_bones(const bContext *C, ListBase *list); -int CTX_data_visible_bose_bones(const bContext *C, ListBase *list); +int CTX_data_visible_pose_bones(const bContext *C, ListBase *list); #ifdef __cplusplus } -- cgit v1.2.3 From 5ca3d1919ca9283dbd56f44684a27d11ea35ccb3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 27 Nov 2009 12:42:42 +0000 Subject: fix for undo crashing when animating proxies that had ID props --- source/blender/blenkernel/intern/armature.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index a570697dfda..418c9f00596 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1509,6 +1509,10 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected pchanw.child= pchan->child; pchanw.path= NULL; + /* this is freed so copy a copy, else undo crashes */ + if(pchanw.prop) + pchanw.prop= IDP_CopyProperty(pchanw.prop); + /* constraints - proxy constraints are flushed... local ones are added after * 1. extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints * 2. copy proxy-pchan's constraints on-to new -- cgit v1.2.3 From 54c5859578362976cc54b4e04f0a513117b4698e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 28 Nov 2009 03:49:45 +0000 Subject: Durian Rigging Requests: (Armature Layers + Rotation Locking Tweaks) * Increased the number of Armature and Bone Layers from 16 to 32. Please note that older versions of Blender may not correctly resolve the layers that bones are on when loading new files. * Newly added objects are now made by default to allow locking of 4-component rotations using 4 separate locks (i.e. one by component) instead of requiring the obscure 'W' toggle (renamed '4L' now) to be enabled first. The objects in the default scene need modifying manually though. --- source/blender/blenkernel/intern/action.c | 5 +++++ source/blender/blenkernel/intern/object.c | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index cb6fef0bc30..ace1292f813 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -456,6 +456,8 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name) chan->ikrotweight = chan->iklinweight = 0.0f; unit_m4(chan->constinv); + chan->protectflag = OB_LOCK_ROT4D; /* lock by components by default */ + BLI_addtail(&pose->chanbase, chan); return chan; @@ -1083,7 +1085,10 @@ void copy_pose_result(bPose *to, bPose *from) VECCOPY(pchanto->pose_head, pchanfrom->pose_head); VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail); + + pchanto->rotmode= pchanfrom->rotmode; pchanto->flag= pchanfrom->flag; + pchanto->protectflag= pchanfrom->protectflag; } } } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index c537f9f57b0..73a1d2023a2 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1044,6 +1044,10 @@ Object *add_object(struct Scene *scene, int type) ob->rotmode= ROT_MODE_EUL; /* axis-angle must not have a 0,0,0 axis, so set y-axis as default... */ ob->rotAxis[1]= ob->drotAxis[1]= 1.0f; + /* quaternions should be 1,0,0,0 by default.... */ + ob->quat[0]= 1.0f; + /* rotation locks should be 4D for 4 component rotations by default... */ + ob->protectflag = OB_LOCK_ROT4D; base= scene_add_base(scene, ob); scene_select_base(scene, base); -- cgit v1.2.3 From c4933cccfa74836ff88a6904abfaf52c8e0cde87 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 28 Nov 2009 13:33:17 +0000 Subject: Mesh Deform Modifier * Now support a Surface mode next to the existing Volume mode. This binds the mesh to the cage mesh surface rather than it's volume. * Implemented reusing the bone heat weighting code. * Advantage is that it works for cage meshes that are not volumes and that binding is much faster. * Weak point is that disconnected components of a mesh are not guaranteed to stick together (same problem exists with bone heat weighting). * Bind weights could still be compressed better to use less memory. Example file: http://download.blender.org/ftp/incoming/cloth_mdef_surface.blend --- source/blender/blenkernel/intern/modifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index b5e0ca9ea5c..56aab7d2ba9 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7894,7 +7894,7 @@ static void meshdeformModifier_do( /* progress bar redraw can make this recursive .. */ if(!recursive) { recursive = 1; - mmd->bindfunc(md->scene, mmd, (float*)vertexCos, numVerts, cagemat); + mmd->bindfunc(md->scene, dm, mmd, (float*)vertexCos, numVerts, cagemat); recursive = 0; } } -- cgit v1.2.3 From a2b370dd6f55d6114da3ec1d86788e9c9786822f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 28 Nov 2009 13:33:56 +0000 Subject: py/rna api - object.modifiers.add()/remove() - armature.edit_bones.active wasnt named correctly --- source/blender/blenkernel/BKE_particle.h | 2 +- source/blender/blenkernel/intern/particle.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 2291601bd47..2199240d77b 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -222,7 +222,7 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); -void object_add_particle_system(struct Scene *scene, struct Object *ob); +struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, char *name); void object_remove_particle_system(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index e241d5808cd..bb2f4128891 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3268,14 +3268,14 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa /************************************************/ /* ParticleSettings handling */ /************************************************/ -void object_add_particle_system(Scene *scene, Object *ob) +ModifierData *object_add_particle_system(Scene *scene, Object *ob, char *name) { ParticleSystem *psys; ModifierData *md; ParticleSystemModifierData *psmd; if(!ob || ob->type != OB_MESH) - return; + return NULL; psys = ob->particlesystem.first; for(; psys; psys=psys->next) @@ -3293,7 +3293,11 @@ void object_add_particle_system(Scene *scene, Object *ob) strcpy(psys->name, "ParticleSystem"); md= modifier_new(eModifierType_ParticleSystem); - sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + + if(name) BLI_strncpy(md->name, name, sizeof(md->name)); + else sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + modifier_unique_name(&ob->modifiers, md); + psmd= (ParticleSystemModifierData*) md; psmd->psys=psys; BLI_addtail(&ob->modifiers, md); @@ -3304,6 +3308,8 @@ void object_add_particle_system(Scene *scene, Object *ob) DAG_scene_sort(scene); DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + + return md; } void object_remove_particle_system(Scene *scene, Object *ob) { -- cgit v1.2.3 From da442c1d43c6a0077d13dbf11acd1c4de5feca78 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 28 Nov 2009 18:19:34 +0000 Subject: UI/RNA: * Set default particleedit selection mode in add scene (TODO: not yet changed in the default blend) * Corrected names for particleedit selection mode in RNA, added icons * Added occlude geometry flag to view3d RNA * Converted particleedit buttons to uiItems in view3d header --- source/blender/blenkernel/intern/scene.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 91fd0bac400..27cb3ad834b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -416,6 +416,7 @@ Scene *add_scene(char *name) pset->brushtype= PE_BRUSH_NONE; pset->draw_step= 2; pset->fade_frames= 2; + pset->selectmode= SCE_SELECT_PATH; for(a=0; abrush[a].strength= 50; pset->brush[a].size= 50; -- cgit v1.2.3 From a22cfe99db567fb34047b1cf3cacde1be271efac Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 29 Nov 2009 18:14:16 +0000 Subject: == Sequencer == Brought back default effect fading: (adding a wipe effect makes it wipe by default for the length of the strip) First round in upgrading IPOs from older versions. (works for non-IPO case now and sets at least the new "default effect fade"-flag) Still non-working for old IPOs, since Sequence-Strips aren't real IDs! And: non-frame-lock case should stretch the FCurve to the right length! --- source/blender/blenkernel/intern/ipo.c | 57 +++++++++++++++++++++++++++++ source/blender/blenkernel/intern/sequence.c | 34 ++++++++++------- 2 files changed, 77 insertions(+), 14 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 18a8210c68d..6fc3fc547df 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -885,6 +885,17 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co case ID_SEQ: /* sequencer strip */ //SEQ_FAC1: + switch (adrcode) { + case SEQ_FAC1: + propname= "effect_fader"; + break; + case SEQ_FAC_SPEED: + propname= "speed_fader"; + break; + case SEQ_FAC_OPACITY: + propname= "blend_opacity"; + break; + } // poin= &(seq->facf0); // XXX this doesn't seem to be included anywhere in sequencer RNA... break; @@ -1604,6 +1615,7 @@ void do_versions_ipos_to_animato(Main *main) ListBase drivers = {NULL, NULL}; ID *id; AnimData *adt; + Scene *scene; if (main == NULL) { printf("Argh! Main is NULL in do_versions_ipos_to_animato() \n"); @@ -1781,6 +1793,51 @@ void do_versions_ipos_to_animato(Main *main) } } + /* sequence strips */ + for(scene = main->scene.first; scene; scene = scene->id.next) { + if(scene->ed && scene->ed->seqbasep) { + Sequence * seq; + + for(seq = scene->ed->seqbasep->first; + seq; seq = seq->next) { + short adrcode = SEQ_FAC1; + + if (G.f & G_DEBUG) + printf("\tconverting sequence strip %s \n", seq->name+2); + + if (!seq->ipo || !seq->ipo->curve.first) { + seq->flag |= + SEQ_USE_EFFECT_DEFAULT_FADE; + continue; + } + + /* patch adrcode, so that we can map + to different DNA variables later + (semi-hack (tm) ) + */ + switch(seq->type) { + case SEQ_IMAGE: + case SEQ_META: + case SEQ_SCENE: + case SEQ_MOVIE: + case SEQ_COLOR: + adrcode = SEQ_FAC_OPACITY; + break; + case SEQ_SPEED: + adrcode = SEQ_FAC_SPEED; + break; + } + ((IpoCurve*) seq->ipo->curve.first) + ->adrcode = adrcode; + ipo_to_animdata((ID*) seq, seq->ipo, + NULL, NULL); + seq->ipo->id.us--; + seq->ipo = NULL; + } + } + } + + /* textures */ for (id= main->tex.first; id; id= id->next) { Tex *te= (Tex *)id; diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index 1920e82b4ab..39b911d1c37 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -820,16 +820,19 @@ static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se) return; } - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, - "effect_fader", 0); - - if (!fcu) { + if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { sh.get_default_fac(seq, cfra, &fac, &facf); if( scene->r.mode & R_FIELDS ); else facf= fac; } else { - fac = facf = evaluate_fcurve(fcu, cfra); - if( scene->r.mode & R_FIELDS ) { - facf = evaluate_fcurve(fcu, cfra + 0.5); + fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, + "effect_fader", 0); + if (fcu) { + fac = facf = evaluate_fcurve(fcu, cfra); + if( scene->r.mode & R_FIELDS ) { + facf = evaluate_fcurve(fcu, cfra + 0.5); + } + } else { + fac = facf = seq->effect_fader; } } @@ -2122,16 +2125,19 @@ static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *s se->se2 = 0; se->se3 = 0; - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, - "effect_fader", 0); - - if (!fcu) { + if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { sh.get_default_fac(seq, cfra, &fac, &facf); if( scene->r.mode & R_FIELDS ); else facf= fac; } else { - fac = facf = evaluate_fcurve(fcu, cfra); - if( scene->r.mode & R_FIELDS ) { - facf = evaluate_fcurve(fcu, cfra + 0.5); + fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, + "effect_fader", 0); + if (fcu) { + fac = facf = evaluate_fcurve(fcu, cfra); + if( scene->r.mode & R_FIELDS ) { + facf = evaluate_fcurve(fcu, cfra + 0.5); + } + } else { + fac = facf = seq->effect_fader; } } -- cgit v1.2.3 From 92b4316708bad0448f4c433ef9c6c2d3cc1f4fb5 Mon Sep 17 00:00:00 2001 From: Arystanbek Dyussenov Date: Sun, 29 Nov 2009 19:16:52 +0000 Subject: Merge from COLLADA branch into trunk of -c 24572 (cmake and scons for OpenCollada @ 675, Linux) and 25001 (bone animation import). See corresponding log entries for more detail. --- source/blender/blenkernel/BKE_texture.h | 2 +- source/blender/blenkernel/intern/texture.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index b9dc5916e69..95ada45f5d8 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -62,7 +62,7 @@ int do_colorband(struct ColorBand *coba, float in, float out[4]); void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size); void default_tex(struct Tex *tex); -struct Tex *add_texture(char *name); +struct Tex *add_texture(const char *name); void default_mtex(struct MTex *mtex); struct MTex *add_mtex(void); struct Tex *copy_texture(struct Tex *tex); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 0171c58f2c6..818e6195049 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -518,7 +518,7 @@ void default_tex(Tex *tex) /* ------------------------------------------------------------------------- */ -Tex *add_texture(char *name) +Tex *add_texture(const char *name) { Tex *tex; -- cgit v1.2.3 From 2bef608fb391fda4c87238abf10e2d3823a883d8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Nov 2009 23:14:41 +0000 Subject: - new objects added from the rna api defaulted to quat rotation, not even using an identity quat. - making meshes in python isnt nice at the moment, added a helper function. mesh.from_pydata(verts, edges, faces) --- source/blender/blenkernel/intern/object.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 73a1d2023a2..69c57fb38fe 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -963,6 +963,7 @@ Object *add_only_object(int type, char *name) /* default object vars */ ob->type= type; /* ob->transflag= OB_QUAT; */ + ob->rotmode= ROT_MODE_EUL; #if 0 /* not used yet */ unit_qt(ob->quat); -- cgit v1.2.3 From a96f6f2e15af08a9eb2f0ea4567abaddecdf5ac0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 29 Nov 2009 23:54:41 +0000 Subject: * Moved rotation initialisation code for new objects to 'the other' add object function that campbell fixed earlier. This should mean that the py-api does everything in the right way now. * Tried adding 'Load Factory Settings' to File menu, but I seem to be running up against some RNA bugs. Can be removed if is too problematic. --- source/blender/blenkernel/intern/object.c | 40 ++++++++++--------------------- 1 file changed, 13 insertions(+), 27 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 69c57fb38fe..1e047380641 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -962,20 +962,22 @@ Object *add_only_object(int type, char *name) /* default object vars */ ob->type= type; - /* ob->transflag= OB_QUAT; */ - ob->rotmode= ROT_MODE_EUL; - -#if 0 /* not used yet */ - unit_qt(ob->quat); - unit_qt(ob->dquat); -#endif - + ob->col[0]= ob->col[1]= ob->col[2]= 1.0; ob->col[3]= 1.0; - - ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0; - ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0; + ob->size[0]= ob->size[1]= ob->size[2]= 1.0; + + /* objects should default to having Euler XYZ rotations, + * but rotations default to quaternions + */ + ob->rotmode= ROT_MODE_EUL; + /* axis-angle must not have a 0,0,0 axis, so set y-axis as default... */ + ob->rotAxis[1]= ob->drotAxis[1]= 1.0f; + /* quaternions should be 1,0,0,0 by default.... */ + ob->quat[0]= ob->dquat[0]= 1.0f; + /* rotation locks should be 4D for 4 component rotations by default... */ + ob->protectflag = OB_LOCK_ROT4D; unit_m4(ob->constinv); unit_m4(ob->parentinv); @@ -993,11 +995,6 @@ Object *add_only_object(int type, char *name) ob->upflag= OB_POSZ; } -#if 0 // XXX old animation system - ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT; - ob->ipowin= ID_OB; /* the ipowin shown */ -#endif // XXX old animation system - ob->dupon= 1; ob->dupoff= 0; ob->dupsta= 1; ob->dupend= 100; ob->dupfacesca = 1.0; @@ -1039,17 +1036,6 @@ Object *add_object(struct Scene *scene, int type) ob->lay= scene->lay; - /* objects should default to having Euler XYZ rotations, - * but rotations default to quaternions - */ - ob->rotmode= ROT_MODE_EUL; - /* axis-angle must not have a 0,0,0 axis, so set y-axis as default... */ - ob->rotAxis[1]= ob->drotAxis[1]= 1.0f; - /* quaternions should be 1,0,0,0 by default.... */ - ob->quat[0]= 1.0f; - /* rotation locks should be 4D for 4 component rotations by default... */ - ob->protectflag = OB_LOCK_ROT4D; - base= scene_add_base(scene, ob); scene_select_base(scene, base); ob->recalc |= OB_RECALC; -- cgit v1.2.3 From b89138564eee9b576263518df0ed5dc045668f75 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Wed, 2 Dec 2009 07:56:34 +0000 Subject: Changes to Color Management After testing and feedback, I've decided to slightly modify the way color management works internally. While the previous method worked well for rendering, was a smaller transition and had some advantages over this new method, it was a bit more ambiguous, and was making things difficult for other areas such as compositing. This implementation now considers all color data (with only a couple of exceptions such as brush colors) to be stored in linear RGB color space, rather than sRGB as previously. This brings it in line with Nuke, which also operates this way, quite successfully. Color swatches, pickers, color ramp display are now gamma corrected to display gamma so you can see what you're doing, but the numbers themselves are considered linear. This makes understanding blending modes more clear (a 0.5 value on overlay will not change the result now) as well as making color swatches act more predictably in the compositor, however bringing over color values from applications like photoshop or gimp, that operate in a gamma space, will give identical results. This commit will convert over existing files saved by earlier 2.5 versions to work generally the same, though there may be some slight differences with things like textures. Now that we're set on changing other areas of shading, this won't be too disruptive overall. I've made a diagram explaining the pipeline here: http://mke3.net/blender/devel/2.5/25_linear_workflow_pipeline.png and some docs here: http://www.blender.org/development/release-logs/blender-250/color-management/ --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_colortools.h | 6 ---- source/blender/blenkernel/intern/colortools.c | 46 --------------------------- source/blender/blenkernel/intern/object.c | 2 +- 4 files changed, 2 insertions(+), 54 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index ebeec31c984..7bbcb63a7f5 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ struct bContext; struct ReportList; #define BLENDER_VERSION 250 -#define BLENDER_SUBVERSION 7 +#define BLENDER_SUBVERSION 8 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index c83a260690b..c571688737a 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -34,12 +34,6 @@ struct CurveMap; struct ImBuf; struct rctf; -void gamma_correct_rec709(float *c, float gamma); -void gamma_correct(float *c, float gamma); -float srgb_to_linearrgb(float c); -float linearrgb_to_srgb(float c); -void color_manage_linearize(float *col_to, float *col_from); - void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index f3448a60b5a..48e42bc539f 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -58,52 +58,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -/* ********************************* color transforms ********************************* */ - -/*Transform linear RGB values to nonlinear RGB values. Rec. - 709 is ITU-R Recommendation BT. 709 (1990) ``Basic - Parameter Values for the HDTV Standard for the Studio and - for International Programme Exchange'', formerly CCIR Rec. - 709.*/ -void gamma_correct_rec709(float *c, float gamma) -{ - /* Rec. 709 gamma correction. */ - const float cc = 0.018f; - - if (*c < cc) - *c *= ((1.099f * (float)powf(cc, gamma)) - 0.099f) * (1.0f/cc); - else - *c = (1.099f * (float)powf(*c, gamma)) - 0.099f; -} - -void gamma_correct(float *c, float gamma) -{ - *c = powf((*c), gamma); -} - -float srgb_to_linearrgb(float c) -{ - if (c < 0.04045f) - return (c < 0.0f)? 0.0f: c*(1.0f/12.92f); - else - return powf((c + 0.055f)*(1.0f/1.055f), 2.4f); -} - -float linearrgb_to_srgb(float c) -{ - if (c < 0.0031308f) - return (c < 0.0f)? 0.0f: c * 12.92f; - else - return 1.055f * powf(c, 1.0f/2.4f) - 0.055f; -} - -/* utility function convert an RGB triplet from sRGB to linear RGB color space */ -void color_manage_linearize(float *col_to, float *col_from) -{ - col_to[0] = srgb_to_linearrgb(col_from[0]); - col_to[1] = srgb_to_linearrgb(col_from[1]); - col_to[2] = srgb_to_linearrgb(col_from[2]); -} void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 1e047380641..41255415b67 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -795,7 +795,7 @@ void *add_lamp(char *name) la->sun_intensity = 1.0f; la->skyblendtype= MA_RAMP_ADD; la->skyblendfac= 1.0f; - la->sky_colorspace= BLI_CS_CIE; + la->sky_colorspace= BLI_XYZ_CIE; la->sky_exposure= 1.0f; curvemapping_initialize(la->curfalloff); -- cgit v1.2.3 From 47b457f19e881c4402d10058b833afc5aaf17957 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Wed, 2 Dec 2009 20:53:28 +0000 Subject: Bug fix: Verlet integration didn't work properly with moving particle emitters. Thanks for mcreamsurfer for reporting and Farsthary for the patch! --- source/blender/blenkernel/intern/particle_system.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 809b5f2090c..dbe6fbd6dde 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2267,12 +2267,13 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra EffectedPoint epoint; ParticleKey states[5], tkey; float timestep = psys_get_timestep(sim); - float force[3],impulse[3],dx[4][3],dv[4][3]; + float force[3],impulse[3],dx[4][3],dv[4][3],oldpos[3]; float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=sim->psys->cfra; int i, steps=1; /* maintain angular velocity */ VECCOPY(pa->state.ave,pa->prev_state.ave); + VECCOPY(oldpos,pa->state.co); if(part->flag & PART_SIZEMASS) pa_mass*=pa->size; @@ -2399,7 +2400,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra VECADDFAC(pa->state.vel,pa->state.vel,force,dtime); VECADDFAC(pa->state.co,pa->state.co,pa->state.vel,dtime); - VECSUB(pa->state.vel,pa->state.co,pa->prev_state.co); + VECSUB(pa->state.vel,pa->state.co,oldpos); mul_v3_fl(pa->state.vel,1.0f/dtime); break; } -- cgit v1.2.3 From 010c99deb271c629742e32f5e7922d357cafc9f3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 3 Dec 2009 18:35:37 +0000 Subject: Sculpt Branch: * Multithread parts of multires and subsurf. Only loops working on face grid data and do no memory allocation have been multithreaded, others would be more complicated. * Force some CCGSubsurf functions to be inlined, gives a small overall speedup in subsurf code. * Fix sculpting not working correct with transformed objects. * Fix a few cases of "spikes" on lower level multires levels. There's still cases where it happens, usually on boundary cornders. The problem is that in such cases the limit surfaces can be very different from the low res surface, so the tangent space is very different too.. * Fix crash deleting multires higher levels with level set to 0. * Fix crashes that happened sometimes when adding faces in editmode. --- source/blender/blenkernel/BKE_DerivedMesh.h | 1 + source/blender/blenkernel/BKE_subsurf.h | 1 + source/blender/blenkernel/intern/CCGSubSurf.c | 217 ++++++++++++++----------- source/blender/blenkernel/intern/multires.c | 172 +++++++------------- source/blender/blenkernel/intern/subsurf_ccg.c | 12 +- 5 files changed, 192 insertions(+), 211 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index bcafc4c48b2..1f6a8f955ba 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -151,6 +151,7 @@ struct DerivedMesh { int (*getGridSize)(DerivedMesh *dm); DMGridData **(*getGridData)(DerivedMesh *dm); DMGridAdjacency *(*getGridAdjacency)(DerivedMesh *dm); + int *(*getGridOffset)(DerivedMesh *dm); /* Iterate over each mapped vertex in the derived mesh, calling the * given function with the original vert and the mapped vert's new diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 7b8adb7cb8e..0a18850e3b7 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -73,6 +73,7 @@ typedef struct CCGDerivedMesh { struct DMGridData **gridData; struct DMGridAdjacency *gridAdjacency; + int *gridOffset; struct _CCGFace **gridFaces; struct { diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 7c2c6d4d99e..cc2bd531fe6 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -8,6 +8,12 @@ #include "BLO_sys_types.h" // for intptr_t support +#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) @@ -523,19 +529,19 @@ static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int return f; } -static void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) { +static CCG_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) { int maxGridSize = 1 + (1<<(levels-1)); int spacing = 1<<(levels-lvl); byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); return &gridBase[dataSize*x*spacing]; } -static void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) { +static CCG_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) { int maxGridSize = 1 + (1<<(levels-1)); int spacing = 1<<(levels-lvl); byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)]; } -static float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) { +static CCG_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) { int maxGridSize = 1 + (1<<(levels-1)); int spacing = 1<<(levels-lvl); byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); @@ -548,7 +554,7 @@ static int _face_getVertIndex(CCGFace *f, CCGVert *v) { return i; return -1; } -static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) { +static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) { int maxGridSize = 1 + (1<<(levels-1)); int spacing = 1<<(levels-lvl); int S, x, y, cx, cy; @@ -1146,9 +1152,11 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, int normalDataOffset = ss->normalDataOffset; int vertDataSize = ss->meshIFC.vertDataSize; + #pragma omp parallel for private(ptrIdx) schedule(static) for (ptrIdx=0; ptrIdxnumVerts; S++) { for (y=0; yflags&Vert_eEffected) NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1)); } - } - - for (ptrIdx=0; ptrIdxnumVerts; S++) { int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected); @@ -1275,18 +1277,16 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, } } } + + #pragma omp parallel for private(ptrIdx) schedule(static) for (ptrIdx=0; ptrIdxnumVerts; S++) { NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1), FACE_getIFNo(f, lvl, S, gridSize-1, 0)); } - } - for (ptrIdx=0; ptrIdxnumVerts; S++) { for (y=0; yq, *r = ss->r; + int ptrIdx, cornerIdx, i; int vertDataSize = ss->meshIFC.vertDataSize; + void *q = ss->q, *r = ss->r; + #pragma omp parallel for private(ptrIdx) schedule(static) for (ptrIdx=0; ptrIdx1.0) { for (x=0; xnumFaces; i++) { - CCGFace *f = e->faces[i]; + for (j=0; jnumFaces; j++) { + CCGFace *f = e->faces[j]; VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize)); numFaces++; } @@ -1460,10 +1463,10 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, void *nCo = VERT_getCo(v, nextLvl); int sharpCount = 0, allSharp = 1; float avgSharpness = 0.0; - int seam = VERT_seam(v), seamEdges = 0; + int j, seam = VERT_seam(v), seamEdges = 0; - for (i=0; inumEdges; i++) { - CCGEdge *e = v->edges[i]; + for (j=0; jnumEdges; j++) { + CCGEdge *e = v->edges[j]; float sharpness = EDGE_getSharpness(e, curLvl); if (seam && _edge_isBoundary(e)) @@ -1493,8 +1496,8 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, int numBoundary = 0; VertDataZero(r); - for (i=0; inumEdges; i++) { - CCGEdge *e = v->edges[i]; + for (j=0; jnumEdges; j++) { + CCGEdge *e = v->edges[j]; if (_edge_isBoundary(e)) { VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); numBoundary++; @@ -1510,15 +1513,15 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, int numEdges = 0, numFaces = 0; VertDataZero(q); - for (i=0; inumFaces; i++) { - CCGFace *f = v->faces[i]; + for (j=0; jnumFaces; j++) { + CCGFace *f = v->faces[j]; VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx)); numFaces++; } VertDataMulN(q, 1.0f/numFaces); VertDataZero(r); - for (i=0; inumEdges; i++) { - CCGEdge *e = v->edges[i]; + for (j=0; jnumEdges; j++) { + CCGEdge *e = v->edges[j]; VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize)); numEdges++; } @@ -1540,8 +1543,8 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, allSharp = 1; } - for (i=0; inumEdges; i++) { - CCGEdge *e = v->edges[i]; + for (j=0; jnumEdges; j++) { + CCGEdge *e = v->edges[j]; float sharpness = EDGE_getSharpness(e, curLvl); if (seam) { @@ -1585,6 +1588,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, float sharpness = EDGE_getSharpness(e, curLvl); int sharpCount = 0; float avgSharpness = 0.0; + int x, j; if (sharpness!=0.0f) { sharpCount = 2; @@ -1622,8 +1626,8 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, VertDataZero(r); VertDataAdd(r, EDGE_getCo(e, curLvl, x-1)); VertDataAdd(r, EDGE_getCo(e, curLvl, x+1)); - for (i=0; inumFaces; i++) { - CCGFace *f = e->faces[i]; + for (j=0; jnumFaces; j++) { + CCGFace *f = e->faces[j]; VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize)); VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize)); @@ -1654,52 +1658,91 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, } } - for (ptrIdx=0; ptrIdxnumVerts; S++) { - VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1)); - } - VertDataMulN(q, 1.0f/f->numVerts); - VertDataZero(r); - for (S=0; SnumVerts; S++) { - VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1)); + #pragma omp critical + { + q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); + r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); } - VertDataMulN(r, 1.0f/f->numVerts); - VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f); - VertDataAdd(FACE_getCenterData(f), q); - VertDataAdd(FACE_getCenterData(f), r); - VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts); + #pragma omp for schedule(static) + for (ptrIdx=0; ptrIdxnumVerts; S++) { - /* interior face shift - * o old interior face point (shifting) - * o new interior edge midpoints + /* interior center point shift + * o old face center point (shifting) + * o old interior edge points * o new interior face midpoints */ - for (x=1; xnumVerts; S++) { + VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1)); + } + VertDataMulN(q, 1.0f/f->numVerts); + VertDataZero(r); + for (S=0; SnumVerts; S++) { + VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1)); + } + VertDataMulN(r, 1.0f/f->numVerts); + + VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f); + VertDataAdd(FACE_getCenterData(f), q); + VertDataAdd(FACE_getCenterData(f), r); + VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts); + + for (S=0; SnumVerts; S++) { + /* interior face shift + * o old interior face point (shifting) + * o new interior edge midpoints + * o new interior face midpoints + */ + for (x=1; xnumVerts, 1, fx-1), + FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1), + FACE_getIFCo(f, nextLvl, S, fx+1, +1), + FACE_getIFCo(f, nextLvl, S, fx-1, +1)); - VertDataAvg4(r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0), - FACE_getIFCo(f, nextLvl, S, fx+1, fy+0), - FACE_getIFCo(f, nextLvl, S, fx+0, fy-1), - FACE_getIFCo(f, nextLvl, S, fx+0, fy+1)); + VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1), + FACE_getIECo(f, nextLvl, S, fx+1), + FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx), + FACE_getIFCo(f, nextLvl, S, fx, 1)); VertDataCopy(nCo, co); VertDataSub(nCo, q); @@ -1707,32 +1750,12 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, VertDataAdd(nCo, r); } } + } - /* interior edge interior shift - * o old interior edge point (shifting) - * o new interior edge midpoints - * o new interior face midpoints - */ - for (x=1; xnumVerts, 1, fx-1), - FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1), - FACE_getIFCo(f, nextLvl, S, fx+1, +1), - FACE_getIFCo(f, nextLvl, S, fx-1, +1)); - - VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1), - FACE_getIECo(f, nextLvl, S, fx+1), - FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx), - FACE_getIFCo(f, nextLvl, S, fx, 1)); - - VertDataCopy(nCo, co); - VertDataSub(nCo, q); - VertDataMulN(nCo, 0.25f); - VertDataAdd(nCo, r); - } + #pragma omp critical + { + CCGSUBSURF_free(ss, q); + CCGSUBSURF_free(ss, r); } } @@ -1740,13 +1763,19 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, edgeSize = 1 + (1<<(nextLvl)); gridSize = 1 + (1<<((nextLvl)-1)); cornerIdx = gridSize-1; + + #pragma omp parallel for private(i) schedule(static) for (i=0; iv0, nextLvl)); VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl)); } + + #pragma omp parallel for private(i) schedule(static) for (i=0; inumVerts; S++) { CCGEdge *e = FACE_getEdges(f)[S]; CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index a709b45f60c..69659db3ba7 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -248,39 +248,45 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object int lvl = multires_get_level(ob, mmd, 0); int levels = mmd->totlvl - lvl; MDisps *mdisps; - + CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); multires_force_update(ob); if(mdisps && levels > 0 && direction == 1) { - int nsize = multires_side_tot[lvl]; - int hsize = multires_side_tot[mmd->totlvl]; - int i; + if(lvl > 0) { + int nsize = multires_side_tot[lvl]; + int hsize = multires_side_tot[mmd->totlvl]; + int i; - for(i = 0; i < me->totface; ++i) { - MDisps *mdisp= &mdisps[i]; - float (*disps)[3], (*ndisps)[3], (*hdisps)[3]; - int nvert = (me->mface[i].v4)? 4: 3; - int totdisp = multires_grid_tot[lvl]*nvert; - int S; + for(i = 0; i < me->totface; ++i) { + MDisps *mdisp= &mdisps[i]; + float (*disps)[3], (*ndisps)[3], (*hdisps)[3]; + int nvert = (me->mface[i].v4)? 4: 3; + int totdisp = multires_grid_tot[lvl]*nvert; + int S; - disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); - ndisps = disps; - hdisps = mdisp->disps; + ndisps = disps; + hdisps = mdisp->disps; - for(S = 0; S < nvert; S++) { - multires_copy_grid(ndisps, hdisps, nsize, hsize); + for(S = 0; S < nvert; S++) { + multires_copy_grid(ndisps, hdisps, nsize, hsize); - ndisps += nsize*nsize; - hdisps += hsize*hsize; - } + ndisps += nsize*nsize; + hdisps += hsize*hsize; + } - MEM_freeN(mdisp->disps); - mdisp->disps = disps; - mdisp->totdisp = totdisp; + MEM_freeN(mdisp->disps); + mdisp->disps = disps; + mdisp->totdisp = totdisp; + } + } + else { + CustomData_external_remove(&me->fdata, CD_MDISPS, me->totface); + CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface); } } @@ -409,105 +415,27 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat multires_set_tot_level(ob, mmd, totlvl); } -static void grid_adjacent_rotate(int rotation, int gridSize, int *x, int *y) -{ - /* we rotate (rotation * 90°) counterclockwise around center */ - int nx, ny; - - switch(rotation) { - case 0: nx = *x; ny = *y; break; - case 1: nx = *y; ny = *x; break; - case 2: nx = *x; ny = *y; break; //gridSize - 1 - *x; ny = gridSize - 1 - *y; break; - case 3: nx = *y; ny = *x; break; - } - - *x = nx; - *y = ny; -} - -static void grid_adjacent_jump(DMGridAdjacency *adj, int gridSize, int *index, int *x, int *y) -{ - if(*x < 0) { - if(adj->index[3] == -1) { - /* no adjacent grid, clamp */ - *x = 0; - } - else { - /* jump to adjacent grid */ - *index = adj->index[3]; - *x += gridSize; - grid_adjacent_rotate(adj->rotation[3], gridSize, x, y); - } - } - else if(*x >= gridSize) { - if(adj->index[1] == -1) { - /* no adjacent grid, take a step back */ - *x = gridSize - 1; - } - else { - /* jump to adjacent grid */ - *index = adj->index[1]; - *x -= gridSize; - grid_adjacent_rotate(adj->rotation[1], gridSize, x, y); - } - } - else if(*y < 0) { - if(adj->index[0] == -1) { - /* no adjacent grid, clamp */ - *y = 0; - } - else { - /* jump to adjacent grid */ - *index = adj->index[0]; - *y += gridSize; - grid_adjacent_rotate(adj->rotation[0], gridSize, x, y); - } - } - else if(*y >= gridSize) { - if(adj->index[2] == -1) { - /* no adjacent grid, take a step back */ - *y = gridSize - 1; - } - else { - /* jump to adjacent grid */ - *index = adj->index[2]; - *y -= gridSize; - grid_adjacent_rotate(adj->rotation[2], gridSize, x, y); - } - } -} - -static void grid_tangent(DMGridAdjacency *adj, int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3]) +static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3]) { - int jindex = index, jx = x, jy = y; - if(axis == 0) { - if(adj->index[1] == -1 && x == gridSize - 1) { - if(adj->index[2] == -1 && y == gridSize - 1) + if(x == gridSize - 1) { + if(y == gridSize - 1) sub_v3_v3v3(t, gridData[index][x + gridSize*(y - 1)].co, gridData[index][x - 1 + gridSize*(y - 1)].co); else sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x - 1 + gridSize*y].co); } - else { - jx += 1; - grid_adjacent_jump(adj, gridSize, &jindex, &jx, &jy); - sub_v3_v3v3(t, gridData[jindex][jx + gridSize*jy].co, gridData[index][x + gridSize*y].co); - } + else + sub_v3_v3v3(t, gridData[index][x + 1 + gridSize*y].co, gridData[index][x + gridSize*y].co); } else if(axis == 1) { - if(adj->index[2] == -1 && y == gridSize - 1) { - if(adj->index[1] == -1 && x == gridSize - 1) { + if(y == gridSize - 1) { + if(x == gridSize - 1) sub_v3_v3v3(t, gridData[index][x - 1 + gridSize*y].co, gridData[index][x - 1 + gridSize*(y - 1)].co); - } - else { + else sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x + gridSize*(y - 1)].co); - } - } - else { - jy += 1; - grid_adjacent_jump(adj, gridSize, &jindex, &jx, &jy); - sub_v3_v3v3(t, gridData[jindex][jx + gridSize*jy].co, gridData[index][x + gridSize*y].co); } + else + sub_v3_v3v3(t, gridData[index][x + gridSize*(y + 1)].co, gridData[index][x + gridSize*y].co); } } @@ -515,28 +443,36 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; DMGridData **gridData, **subGridData; - DMGridAdjacency *gridAdjacency; MFace *mface = me->mface; MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); - int i, S, x, y, numGrids, gIndex, gridSize, dGridSize, dSkip; + int *gridOffset; + int i, numGrids, gridSize, dGridSize, dSkip; numGrids = dm->getNumGrids(dm); gridSize = dm->getGridSize(dm); gridData = dm->getGridData(dm); - gridAdjacency = dm->getGridAdjacency(dm); + gridOffset = dm->getGridOffset(dm); subGridData = (oldGridData)? oldGridData: gridData; dGridSize = multires_side_tot[totlvl]; dSkip = (dGridSize-1)/(gridSize-1); - for(gIndex = 0, i = 0; i < me->totface; ++i) { + #pragma omp parallel for private(i) schedule(static) + for(i = 0; i < me->totface; ++i) { const int numVerts = mface[i].v4 ? 4 : 3; MDisps *mdisp = &mdisps[i]; + int S, x, y, gIndex = gridOffset[i]; + + /* when adding new faces in edit mode, need to allocate disps */ + if(!mdisp->disps) + #pragma omp critical + { + multires_reallocate_mdisps(me, mdisps, totlvl); + } for(S = 0; S < numVerts; ++S, ++gIndex) { DMGridData *grid = gridData[gIndex]; DMGridData *subgrid = subGridData[gIndex]; - DMGridAdjacency *adj = &gridAdjacency[gIndex]; float (*dispgrid)[3] = &mdisp->disps[S*dGridSize*dGridSize]; for(y = 0; y < gridSize; y++) { @@ -548,12 +484,16 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int float mat[3][3], tx[3], ty[3], disp[3], d[3]; /* construct tangent space matrix */ - grid_tangent(adj, gridSize, gIndex, x, y, 0, subGridData, tx); + grid_tangent(gridSize, gIndex, x, y, 0, subGridData, tx); normalize_v3(tx); - grid_tangent(adj, gridSize, gIndex, x, y, 1, subGridData, ty); + grid_tangent(gridSize, gIndex, x, y, 1, subGridData, ty); normalize_v3(ty); + //mul_v3_fl(tx, 1.0f/(gridSize-1)); + //mul_v3_fl(ty, 1.0f/(gridSize-1)); + //cross_v3_v3v3(no, tx, ty); + column_vectors_to_mat3(mat, tx, ty, no); if(!invert) { diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 716229e6ead..c9d84670044 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1894,6 +1894,7 @@ static void ccgDM_release(DerivedMesh *dm) { if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces); if(ccgdm->gridData) MEM_freeN(ccgdm->gridData); if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency); + if(ccgdm->gridOffset) MEM_freeN(ccgdm->gridOffset); if(ccgdm->freeSS) ccgSubSurf_free(ccgdm->ss); MEM_freeN(ccgdm->edgeFlags); MEM_freeN(ccgdm->faceFlags); @@ -2112,7 +2113,7 @@ static void ccgdm_create_grids(DerivedMesh *dm) ccgdm->gridData = gridData; ccgdm->gridFaces = gridFaces; ccgdm->gridAdjacency = gridAdjacency; - MEM_freeN(gridOffset); + ccgdm->gridOffset = gridOffset; } static DMGridData **ccgDM_getGridData(DerivedMesh *dm) @@ -2131,6 +2132,14 @@ static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm) return ccgdm->gridAdjacency; } +static int *ccgDM_getGridOffset(DerivedMesh *dm) +{ + CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; + + ccgdm_create_grids(dm); + return ccgdm->gridOffset; +} + static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) { CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; @@ -2209,6 +2218,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.getGridSize = ccgDM_getGridSize; ccgdm->dm.getGridData = ccgDM_getGridData; ccgdm->dm.getGridAdjacency = ccgDM_getGridAdjacency; + ccgdm->dm.getGridOffset = ccgDM_getGridOffset; ccgdm->dm.getPBVH = ccgDM_getPBVH; ccgdm->dm.getVertCos = ccgdm_getVertCos; -- cgit v1.2.3 From b1a1a0f135f1f32551aea766c9faeb6f07875970 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 4 Dec 2009 01:25:43 +0000 Subject: Cleaning: update a couple of functions to use scene from context instead of from screen. --- source/blender/blenkernel/BKE_screen.h | 3 ++- source/blender/blenkernel/intern/depsgraph.c | 2 +- source/blender/blenkernel/intern/screen.c | 17 ++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 39a90fe3074..bf01ef0ec60 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -41,6 +41,7 @@ struct Header; struct Menu; struct ScrArea; struct SpaceType; +struct Scene; struct wmNotifier; struct wmWindow; struct wmWindowManager; @@ -233,7 +234,7 @@ void BKE_screen_area_free(struct ScrArea *sa); /* screen */ void free_screen(struct bScreen *sc); -unsigned int BKE_screen_visible_layers(struct bScreen *screen); +unsigned int BKE_screen_visible_layers(struct bScreen *screen, struct Scene *scene); #endif diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 302b81f2a04..8535bfc6d0c 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2155,7 +2155,7 @@ static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay for(win=wm->windows.first; win; win=win->next) { if(win->screen) { if(!*sce) *sce= win->screen->scene; - *lay |= BKE_screen_visible_layers(win->screen); + *lay |= BKE_screen_visible_layers(win->screen, win->screen->scene); } } } diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 459db96dbfb..0dc6bf359f6 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -318,21 +318,20 @@ void free_screen(bScreen *sc) } /* for depsgraph */ -unsigned int BKE_screen_visible_layers(bScreen *screen) +unsigned int BKE_screen_visible_layers(bScreen *screen, Scene *scene) { ScrArea *sa; unsigned int layer= 0; - if(!screen) - return layer; - - /* get all used view3d layers */ - for(sa= screen->areabase.first; sa; sa= sa->next) - if(sa->spacetype==SPACE_VIEW3D) - layer |= ((View3D *)sa->spacedata.first)->lay; + if(screen) { + /* get all used view3d layers */ + for(sa= screen->areabase.first; sa; sa= sa->next) + if(sa->spacetype==SPACE_VIEW3D) + layer |= ((View3D *)sa->spacedata.first)->lay; + } if(!layer) - return screen->scene->lay; + return scene->lay; return layer; } -- cgit v1.2.3 From a358b6386d8022f71160ccdb714e596ec63670a6 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Fri, 4 Dec 2009 04:28:50 +0000 Subject: * Fix for incorrect disabling after baking cloth sim * Fix for time cursor getting 'stuck' after baking point caches --- source/blender/blenkernel/BKE_pointcache.h | 1 + source/blender/blenkernel/intern/pointcache.c | 4 +++- 2 files changed, 4 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 5ae10d736fd..4b26eaa6d76 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -151,6 +151,7 @@ typedef struct PTCacheBaker { int (*break_test)(void *data); void *break_data; void (*progressbar)(void *data, int num); + void (*progressend)(void *data); void *progresscontext; } PTCacheBaker; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index c2798b4a746..cc7b942a6bb 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2232,6 +2232,7 @@ void BKE_ptcache_quick_cache_all(Scene *scene) baker.break_test=NULL; baker.pid=NULL; baker.progressbar=NULL; + baker.progressend=NULL; baker.progresscontext=NULL; baker.render=0; baker.anim_init = 0; @@ -2360,6 +2361,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if(baker->break_test && baker->break_test(baker->break_data)) break; } + baker->progressend(baker->progresscontext); /* clear baking flag */ if(pid) { @@ -2400,7 +2402,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) scene->r.framelen = frameleno; CFRA = cfrao; - + if(bake) /* already on cfra unless baking */ scene_update_for_newframe(scene, scene->lay); -- cgit v1.2.3 From 56b0880d2f66ae77e34c7ac518758ea13792056f Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 4 Dec 2009 19:08:07 +0000 Subject: Null check for baking progressend function Simplify end of line for console progress. --- source/blender/blenkernel/intern/pointcache.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index cc7b942a6bb..7b2cf72e311 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2361,7 +2361,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if(baker->break_test && baker->break_test(baker->break_data)) break; } - baker->progressend(baker->progresscontext); + + if (baker->progressend) + baker->progressend(baker->progresscontext); /* clear baking flag */ if(pid) { -- cgit v1.2.3 From a94a2c8c722f50415dcb2c0dad536f787eb42e2b Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Mon, 7 Dec 2009 10:28:36 +0000 Subject: Fix for [#20286] New objects have no Display Type Removed a few more references to shaded mode --- source/blender/blenkernel/intern/exotic.c | 2 +- source/blender/blenkernel/intern/object.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index 48a05c2f6a7..2a0759e6c36 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -4050,7 +4050,7 @@ static void dxf_read(Scene *scene, char *filename) ob->type= OB_MESH; - ob->dt= OB_SHADED; + ob->dt= OB_TEXTURE; ob->trackflag= OB_POSY; ob->upflag= OB_POSZ; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 41255415b67..5806b269e7d 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -982,7 +982,7 @@ Object *add_only_object(int type, char *name) unit_m4(ob->constinv); unit_m4(ob->parentinv); unit_m4(ob->obmat); - ob->dt= OB_SHADED; + ob->dt= OB_TEXTURE; ob->empty_drawtype= OB_ARROWS; ob->empty_drawsize= 1.0; -- cgit v1.2.3 From 74b80f8c3d30b8fc64fdf6eb023641ec94c6d57e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 7 Dec 2009 15:54:27 +0000 Subject: crashfix, duplicating armatures with ID-Props assigned to the bones didnt copy the bone. --- source/blender/blenkernel/intern/armature.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 418c9f00596..e53e4a1155b 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -184,6 +184,9 @@ static void copy_bonechildren (Bone* newBone, Bone* oldBone, Bone* actBone, Bone if(oldBone == actBone) *newActBone= newBone; + if(oldBone->prop) + newBone->prop= IDP_CopyProperty(oldBone->prop); + /* Copy this bone's list*/ BLI_duplicatelist(&newBone->childbase, &oldBone->childbase); -- cgit v1.2.3 From 4a23c3f9e1aaaefcb7b5586b908c51d2922d71fb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 7 Dec 2009 17:55:58 +0000 Subject: Particles: child editing bugfixes * Make partial update work again for faster editing. * Draw parents over children again, nicer for editing. * Fix crash with remove tools & showing child particles. * Fix children not disappearing always when setting to None. * Fix wrong normal for last point in child path. * Fix a python error in the hair dynamics panel. --- source/blender/blenkernel/intern/particle.c | 4 ++++ source/blender/blenkernel/intern/particle_system.c | 2 ++ 2 files changed, 6 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index bb2f4128891..ab73b24ba39 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2332,6 +2332,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c ctx->totparent= totparent; ctx->parent_pass= 0; ctx->cfra= cfra; + ctx->editupdate= editupdate; psys->lattice = psys_get_lattice(&ctx->sim); @@ -2615,6 +2616,9 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle get_strand_normal(ctx->ma, ornor, cur_length, (state-1)->vel); } + if(k == ctx->steps) + VECSUB(state->vel,state->co,(state-1)->co); + /* check if path needs to be cut before actual end of data points */ if(k){ VECSUB(dvec,state->co,(state-1)->co); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index dbe6fbd6dde..3c660be64ce 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2925,6 +2925,8 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra) psys_find_parents(sim); } } + else + psys_free_children(psys); } if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) -- cgit v1.2.3 From 4ca2581b77112c488938f0a2dc226042e0390b71 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 7 Dec 2009 19:11:37 +0000 Subject: Sculpt Branch: * Don't allow adding/removing multires levels in editmode. * Customdata code for swapping mdisps restored. * Fix inflate brush crashing with multires. * Smooth and layer brush don't work yet with multires, but at least avoids crashing now. * Fix threading issue with flatten brush. --- source/blender/blenkernel/intern/customdata.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 8f167310741..f9997708a50 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -440,29 +440,30 @@ static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, fl } #endif +static int mdisp_corners(MDisps *s) +{ + /* silly trick because we don't get it from callback */ + return (s->totdisp % (3*3) == 0)? 3: 4; +} + static void layerSwap_mdisps(void *data, int *ci) { - // XXX -#if 0 MDisps *s = data; float (*d)[3] = NULL; - int x, y, st; + int corners, cornersize, S; - if(!(ci[0] == 2 && ci[1] == 3 && ci[2] == 0 && ci[3] == 1)) return; + /* this function is untested .. */ + corners = mdisp_corners(s); + cornersize = s->totdisp/corners; d = MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); - st = sqrt(s->totdisp); - for(y = 0; y < st; ++y) { - for(x = 0; x < st; ++x) { - copy_v3_v3(d[(st - y - 1) * st + (st - x - 1)], s->disps[y * st + x]); - } - } + 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; -#endif } static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights, -- cgit v1.2.3 From 987e9bc1724602fe6dab35662afa54df26d07cf4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 7 Dec 2009 19:49:14 +0000 Subject: missing null check from recent changes --- source/blender/blenkernel/intern/group.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 3ab02a576d0..f35a0a96bb4 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -217,8 +217,8 @@ static int rem_from_group_internal(Group *group, Object *ob) int rem_from_group(Group *group, Object *object, Scene *scene, Base *base) { if(rem_from_group_internal(group, object)) { - - if(find_group(object, NULL) == NULL) { + /* object can be NULL */ + if(object && find_group(object, NULL) == NULL) { if(scene && base==NULL) base= object_in_scene(object, scene); -- cgit v1.2.3 From 47416c725c9790c17abddfbcd96c080e28e76abb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 7 Dec 2009 19:59:04 +0000 Subject: driver type 'Sum' --- source/blender/blenkernel/intern/fcurve.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 0623a5cbe5e..b3a6b773cf3 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -910,6 +910,7 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime) // TODO: the flags for individual targets need to be used too for more fine-grained support... switch (driver->type) { case DRIVER_TYPE_AVERAGE: /* average values of driver targets */ + case DRIVER_TYPE_SUM: /* sum values of driver targets */ { /* check how many targets there are first (i.e. just one?) */ if (driver->targets.first == driver->targets.last) { @@ -921,19 +922,22 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime) /* more than one target, so average the values of the targets */ int tot = 0; float value = 0.0f; - + /* loop through targets, adding (hopefully we don't get any overflow!) */ for (dtar= driver->targets.first; dtar; dtar=dtar->next) { - value += driver_get_target_value(driver, dtar); + value += driver_get_target_value(driver, dtar); tot++; } - + /* return the average of these */ - return (value / (float)tot); + if(driver->type == DRIVER_TYPE_AVERAGE) + return (value / (float)tot); + else + return value; + } } break; - case DRIVER_TYPE_PYTHON: /* expression */ { #ifndef DISABLE_PYTHON -- cgit v1.2.3 From f350cde18c2103d6a78e4d5d14f9b57cbaab1a1e Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 7 Dec 2009 20:39:57 +0000 Subject: -noaudio option to force the sound system to None. Useful when openAL is not setup properly (*cough* pulseaudio *cough) and prevents startup. This doesn't actually affect the userpref option, so you can set it to whatever you want, save userprefs and restart. --- source/blender/blenkernel/BKE_sound.h | 2 ++ source/blender/blenkernel/intern/sound.c | 10 ++++++++++ 2 files changed, 12 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index cbce4663d6f..64ce1983e7d 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -41,6 +41,8 @@ void sound_init(); void sound_exit(); +void sound_disable(); + struct bSound* sound_new_file(struct Main *main, char* filename); // XXX unused currently diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index d8950c7dace..74c6afdc018 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -31,6 +31,13 @@ #include #endif +static int sound_disabled = 0; + +void sound_disable() +{ + sound_disabled = 1; +} + void sound_init() { AUD_Specs specs; @@ -42,6 +49,9 @@ void sound_init() specs.format = U.audioformat; specs.rate = U.audiorate; + if (sound_disabled) + device = 0; + if(buffersize < 128) buffersize = AUD_DEFAULT_BUFFER_SIZE; -- cgit v1.2.3 From 0391b1ab780b34a149d3c4181d0fe676ef55199e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Dec 2009 10:36:46 +0000 Subject: compile python driver expressions for faster re-evaluation. approx 15-25x speedup --- source/blender/blenkernel/intern/fcurve.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index b3a6b773cf3..04fcd43b883 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -758,7 +758,12 @@ void fcurve_free_driver(FCurve *fcu) dtarn= dtar->next; driver_free_target(driver, dtar); } - + +#ifndef DISABLE_PYTHON + if(driver->expr_comp) + BPY_DECREF(driver->expr_comp); +#endif + /* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */ MEM_freeN(driver); fcu->driver= NULL; -- cgit v1.2.3 From f2452c1fd6fe2009e2ecd794b13b1de1fade277b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 8 Dec 2009 13:57:51 +0000 Subject: Sequencer: * Sound strips now respect metastrips for muting. That means they are muted if the metastrip is muted, and don't play when located outside of the current metastrip. * Operators now use notifiers instead of redraw tagging, added a separate notifier for selection as well, but that is not used to do less redraws yet. --- source/blender/blenkernel/BKE_sequence.h | 1 + source/blender/blenkernel/intern/sequence.c | 47 ++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequence.h b/source/blender/blenkernel/BKE_sequence.h index 2f7526d524c..acc0d8576a1 100644 --- a/source/blender/blenkernel/BKE_sequence.h +++ b/source/blender/blenkernel/BKE_sequence.h @@ -186,6 +186,7 @@ int shuffle_seq_time(ListBase * seqbasep); void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage); void seq_update_sound(struct Sequence *seq); +void seq_update_muting(struct Editing *ed); void clear_scene_in_allseqs(struct Scene *sce); diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index 39b911d1c37..f11aca32da7 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -3477,16 +3477,55 @@ int shuffle_seq_time(ListBase * seqbasep) return offset? 0:1; } - -void seq_update_sound(struct Sequence *seq) +void seq_update_sound(Sequence *seq) { - if(seq->type == SEQ_SOUND) + if(seq->type == SEQ_SOUND && seq->sound_handle) { seq->sound_handle->startframe = seq->startdisp; seq->sound_handle->endframe = seq->enddisp; seq->sound_handle->frameskip = seq->startofs + seq->anim_startofs; - seq->sound_handle->mute = seq->flag & SEQ_MUTE ? 1 : 0; seq->sound_handle->changed = -1; + /* mute is set in seq_update_muting_recursive */ + } +} + +static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute) +{ + Sequence *seq; + int seqmute; + + /* for sound we go over full meta tree to update muted state, + since sound is played outside of evaluating the imbufs, */ + for(seq=seqbasep->first; seq; seq=seq->next) { + seqmute= (mute || (seq->flag & SEQ_MUTE)); + + if(seq->type == SEQ_META) { + /* if this is the current meta sequence, unmute because + all sequences above this were set to mute */ + if(seq == metaseq) + seqmute= 0; + + seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute); + } + else if(seq->type == SEQ_SOUND) { + if(seq->sound_handle && seqmute != seq->sound_handle->mute) { + seq->sound_handle->mute = seqmute; + seq->sound_handle->changed = -1; + } + } + } +} + +void seq_update_muting(Editing *ed) +{ + if(ed) { + /* mute all sounds up to current metastack list */ + MetaStack *ms= ed->metastack.last; + + if(ms) + seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1); + else + seq_update_muting_recursive(&ed->seqbase, NULL, 0); } } -- cgit v1.2.3 From 2ef0ee76a05b39b148ffc280ebf002c9ac9a44da Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Wed, 9 Dec 2009 01:53:04 +0000 Subject: Fix for [#20249] duplicating a mesh in edit mode with a lattice modifier Removed lattice and curve modifiers from being correctable for crazy space - it didn't work and was giving weird results. --- source/blender/blenkernel/BKE_modifier.h | 4 ++-- source/blender/blenkernel/intern/DerivedMesh.c | 2 +- source/blender/blenkernel/intern/modifier.c | 16 ++++++---------- 3 files changed, 9 insertions(+), 13 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index c30bfa3e247..539c2e59dbe 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -280,7 +280,7 @@ void modifier_copyData(struct ModifierData *md, struct ModifierData *ta int modifier_dependsOnTime(struct ModifierData *md); int modifier_supportsMapping(struct ModifierData *md); int modifier_couldBeCage(struct ModifierData *md); -int modifier_isDeformer(struct ModifierData *md); +int modifier_isCorrectableDeformed(struct ModifierData *md); int modifier_sameTopology(ModifierData *md); int modifier_isEnabled(struct ModifierData *md, int required_mode); void modifier_setError(struct ModifierData *md, char *format, ...); @@ -303,7 +303,7 @@ int modifiers_isParticleEnabled(struct Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); struct Object *modifiers_isDeformedByLattice(struct Object *ob); int modifiers_usesArmature(struct Object *ob, struct bArmature *arm); -int modifiers_isDeformed(struct Scene *scene, struct Object *ob); +int modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob); void modifier_freeTemporaryData(struct ModifierData *md); int modifiers_indexInObject(struct Object *ob, struct ModifierData *md); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 209e4610c6a..a681b539097 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2513,7 +2513,7 @@ int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deform } for(; md && i <= cageIndex; md = md->next, i++) - if(editmesh_modifier_is_enabled(md, dm) && modifier_isDeformer(md)) + if(editmesh_modifier_is_enabled(md, dm) && modifier_isCorrectableDeformed(md)) numleft++; if(dm) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 56aab7d2ba9..08c979b89db 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -9151,15 +9151,15 @@ Object *modifiers_isDeformedByArmature(Object *ob) } /* Takes an object and returns its first selected lattice, else just its -* armature -* This should work for multiple armatures per object +* lattice +* This should work for multiple lattics per object */ Object *modifiers_isDeformedByLattice(Object *ob) { ModifierData *md = modifiers_getVirtualModifierList(ob); LatticeModifierData *lmd= NULL; - /* return the first selected armature, this lets us use multiple armatures + /* return the first selected lattice, this lets us use multiple lattices */ for (; md; md=md->next) { if (md->type==eModifierType_Lattice) { @@ -9192,28 +9192,24 @@ int modifiers_usesArmature(Object *ob, bArmature *arm) return 0; } -int modifier_isDeformer(ModifierData *md) +int modifier_isCorrectableDeformed(ModifierData *md) { if (md->type==eModifierType_Armature) return 1; - if (md->type==eModifierType_Curve) - return 1; - if (md->type==eModifierType_Lattice) - return 1; if (md->type==eModifierType_ShapeKey) return 1; return 0; } -int modifiers_isDeformed(Scene *scene, Object *ob) +int modifiers_isCorrectableDeformed(Scene *scene, Object *ob) { ModifierData *md = modifiers_getVirtualModifierList(ob); for (; md; md=md->next) { if(ob->mode==OB_MODE_EDIT && (md->mode & eModifierMode_Editmode)==0); else - if(modifier_isDeformer(md)) + if(modifier_isCorrectableDeformed(md)) return 1; } return 0; -- cgit v1.2.3 From 1c47b3acb6fa03ea13f9a1f545a750439dcd68ab Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Wed, 9 Dec 2009 02:55:19 +0000 Subject: Fix for [#20197] dof node bugs This is still a bit dodgy, the issue of accessing scene data from nodes needs to be solved better, but this at least fixes it up to previous capabilities, and prevents writing any data to scene/objects either. --- source/blender/blenkernel/intern/object.c | 6 +++--- 1 file changed, 3 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 5806b269e7d..048e1cd01e3 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -741,12 +741,12 @@ float dof_camera(Object *ob) if (cam->dof_ob) { /* too simple, better to return the distance on the view axis only * return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); */ - float mat[4][4], obmat[4][4]; + float mat[4][4], imat[4][4], obmat[4][4]; copy_m4_m4(obmat, ob->obmat); normalize_m4(obmat); - invert_m4_m4(ob->imat, obmat); - mul_m4_m4m4(mat, cam->dof_ob->obmat, ob->imat); + invert_m4_m4(imat, obmat); + mul_m4_m4m4(mat, cam->dof_ob->obmat, imat); return (float)fabs(mat[3][2]); } return cam->YF_dofdist; -- cgit v1.2.3 From 9ea765e5d316ca6d2b15da2392e9da3643a856bb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 9 Dec 2009 13:37:19 +0000 Subject: Sculpt Branch: * Smooth brush works again for multires. * Optimal Display option for multires modifier, same as subsurf. --- source/blender/blenkernel/BKE_multires.h | 20 ++++---- source/blender/blenkernel/intern/CCGSubSurf.c | 27 +++++++---- source/blender/blenkernel/intern/multires.c | 67 +++++++++++++++++++++++--- source/blender/blenkernel/intern/subsurf_ccg.c | 6 +-- 4 files changed, 91 insertions(+), 29 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 53ead3a5eda..ff320bc7d25 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -27,24 +27,22 @@ * ***** END GPL LICENSE BLOCK ***** */ +#ifndef BKE_MULTIRES_H +#define BKE_MULTIRES_H + struct DerivedMesh; struct Mesh; struct MFace; +struct Multires; struct MultiresModifierData; struct Object; -typedef struct MultiresSubsurf { - struct MultiresModifierData *mmd; - struct Object *ob; - int local_mmd; -} MultiresSubsurf; - void multires_mark_as_modified(struct Object *ob); void multires_force_update(struct Object *ob); -struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*, int local_mmd, struct DerivedMesh*, - struct Object *, int, int); +struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*, + int local_mmd, struct DerivedMesh*, struct Object *, int, int); struct MultiresModifierData *find_multires_modifier(struct Object *ob); void multiresModifier_join(struct Object *); @@ -53,7 +51,11 @@ void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object int updateblock, int simple); int multiresModifier_reshape(struct MultiresModifierData *mmd, struct Object *dst, struct Object *src); +void multires_stitch_grids(struct Object *); + /* Related to the old multires */ -struct Multires; void multires_load_old(struct DerivedMesh *, struct Multires *); void multires_free(struct Multires*); + +#endif + diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index cc2bd531fe6..4bd0586c592 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -2228,8 +2228,9 @@ CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, in VertDataZero(FACE_getCenterData(f)); for (S=0; SnumVerts; S++) - for (x=0; xflags&Edge_eEffected) + for (x=0; xnumVerts; S++) { int prevS = (S+f->numVerts-1)%f->numVerts; @@ -2237,18 +2238,23 @@ CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, in CCGEdge *prevE = FACE_getEdges(f)[prevS]; VertDataAdd(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0)); - VertDataAdd(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx)); + if (FACE_getVerts(f)[S]->flags&Vert_eEffected) + VertDataAdd(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx)); for (x=1; xflags&Edge_eEffected) + VertDataAdd(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0)); + if (FACE_getEdges(f)[prevS]->flags&Edge_eEffected) + VertDataAdd(FACE_getIECo(f, lvl, prevS, x), FACE_getIFCo(f, lvl, S, 0, x)); } for (x=0; xflags&Edge_eEffected) + VertDataAdd(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x)); + if (FACE_getEdges(f)[prevS]->flags&Edge_eEffected) + if(x != 0) + VertDataAdd(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx)); } } } @@ -2276,8 +2282,9 @@ CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, in VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts); for (S=0; SnumVerts; S++) - for (x=1; xflags&Edge_eEffected) + for (x=1; xnumVerts; S++) { int prevS = (S+f->numVerts-1)%f->numVerts; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 69659db3ba7..8a76d659d5f 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -39,6 +39,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_pbvh.h" #include "BKE_btex.h" #include "BKE_cdderivedmesh.h" @@ -60,8 +61,8 @@ /* MULTIRES MODIFIER */ static const int multires_max_levels = 13; -static const int multires_grid_tot[] = {1, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; -static const int multires_side_tot[] = {1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; +static const int multires_grid_tot[] = {0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; +static const int multires_side_tot[] = {0, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl); @@ -307,7 +308,7 @@ static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lv return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0); } -static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple) +static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal) { SubsurfModifierData smd; @@ -316,6 +317,8 @@ static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl smd.flags |= eSubsurfModifierFlag_SubsurfUv; if(simple) smd.subdivType = ME_SIMPLE_SUBSURF; + if(optimal) + smd.flags |= eSubsurfModifierFlag_ControlEdges; return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0); } @@ -363,7 +366,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat /* create subsurf DM from original mesh at high level */ cddm = CDDM_from_mesh(me, NULL); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0); /* create multires DM from original mesh at low level */ lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple); @@ -551,7 +554,7 @@ static void multiresModifier_update(DerivedMesh *dm) /* create subsurf DM from original mesh at high level */ cddm = CDDM_from_mesh(me, NULL); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0); /* create multires DM from original mesh and displacements */ lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple); @@ -602,7 +605,7 @@ static void multiresModifier_update(DerivedMesh *dm) DerivedMesh *cddm, *subdm; cddm = CDDM_from_mesh(me, NULL); - subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple); + subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0); cddm->release(cddm); multiresModifier_disp_run(dm, me, 1, 0, subdm->getGridData(subdm), mmd->totlvl); @@ -629,6 +632,25 @@ void multires_force_update(Object *ob) } } +void multires_stitch_grids(Object *ob) +{ + /* utility for smooth brush */ + if(ob && ob->derivedFinal) { + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)ob->derivedFinal; + CCGFace **faces; + int totface; + + if(ccgdm->pbvh) { + BLI_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void***)&faces, &totface); + + if(totface) { + ccgSubSurf_stitchFaces(ccgdm->ss, 0, faces, totface); + MEM_freeN(faces); + } + } + } +} + struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob, int useRenderParams, int isFinalCalc) { @@ -642,7 +664,8 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i if(lvl == 0) return dm; - result = subsurf_dm_create_local(ob, dm, lvl, 0); + result = subsurf_dm_create_local(ob, dm, lvl, + mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges); if(!local_mmd) { ccgdm = (CCGDerivedMesh*)result; @@ -680,6 +703,36 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i /**** Old Multires code **** ***************************/ +#if 0 +static void mdisp_copy_grid(float (*new)[3], int newstride, float (*old)[3], int oldstride, int xoff, int yoff, int xsize, int ysize) +{ + int x, y; + + for(y = 0; y < ysize; ++y) + for(x = 0; x < xsize; ++x) + copy_v3_v3(disps[x + y*side], mdisp->disps[(x + xoffs) + (y + yoffs)*oldside]); + +} + +static void mdisps_convert(MFace *mface, MDisps *mdisp, int lvl) +{ + int side = multires_side_tot[lvl]; + int nvert = (mface->v4)? 4: 3; + int totdisp = multires_grid_tot[lvl]*nvert; + int x, y; + float (*disps)[3]; + + disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + + + +static const int multires_max_levels = 13; +static const int multires_grid_tot[] = {1, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; +static const int multires_side_tot[] = {1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; + +} +#endif + /* Does not actually free lvl itself */ static void multires_free_level(MultiresLevel *lvl) { diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index c9d84670044..f6abedda2b6 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1235,7 +1235,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) CCGFace **faces; int totface; - BLI_pbvh_get_grid_updates(ccgdm->pbvh, (void***)&faces, &totface); + BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void***)&faces, &totface); if(totface) { ccgSubSurf_updateFromFaces(ss, 0, faces, totface); ccgSubSurf_updateNormals(ss, faces, totface); @@ -2155,8 +2155,8 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) numGrids = ccgDM_getNumGrids(dm); ccgdm->pbvh = BLI_pbvh_new(); - BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, numGrids, gridSize, - (void**)ccgdm->gridFaces); + BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, + numGrids, gridSize, (void**)ccgdm->gridFaces); } else if(ob->type == OB_MESH) { Mesh *me= ob->data; -- cgit v1.2.3 From 00b8e65f0aaefc34c91bdfee7f31233bb313f312 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Dec 2009 16:46:41 +0000 Subject: very very bad hack to have sequencer strips fcurve data transform with them. ifdef'd so its not kept in by accident. Committing because without this animating with the sequencer isnt really usable and am not interensted in having many patches applied on artists systems. --- source/blender/blenkernel/BKE_sequence.h | 1 + source/blender/blenkernel/intern/sequence.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequence.h b/source/blender/blenkernel/BKE_sequence.h index acc0d8576a1..b42f023d12a 100644 --- a/source/blender/blenkernel/BKE_sequence.h +++ b/source/blender/blenkernel/BKE_sequence.h @@ -181,6 +181,7 @@ int seq_tx_test(struct Sequence * seq); int check_single_seq(struct Sequence *seq); void fix_single_seq(struct Sequence *seq); int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test); +void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test); int shuffle_seq_time(ListBase * seqbasep); void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage); diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index f11aca32da7..bb1096c9e7e 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -3529,6 +3529,31 @@ void seq_update_muting(Editing *ed) } } + +/* XXX - hackish function needed for transforming strips! TODO - have some better solution */ +void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) +{ + if(scene->adt==NULL || ofs==0) + return; + + char str[32]; + sprintf(str, "[\"%s\"]", seq->name+2); + + FCurve *fcu; + for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) { + if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { + int i; + for (i = 0; i < fcu->totvert; i++) { + BezTriple *bezt= &fcu->bezt[i]; + bezt->vec[0][0] += ofs; + bezt->vec[1][0] += ofs; + bezt->vec[2][0] += ofs; + } + } + } +} + + Sequence *active_seq_get(Scene *scene) { Editing *ed= seq_give_editing(scene, FALSE); -- cgit v1.2.3 From 1d53b78036601c2112e3cdcf26c8affb9f1bc95c Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Wed, 9 Dec 2009 18:08:14 +0000 Subject: Fix compile problem (warnings are important) --- source/blender/blenkernel/intern/sequence.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index bb1096c9e7e..71382a53d5d 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -3533,13 +3533,14 @@ void seq_update_muting(Editing *ed) /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) { + char str[32]; + FCurve *fcu; + if(scene->adt==NULL || ofs==0) return; - char str[32]; sprintf(str, "[\"%s\"]", seq->name+2); - FCurve *fcu; for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) { if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { int i; -- cgit v1.2.3 From c16acaff8b546434902bdced6a01a28edc7b0d02 Mon Sep 17 00:00:00 2001 From: Andrea Weikert Date: Wed, 9 Dec 2009 20:03:08 +0000 Subject: Sequencer fix: Transform Strip wouldn't work with default_fader * added default_fader to transform strip, since it used the old fac too. * removed ANIMATEABLE attribute from the settings in the transform strip, since they are animated via the effect_fader and not directly for now. (too confusing) * UI: only show default_fader for the effect strips that support it Sequencer Durian feature: uniform scale for Sequence transform strip. * for now re-using variable for x-axis scaling. Note: This brings back functionality as close to 2.49 as possible. The Start and End values in the current design are not meant to be animated directly, but via the effect_fader. --- source/blender/blenkernel/intern/seqeffects.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index a1f81bf6166..50fa34b52e3 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2007,8 +2007,12 @@ static void do_transform(Sequence * seq,float facf0, int x, int y, yo = y; //factor scale - factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0; - factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0; + if (scale->uniform_scale) { + factxScale = factyScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0; + } else { + factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0; + factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0; + } //Factor translate if(!scale->percent){ @@ -3080,6 +3084,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.free = free_transform_effect; rval.copy = copy_transform_effect; rval.execute = do_transform_effect; + rval.get_default_fac = get_default_fac_fade; break; case SEQ_SPEED: rval.init = init_speed_effect; -- cgit v1.2.3 From 11ca70b42d2bb46202365358f40e63822a42a840 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 10 Dec 2009 11:08:38 +0000 Subject: Update Handling: moved wm_data_handle_update from windowmanager to scene_update_tagged in blenkernel, code fits better there. --- source/blender/blenkernel/BKE_scene.h | 1 + source/blender/blenkernel/intern/scene.c | 41 +++++++++++++++++++++++++++++--- 2 files changed, 39 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 686fc265de0..ecff62a7952 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -74,6 +74,7 @@ void scene_select_base(struct Scene *sce, struct Base *selbase); /* checks for cycle, returns 1 if it's all OK */ int scene_check_setscene(struct Scene *sce); +void scene_update_tagged(struct Scene *sce); void scene_update_for_newframe(struct Scene *sce, unsigned int lay); void scene_add_render_layer(struct Scene *sce); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 27cb3ad834b..cd9487862ea 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -77,6 +77,7 @@ #include "BKE_node.h" #include "BKE_object.h" #include "BKE_paint.h" +#include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_sequence.h" #include "BKE_world.h" @@ -772,7 +773,7 @@ float frame_to_float (Scene *scene, int cfra) /* see also bsystem_time in objec return ctime; } -static void scene_update(Scene *sce, unsigned int lay) +static void scene_update_newframe(Scene *sce, unsigned int lay) { Base *base; Object *ob; @@ -804,6 +805,40 @@ static void scene_update(Scene *sce, unsigned int lay) } } +/* this is called in main loop, doing tagged updates before redraw */ +void scene_update_tagged(Scene *scene) +{ + Scene *sce; + Base *base; + float ctime = frame_to_float(scene, scene->r.cfra); + + /* update all objects: drivers, matrices, displists, etc. flags set + by depgraph or manual, no layer check here, gets correct flushed */ + + /* sets first, we allow per definition current scene to have + dependencies on sets, but not the other way around. */ + if(scene->set) { + for(SETLOOPER(scene->set, base)) + object_handle_update(scene, base->object); + } + + for(base= scene->base.first; base; base= base->next) { + object_handle_update(scene, base->object); + } + + /* recalc scene animation data here (for sequencer) */ + { + AnimData *adt= BKE_animdata_from_id(&scene->id); + + if(adt && (adt->recalc & ADT_RECALC_ANIM)) + BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, 0); + } + + BKE_ptcache_quick_cache_all(scene); + + /* in the future this should handle updates for all datablocks, not + only objects and scenes. - brecht */ +} /* applies changes right away, does all sets too */ void scene_update_for_newframe(Scene *sce, unsigned int lay) @@ -815,9 +850,9 @@ void scene_update_for_newframe(Scene *sce, unsigned int lay) /* sets first, we allow per definition current scene to have dependencies on sets */ for(sce= sce->set; sce; sce= sce->set) - scene_update(sce, lay); + scene_update_newframe(sce, lay); - scene_update(scene, lay); + scene_update_newframe(scene, lay); } /* return default layer, also used to patch old files */ -- cgit v1.2.3 From acadb8c39f83a4b4112c8c77bac1eb39584ad100 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 10 Dec 2009 14:26:06 +0000 Subject: Sculpt Branch: Revised external multires file saving. Now it is more manual in that you have to specify where to save it, like an image file, but still saved at the same time as the .blend. It would ideally be automatic, but this is difficult to implement, so for now this should at least be more reliable. --- source/blender/blenkernel/BKE_btex.h | 64 --- source/blender/blenkernel/BKE_customdata.h | 10 +- source/blender/blenkernel/BKE_customdata_file.h | 59 +++ source/blender/blenkernel/BKE_utildefines.h | 10 +- source/blender/blenkernel/intern/btex.c | 482 --------------------- source/blender/blenkernel/intern/customdata.c | 125 +++--- source/blender/blenkernel/intern/customdata_file.c | 446 +++++++++++++++++++ source/blender/blenkernel/intern/multires.c | 9 +- 8 files changed, 594 insertions(+), 611 deletions(-) delete mode 100644 source/blender/blenkernel/BKE_btex.h create mode 100644 source/blender/blenkernel/BKE_customdata_file.h delete mode 100644 source/blender/blenkernel/intern/btex.c create mode 100644 source/blender/blenkernel/intern/customdata_file.c (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_btex.h b/source/blender/blenkernel/BKE_btex.h deleted file mode 100644 index cb73fd160d7..00000000000 --- a/source/blender/blenkernel/BKE_btex.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef BKE_BTEX_H -#define BKE_BTEX_H - -#define BTEX_TYPE_IMAGE 0 -#define BTEX_TYPE_MESH 1 - -#define BTEX_LAYER_NAME_MAX 64 - -typedef struct BTex BTex; -typedef struct BTexLayer BTexLayer; - -/* Create/Free */ - -BTex *btex_create(int type); -void btex_free(BTex *btex); - -/* File read/write/remove */ - -int btex_read_open(BTex *btex, char *filename); -int btex_read_layer(BTex *btex, BTexLayer *blay); -int btex_read_data(BTex *btex, int size, void *data); -void btex_read_close(BTex *btex); - -int btex_write_open(BTex *btex, char *filename); -int btex_write_layer(BTex *btex, BTexLayer *blay); -int btex_write_data(BTex *btex, int size, void *data); -void btex_write_close(BTex *btex); - -void btex_remove(char *filename); - -/* Layers */ - -BTexLayer *btex_layer_find(BTex *btex, int type, char *name); -BTexLayer *btex_layer_add(BTex *btex, int type, char *name); -void btex_layer_remove(BTex *btex, BTexLayer *blay); - -/* Mesh */ - -void btex_mesh_set_grids(BTex *btex, int totgrid, int gridsize, int datasize); - -#endif /* BKE_BTEX_H */ - diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 5ce4b396f0e..5f13e702343 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -32,6 +32,7 @@ #ifndef BKE_CUSTOMDATA_H #define BKE_CUSTOMDATA_H +struct ID; struct CustomData; struct CustomDataLayer; typedef unsigned int CustomDataMask; @@ -282,16 +283,15 @@ void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize); /* External file storage */ void CustomData_external_add(struct CustomData *data, - int type, const char *name, int totelem); + struct ID *id, int type, int totelem, const char *filename); void CustomData_external_remove(struct CustomData *data, - int type, int totelem); -void CustomData_external_remove_object(struct CustomData *data); + struct ID *id, int type, int totelem); int CustomData_external_test(struct CustomData *data, int type); void CustomData_external_write(struct CustomData *data, - CustomDataMask mask, int totelem, int free); + struct ID *id, CustomDataMask mask, int totelem, int free); void CustomData_external_read(struct CustomData *data, - CustomDataMask mask, int totelem); + struct ID *id, CustomDataMask mask, int totelem); #endif diff --git a/source/blender/blenkernel/BKE_customdata_file.h b/source/blender/blenkernel/BKE_customdata_file.h new file mode 100644 index 00000000000..5cbff193cd3 --- /dev/null +++ b/source/blender/blenkernel/BKE_customdata_file.h @@ -0,0 +1,59 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BKE_CUSTOMDATA_FILE_H +#define BKE_CUSTOMDATA_FILE_H + +#define CDF_TYPE_IMAGE 0 +#define CDF_TYPE_MESH 1 + +#define CDF_LAYER_NAME_MAX 64 + +typedef struct CDataFile CDataFile; +typedef struct CDataFileLayer CDataFileLayer; + +/* Create/Free */ + +CDataFile *cdf_create(int type); +void cdf_free(CDataFile *cdf); + +/* File read/write/remove */ + +int cdf_read_open(CDataFile *cdf, char *filename); +int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay); +int cdf_read_data(CDataFile *cdf, int size, void *data); +void cdf_read_close(CDataFile *cdf); + +int cdf_write_open(CDataFile *cdf, char *filename); +int cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay); +int cdf_write_data(CDataFile *cdf, int size, void *data); +void cdf_write_close(CDataFile *cdf); + +void cdf_remove(char *filename); + +/* Layers */ + +CDataFileLayer *cdf_layer_find(CDataFile *cdf, int type, char *name); +CDataFileLayer *cdf_layer_add(CDataFile *cdf, int type, char *name, size_t datasize); + +#endif /* BKE_CUSTOMDATA_FILE_H */ + diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index c0ed8430177..c052af775f2 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -168,7 +168,15 @@ #define ENDB MAKE_ID('E','N','D','B') -/* This one rotates the bytes in an int */ +/* This one rotates the bytes in an int64, int (32) and short (16) */ +#define SWITCH_INT64(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \ + s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \ + s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \ + s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; } + #define SWITCH_INT(a) { \ char s_i, *p_i; \ p_i= (char *)&(a); \ diff --git a/source/blender/blenkernel/intern/btex.c b/source/blender/blenkernel/intern/btex.c deleted file mode 100644 index 363e515f6e2..00000000000 --- a/source/blender/blenkernel/intern/btex.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include -#include -#include - -#include "MEM_guardedalloc.h" - -#include "BLI_fileops.h" -#include "BLI_string.h" - -#include "BKE_btex.h" -#include "BKE_global.h" -#include "BKE_utildefines.h" - -/************************* File Format Definitions ***************************/ - -#define BTEX_ENDIAN_LITTLE 0 -#define BTEX_ENDIAN_BIG 1 - -#define BTEX_DATA_FLOAT 0 - -typedef struct BTexHeader { - char ID[4]; /* "BTEX" */ - char endian; /* little, big */ - char version; /* non-compatible versions */ - char subversion; /* compatible sub versions */ - char pad; /* padding */ - - int structbytes; /* size of this struct in bytes */ - int type; /* image, mesh */ - int totlayer; /* number of layers in the file */ -} BTexHeader; - -typedef struct BTexImageHeader { - int structbytes; /* size of this struct in bytes */ - int width; /* image width */ - int height; /* image height */ - int tile_size; /* tile size (required power of 2) */ -} BTexImageHeader; - -typedef struct BTexMeshHeader { - int structbytes; /* size of this struct in bytes */ - int totgrid; /* number of grids */ - int gridsize; /* width of grids */ -} BTexMeshHeader; - -struct BTexLayer { - int structbytes; /* size of this struct in bytes */ - int datatype; /* only float for now */ - int datasize; /* size of data in layer */ - int type; /* layer type */ - char name[BTEX_LAYER_NAME_MAX]; /* layer name */ -}; - -/**************************** Other Definitions ******************************/ - -#define BTEX_VERSION 0 -#define BTEX_SUBVERSION 0 -#define BTEX_TILE_SIZE 64 - -struct BTex { - int type; - - BTexHeader header; - union { - BTexImageHeader image; - BTexMeshHeader mesh; - } btype; - - BTexLayer *layer; - int totlayer; - - FILE *readf; - FILE *writef; - int switchendian; - size_t dataoffset; -}; - -/********************************* Create/Free *******************************/ - -static int btex_endian(void) -{ - if(ENDIAN_ORDER == L_ENDIAN) - return BTEX_ENDIAN_LITTLE; - else - return BTEX_ENDIAN_BIG; -} - -/*static int btex_data_type_size(int datatype) -{ - if(datatype == BTEX_DATA_FLOAT) - return sizeof(float); - - return 0; -}*/ - -BTex *btex_create(int type) -{ - BTex *btex= MEM_callocN(sizeof(BTex), "BTex"); - - btex->type= type; - - return btex; -} - -void btex_free(BTex *btex) -{ - btex_read_close(btex); - btex_write_close(btex); - - if(btex->layer) - MEM_freeN(btex->layer); - - MEM_freeN(btex); -} - -/********************************* Read/Write ********************************/ - -static int btex_read_header(BTex *btex) -{ - BTexHeader *header; - BTexImageHeader *image; - BTexMeshHeader *mesh; - BTexLayer *layer; - FILE *f= btex->readf; - size_t offset = 0; - int a; - - header= &btex->header; - - if(!fread(header, sizeof(BTexHeader), 1, btex->readf)) - return 0; - - if(memcmp(header->ID, "BTEX", sizeof(header->ID)) != 0) - return 0; - if(header->version > BTEX_VERSION) - return 0; - - btex->switchendian= header->endian != btex_endian(); - header->endian= btex_endian(); - - if(btex->switchendian) { - SWITCH_INT(header->type); - SWITCH_INT(header->totlayer); - SWITCH_INT(header->structbytes); - } - - if(!ELEM(header->type, BTEX_TYPE_IMAGE, BTEX_TYPE_MESH)) - return 0; - - offset += header->structbytes; - header->structbytes= sizeof(BTexHeader); - - if(fseek(f, offset, SEEK_SET) != 0) - return 0; - - if(header->type == BTEX_TYPE_IMAGE) { - image= &btex->btype.image; - if(!fread(image, sizeof(BTexImageHeader), 1, f)) - return 0; - - if(btex->switchendian) { - SWITCH_INT(image->width); - SWITCH_INT(image->height); - SWITCH_INT(image->tile_size); - SWITCH_INT(image->structbytes); - } - - offset += image->structbytes; - image->structbytes= sizeof(BTexImageHeader); - } - else if(header->type == BTEX_TYPE_MESH) { - mesh= &btex->btype.mesh; - if(!fread(mesh, sizeof(BTexMeshHeader), 1, f)) - return 0; - - if(btex->switchendian) { - SWITCH_INT(mesh->totgrid); - SWITCH_INT(mesh->gridsize); - SWITCH_INT(mesh->structbytes); - } - - offset += mesh->structbytes; - mesh->structbytes= sizeof(BTexMeshHeader); - } - - if(fseek(f, offset, SEEK_SET) != 0) - return 0; - - btex->layer= MEM_callocN(sizeof(BTexLayer)*header->totlayer, "BTexLayer"); - btex->totlayer= header->totlayer; - - for(a=0; atotlayer; a++) { - layer= &btex->layer[a]; - - if(!fread(layer, sizeof(BTexLayer), 1, f)) - return 0; - - if(btex->switchendian) { - SWITCH_INT(layer->type); - SWITCH_INT(layer->datatype); - SWITCH_INT(layer->datasize); - SWITCH_INT(layer->structbytes); - } - - if(layer->datatype != BTEX_DATA_FLOAT) - return 0; - - offset += layer->structbytes; - layer->structbytes= sizeof(BTexLayer); - - if(fseek(f, offset, SEEK_SET) != 0) - return 0; - } - - btex->dataoffset= offset; - - return 1; -} - -static int btex_write_header(BTex *btex) -{ - BTexHeader *header; - BTexImageHeader *image; - BTexMeshHeader *mesh; - BTexLayer *layer; - FILE *f= btex->writef; - int a; - - header= &btex->header; - - if(!fwrite(header, sizeof(BTexHeader), 1, f)) - return 0; - - if(header->type == BTEX_TYPE_IMAGE) { - image= &btex->btype.image; - if(!fwrite(image, sizeof(BTexImageHeader), 1, f)) - return 0; - } - else if(header->type == BTEX_TYPE_MESH) { - mesh= &btex->btype.mesh; - if(!fwrite(mesh, sizeof(BTexMeshHeader), 1, f)) - return 0; - } - - for(a=0; atotlayer; a++) { - layer= &btex->layer[a]; - - if(!fwrite(layer, sizeof(BTexLayer), 1, f)) - return 0; - } - - return 1; -} - -int btex_read_open(BTex *btex, char *filename) -{ - FILE *f; - - f= fopen(filename, "rb"); - if(!f) - return 0; - - btex->readf= f; - - if(!btex_read_header(btex)) { - btex_read_close(btex); - return 0; - } - - if(btex->header.type != btex->type) { - btex_read_close(btex); - return 0; - } - - return 1; -} - -int btex_read_layer(BTex *btex, BTexLayer *blay) -{ - size_t offset; - int a; - - /* seek to right location in file */ - offset= btex->dataoffset; - for(a=0; atotlayer; a++) { - if(&btex->layer[a] == blay) - break; - else - offset += btex->layer[a].datasize; - } - - return (fseek(btex->readf, offset, SEEK_SET) == 0); -} - -int btex_read_data(BTex *btex, int size, void *data) -{ - float *fdata; - int a; - - /* read data */ - if(!fread(data, size, 1, btex->readf)) - return 0; - - /* switch endian if necessary */ - if(btex->switchendian) { - fdata= data; - - for(a=0; areadf) { - fclose(btex->readf); - btex->readf= NULL; - } -} - -int btex_write_open(BTex *btex, char *filename) -{ - BTexHeader *header; - BTexImageHeader *image; - BTexMeshHeader *mesh; - FILE *f; - - f= fopen(filename, "wb"); - if(!f) - return 0; - - btex->writef= f; - - /* fill header */ - header= &btex->header; - strcpy(header->ID, "BTEX"); - header->endian= btex_endian(); - header->version= BTEX_VERSION; - header->subversion= BTEX_SUBVERSION; - - header->structbytes= sizeof(BTexHeader); - header->type= btex->type; - header->totlayer= btex->totlayer; - - if(btex->type == BTEX_TYPE_IMAGE) { - /* fill image header */ - image= &btex->btype.image; - image->structbytes= sizeof(BTexImageHeader); - image->tile_size= BTEX_TILE_SIZE; - } - else if(btex->type == BTEX_TYPE_MESH) { - /* fill mesh header */ - mesh= &btex->btype.mesh; - mesh->structbytes= sizeof(BTexMeshHeader); - } - - btex_write_header(btex); - - return 1; -} - -int btex_write_layer(BTex *btex, BTexLayer *blay) -{ - return 1; -} - -int btex_write_data(BTex *btex, int size, void *data) -{ - /* write data */ - if(!fwrite(data, size, 1, btex->writef)) - return 0; - - return 1; -} - -void btex_write_close(BTex *btex) -{ - if(btex->writef) { - fclose(btex->writef); - btex->writef= NULL; - } -} - -void btex_remove(char *filename) -{ - BLI_delete(filename, 0, 0); -} - -/********************************** Layers ***********************************/ - -BTexLayer *btex_layer_find(BTex *btex, int type, char *name) -{ - BTexLayer *layer; - int a; - - for(a=0; atotlayer; a++) { - layer= &btex->layer[a]; - - if(layer->type == type && strcmp(layer->name, name) == 0) - return layer; - } - - return NULL; -} - -BTexLayer *btex_layer_add(BTex *btex, int type, char *name) -{ - BTexLayer *newlayer, *layer; - - /* expand array */ - newlayer= MEM_callocN(sizeof(BTexLayer)*(btex->totlayer+1), "BTexLayer"); - memcpy(newlayer, btex->layer, sizeof(BTexLayer)*btex->totlayer); - btex->layer= newlayer; - - btex->totlayer++; - - /* fill in new layer */ - layer= &btex->layer[btex->totlayer-1]; - layer->structbytes= sizeof(BTexLayer); - layer->datatype= BTEX_DATA_FLOAT; - layer->type= type; - BLI_strncpy(layer->name, name, BTEX_LAYER_NAME_MAX); - - return layer; -} - -void btex_layer_remove(BTex *btex, BTexLayer *layer) -{ - BTexLayer *newlayer; - int index= layer - btex->layer; - - /* expand array */ - newlayer= MEM_callocN(sizeof(BTexLayer)*(btex->totlayer-1), "BTexLayer"); - if(index > 0) - memcpy(newlayer, btex->layer, sizeof(BTexLayer)*index); - if(index+1 < btex->totlayer) - memcpy(newlayer+index, btex->layer+index+1, sizeof(BTexLayer)*(btex->totlayer-(index+1))); - btex->layer= newlayer; - - btex->totlayer--; -} - -/********************************* Mesh **************************************/ - -void btex_mesh_set_grids(BTex *btex, int totgrid, int gridsize, int datasize) -{ - BTexLayer *layer; - int a; - - btex->btype.mesh.totgrid= totgrid; - btex->btype.mesh.gridsize= gridsize; - - for(a=0; atotlayer; a++) { - layer= &btex->layer[a]; - layer->datasize= datasize; - } -} - diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index f9997708a50..d9e85d5d412 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -48,8 +48,8 @@ #include "BLI_mempool.h" #include "BLI_string.h" -#include "BKE_btex.h" #include "BKE_customdata.h" +#include "BKE_customdata_file.h" #include "BKE_global.h" #include "BKE_utildefines.h" @@ -95,11 +95,14 @@ typedef struct LayerTypeInfo { default is assumed to be all zeros */ void (*set_default)(void *data, int count); - /* a function to read data from a btex file */ - int (*read)(BTex *btex, void *data, int count); + /* a function to read data from a cdf file */ + int (*read)(CDataFile *cdf, void *data, int count); - /* a function to write data to a btex file */ - int (*write)(BTex *btex, void *data, int count); + /* a function to write data to a cdf file */ + int (*write)(CDataFile *cdf, void *data, int count); + + /* a function to determine file size */ + size_t (*filesize)(CDataFile *cdf, void *data, int count); } LayerTypeInfo; static void layerCopy_mdeformvert(const void *source, void *dest, @@ -550,7 +553,7 @@ static void layerFree_mdisps(void *data, int count, int size) } } -static int layerRead_mdisps(BTex *btex, void *data, int count) +static int layerRead_mdisps(CDataFile *cdf, void *data, int count) { MDisps *d = data; int i; @@ -559,7 +562,7 @@ static int layerRead_mdisps(BTex *btex, void *data, int count) if(!d[i].disps) d[i].disps = MEM_callocN(sizeof(float)*3*d[i].totdisp, "mdisps read"); - if(!btex_read_data(btex, d[i].totdisp*3*sizeof(float), d[i].disps)) { + if(!cdf_read_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) { printf("failed to read %d/%d %d\n", i, count, d[i].totdisp); return 0; } @@ -568,13 +571,13 @@ static int layerRead_mdisps(BTex *btex, void *data, int count) return 1; } -static int layerWrite_mdisps(BTex *btex, void *data, int count) +static int layerWrite_mdisps(CDataFile *cdf, void *data, int count) { MDisps *d = data; int i; for(i = 0; i < count; ++i) { - if(!btex_write_data(btex, d[i].totdisp*3*sizeof(float), d[i].disps)) { + if(!cdf_write_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) { printf("failed to write %d/%d %d\n", i, count, d[i].totdisp); return 0; } @@ -583,6 +586,18 @@ static int layerWrite_mdisps(BTex *btex, void *data, int count) return 1; } +static size_t layerFilesize_mdisps(CDataFile *cdf, void *data, int count) +{ + MDisps *d = data; + size_t size = 0; + int i; + + for(i = 0; i < count; ++i) + size += d[i].totdisp*3*sizeof(float); + + return size; +} + /* --------- */ static void layerDefault_mloopcol(void *data, int count) @@ -776,7 +791,7 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, - layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps}, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps}, {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, @@ -838,8 +853,6 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataLayer *layer, *newlayer; int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0; - CustomData_external_read(dest, mask, totelem); - for(i = 0; i < source->totlayer; ++i) { layer = &source->layers[i]; typeInfo = layerType_getInfo(layer->type); @@ -2297,18 +2310,20 @@ int CustomData_verify_versions(struct CustomData *data, int index) /****************************** External Files *******************************/ -static void customdata_external_filename(char filename[FILE_MAX], CustomDataExternal *external) +static void customdata_external_filename(char filename[FILE_MAX], ID *id, CustomDataExternal *external) { + char *path = (id->lib)? id->lib->filename: G.sce; + BLI_strncpy(filename, external->filename, FILE_MAX); - BLI_convertstringcode(filename, G.sce); + BLI_convertstringcode(filename, path); } -void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem) +void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int totelem) { CustomDataExternal *external= data->external; CustomDataLayer *layer; - BTex *btex; - BTexLayer *blay; + CDataFile *cdf; + CDataFileLayer *blay; char filename[FILE_MAX]; const LayerTypeInfo *typeInfo; int i, update = 0; @@ -2329,10 +2344,10 @@ void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem if(!update) return; - customdata_external_filename(filename, external); + customdata_external_filename(filename, id, external); - btex= btex_create(BTEX_TYPE_MESH); - if(!btex_read_open(btex, filename)) + cdf= cdf_create(CDF_TYPE_MESH); + if(!cdf_read_open(cdf, filename)) return; for(i=0; itotlayer; i++) { @@ -2342,11 +2357,11 @@ void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem if(!(mask & (1<type))); else if(layer->flag & CD_FLAG_IN_MEMORY); else if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) { - blay= btex_layer_find(btex, layer->type, layer->name); + blay= cdf_layer_find(cdf, layer->type, layer->name); if(blay) { - if(btex_read_layer(btex, blay)) { - if(typeInfo->read(btex, layer->data, totelem)); + if(cdf_read_layer(cdf, blay)) { + if(typeInfo->read(cdf, layer->data, totelem)); else break; layer->flag |= CD_FLAG_IN_MEMORY; } @@ -2356,16 +2371,16 @@ void CustomData_external_read(CustomData *data, CustomDataMask mask, int totelem } } - btex_read_close(btex); - btex_free(btex); + cdf_read_close(cdf); + cdf_free(cdf); } -void CustomData_external_write(CustomData *data, CustomDataMask mask, int totelem, int free) +void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, int totelem, int free) { CustomDataExternal *external= data->external; CustomDataLayer *layer; - BTex *btex; - BTexLayer *blay; + CDataFile *cdf; + CDataFileLayer *blay; const LayerTypeInfo *typeInfo; int i, update = 0; char filename[FILE_MAX]; @@ -2385,20 +2400,21 @@ void CustomData_external_write(CustomData *data, CustomDataMask mask, int totele if(!update) return; - CustomData_external_read(data, mask, totelem); + CustomData_external_read(data, id, mask, totelem); - btex= btex_create(BTEX_TYPE_MESH); + cdf= cdf_create(CDF_TYPE_MESH); for(i=0; itotlayer; i++) { layer = &data->layers[i]; typeInfo = layerType_getInfo(layer->type); - if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) - btex_layer_add(btex, layer->type, layer->name); + if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) + cdf_layer_add(cdf, layer->type, layer->name, + typeInfo->filesize(cdf, layer->data, totelem)); } - customdata_external_filename(filename, external); - if(!btex_write_open(btex, filename)) + customdata_external_filename(filename, id, external); + if(!cdf_write_open(cdf, filename)) return; for(i=0; itotlayer; i++) { @@ -2406,10 +2422,10 @@ void CustomData_external_write(CustomData *data, CustomDataMask mask, int totele typeInfo = layerType_getInfo(layer->type); if((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { - blay= btex_layer_find(btex, layer->type, layer->name); + blay= cdf_layer_find(cdf, layer->type, layer->name); - if(btex_write_layer(btex, blay)) { - if(typeInfo->write(btex, layer->data, totelem)); + if(cdf_write_layer(cdf, blay)) { + if(typeInfo->write(cdf, layer->data, totelem)); else break; } else @@ -2418,7 +2434,7 @@ void CustomData_external_write(CustomData *data, CustomDataMask mask, int totele } if(i != data->totlayer) { - btex_free(btex); + cdf_free(cdf); return; } @@ -2435,11 +2451,11 @@ void CustomData_external_write(CustomData *data, CustomDataMask mask, int totele } } - btex_write_close(btex); - btex_free(btex); + cdf_write_close(cdf); + cdf_free(cdf); } -void CustomData_external_add(CustomData *data, int type, const char *name, int totelem) +void CustomData_external_add(CustomData *data, ID *id, int type, int totelem, const char *filename) { CustomDataExternal *external= data->external; CustomDataLayer *layer; @@ -2454,23 +2470,20 @@ void CustomData_external_add(CustomData *data, int type, const char *name, int t return; if(!external) { - char hex[MAX_ID_NAME*2]; - external= MEM_callocN(sizeof(CustomDataExternal), "CustomDataExternal"); - BLI_strhex(hex, sizeof(hex), name); - BLI_snprintf(external->filename, sizeof(external->filename), "//%s_mesh.btex", hex); + BLI_strncpy(external->filename, filename, sizeof(external->filename)); data->external= external; } layer->flag |= CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY; } -void CustomData_external_remove(CustomData *data, int type, int totelem) +void CustomData_external_remove(CustomData *data, ID *id, int type, int totelem) { CustomDataExternal *external= data->external; CustomDataLayer *layer; - char filename[FILE_MAX]; - int layer_index, i, remove_file; + //char filename[FILE_MAX]; + int layer_index; // i, remove_file; layer_index = CustomData_get_active_layer_index(data, type); if(layer_index < 0) return; @@ -2482,20 +2495,22 @@ void CustomData_external_remove(CustomData *data, int type, int totelem) if(layer->flag & CD_FLAG_EXTERNAL) { if(!(layer->flag & CD_FLAG_IN_MEMORY)) - CustomData_external_read(data, (1<type), totelem); + CustomData_external_read(data, id, (1<type), totelem); layer->flag &= ~CD_FLAG_EXTERNAL; +#if 0 remove_file= 1; for(i=0; itotlayer; i++) if(data->layers[i].flag & CD_FLAG_EXTERNAL) remove_file= 0; if(remove_file) { - customdata_external_filename(filename, external); - btex_remove(filename); + customdata_external_filename(filename, id, external); + cdf_remove(filename); CustomData_external_free(data); } +#endif } } @@ -2511,7 +2526,8 @@ int CustomData_external_test(CustomData *data, int type) return (layer->flag & CD_FLAG_EXTERNAL); } -void CustomData_external_remove_object(CustomData *data) +#if 0 +void CustomData_external_remove_object(CustomData *data, ID *id) { CustomDataExternal *external= data->external; char filename[FILE_MAX]; @@ -2519,8 +2535,9 @@ void CustomData_external_remove_object(CustomData *data) if(!external) return; - customdata_external_filename(filename, external); - btex_remove(filename); + customdata_external_filename(filename, id, external); + cdf_remove(filename); CustomData_external_free(data); } +#endif diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c new file mode 100644 index 00000000000..b58ada878de --- /dev/null +++ b/source/blender/blenkernel/intern/customdata_file.c @@ -0,0 +1,446 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_fileops.h" +#include "BLI_string.h" + +#include "BKE_customdata_file.h" +#include "BKE_global.h" +#include "BKE_utildefines.h" + +/************************* File Format Definitions ***************************/ + +#define CDF_ENDIAN_LITTLE 0 +#define CDF_ENDIAN_BIG 1 + +#define CDF_DATA_FLOAT 0 + +typedef struct CDataFileHeader { + char ID[4]; /* "BCDF" */ + char endian; /* little, big */ + char version; /* non-compatible versions */ + char subversion; /* compatible sub versions */ + char pad; /* padding */ + + int structbytes; /* size of this struct in bytes */ + int type; /* image, mesh */ + int totlayer; /* number of layers in the file */ +} CDataFileHeader; + +typedef struct CDataFileImageHeader { + int structbytes; /* size of this struct in bytes */ + int width; /* image width */ + int height; /* image height */ + int tile_size; /* tile size (required power of 2) */ +} CDataFileImageHeader; + +typedef struct CDataFileMeshHeader { + int structbytes; /* size of this struct in bytes */ +} CDataFileMeshHeader; + +struct CDataFileLayer { + int structbytes; /* size of this struct in bytes */ + int datatype; /* only float for now */ + uint64_t datasize; /* size of data in layer */ + int type; /* layer type */ + char name[CDF_LAYER_NAME_MAX]; /* layer name */ +}; + +/**************************** Other Definitions ******************************/ + +#define CDF_VERSION 0 +#define CDF_SUBVERSION 0 +#define CDF_TILE_SIZE 64 + +struct CDataFile { + int type; + + CDataFileHeader header; + union { + CDataFileImageHeader image; + CDataFileMeshHeader mesh; + } btype; + + CDataFileLayer *layer; + int totlayer; + + FILE *readf; + FILE *writef; + int switchendian; + size_t dataoffset; +}; + +/********************************* Create/Free *******************************/ + +static int cdf_endian(void) +{ + if(ENDIAN_ORDER == L_ENDIAN) + return CDF_ENDIAN_LITTLE; + else + return CDF_ENDIAN_BIG; +} + +/*static int cdf_data_type_size(int datatype) +{ + if(datatype == CDF_DATA_FLOAT) + return sizeof(float); + + return 0; +}*/ + +CDataFile *cdf_create(int type) +{ + CDataFile *cdf= MEM_callocN(sizeof(CDataFile), "CDataFile"); + + cdf->type= type; + + return cdf; +} + +void cdf_free(CDataFile *cdf) +{ + cdf_read_close(cdf); + cdf_write_close(cdf); + + if(cdf->layer) + MEM_freeN(cdf->layer); + + MEM_freeN(cdf); +} + +/********************************* Read/Write ********************************/ + +static int cdf_read_header(CDataFile *cdf) +{ + CDataFileHeader *header; + CDataFileImageHeader *image; + CDataFileMeshHeader *mesh; + CDataFileLayer *layer; + FILE *f= cdf->readf; + size_t offset = 0; + int a; + + header= &cdf->header; + + if(!fread(header, sizeof(CDataFileHeader), 1, cdf->readf)) + return 0; + + if(memcmp(header->ID, "BCDF", sizeof(header->ID)) != 0) + return 0; + if(header->version > CDF_VERSION) + return 0; + + cdf->switchendian= header->endian != cdf_endian(); + header->endian= cdf_endian(); + + if(cdf->switchendian) { + SWITCH_INT(header->type); + SWITCH_INT(header->totlayer); + SWITCH_INT(header->structbytes); + } + + if(!ELEM(header->type, CDF_TYPE_IMAGE, CDF_TYPE_MESH)) + return 0; + + offset += header->structbytes; + header->structbytes= sizeof(CDataFileHeader); + + if(fseek(f, offset, SEEK_SET) != 0) + return 0; + + if(header->type == CDF_TYPE_IMAGE) { + image= &cdf->btype.image; + if(!fread(image, sizeof(CDataFileImageHeader), 1, f)) + return 0; + + if(cdf->switchendian) { + SWITCH_INT(image->width); + SWITCH_INT(image->height); + SWITCH_INT(image->tile_size); + SWITCH_INT(image->structbytes); + } + + offset += image->structbytes; + image->structbytes= sizeof(CDataFileImageHeader); + } + else if(header->type == CDF_TYPE_MESH) { + mesh= &cdf->btype.mesh; + if(!fread(mesh, sizeof(CDataFileMeshHeader), 1, f)) + return 0; + + if(cdf->switchendian) + SWITCH_INT(mesh->structbytes); + + offset += mesh->structbytes; + mesh->structbytes= sizeof(CDataFileMeshHeader); + } + + if(fseek(f, offset, SEEK_SET) != 0) + return 0; + + cdf->layer= MEM_callocN(sizeof(CDataFileLayer)*header->totlayer, "CDataFileLayer"); + cdf->totlayer= header->totlayer; + + for(a=0; atotlayer; a++) { + layer= &cdf->layer[a]; + + if(!fread(layer, sizeof(CDataFileLayer), 1, f)) + return 0; + + if(cdf->switchendian) { + SWITCH_INT(layer->type); + SWITCH_INT(layer->datatype); + SWITCH_INT64(layer->datasize); + SWITCH_INT(layer->structbytes); + } + + if(layer->datatype != CDF_DATA_FLOAT) + return 0; + + offset += layer->structbytes; + layer->structbytes= sizeof(CDataFileLayer); + + if(fseek(f, offset, SEEK_SET) != 0) + return 0; + } + + cdf->dataoffset= offset; + + return 1; +} + +static int cdf_write_header(CDataFile *cdf) +{ + CDataFileHeader *header; + CDataFileImageHeader *image; + CDataFileMeshHeader *mesh; + CDataFileLayer *layer; + FILE *f= cdf->writef; + int a; + + header= &cdf->header; + + if(!fwrite(header, sizeof(CDataFileHeader), 1, f)) + return 0; + + if(header->type == CDF_TYPE_IMAGE) { + image= &cdf->btype.image; + if(!fwrite(image, sizeof(CDataFileImageHeader), 1, f)) + return 0; + } + else if(header->type == CDF_TYPE_MESH) { + mesh= &cdf->btype.mesh; + if(!fwrite(mesh, sizeof(CDataFileMeshHeader), 1, f)) + return 0; + } + + for(a=0; atotlayer; a++) { + layer= &cdf->layer[a]; + + if(!fwrite(layer, sizeof(CDataFileLayer), 1, f)) + return 0; + } + + return 1; +} + +int cdf_read_open(CDataFile *cdf, char *filename) +{ + FILE *f; + + f= fopen(filename, "rb"); + if(!f) + return 0; + + cdf->readf= f; + + if(!cdf_read_header(cdf)) { + cdf_read_close(cdf); + return 0; + } + + if(cdf->header.type != cdf->type) { + cdf_read_close(cdf); + return 0; + } + + return 1; +} + +int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay) +{ + size_t offset; + int a; + + /* seek to right location in file */ + offset= cdf->dataoffset; + for(a=0; atotlayer; a++) { + if(&cdf->layer[a] == blay) + break; + else + offset += cdf->layer[a].datasize; + } + + return (fseek(cdf->readf, offset, SEEK_SET) == 0); +} + +int cdf_read_data(CDataFile *cdf, int size, void *data) +{ + float *fdata; + int a; + + /* read data */ + if(!fread(data, size, 1, cdf->readf)) + return 0; + + /* switch endian if necessary */ + if(cdf->switchendian) { + fdata= data; + + for(a=0; areadf) { + fclose(cdf->readf); + cdf->readf= NULL; + } +} + +int cdf_write_open(CDataFile *cdf, char *filename) +{ + CDataFileHeader *header; + CDataFileImageHeader *image; + CDataFileMeshHeader *mesh; + FILE *f; + + f= fopen(filename, "wb"); + if(!f) + return 0; + + cdf->writef= f; + + /* fill header */ + header= &cdf->header; + strcpy(header->ID, "BCDF"); + header->endian= cdf_endian(); + header->version= CDF_VERSION; + header->subversion= CDF_SUBVERSION; + + header->structbytes= sizeof(CDataFileHeader); + header->type= cdf->type; + header->totlayer= cdf->totlayer; + + if(cdf->type == CDF_TYPE_IMAGE) { + /* fill image header */ + image= &cdf->btype.image; + image->structbytes= sizeof(CDataFileImageHeader); + image->tile_size= CDF_TILE_SIZE; + } + else if(cdf->type == CDF_TYPE_MESH) { + /* fill mesh header */ + mesh= &cdf->btype.mesh; + mesh->structbytes= sizeof(CDataFileMeshHeader); + } + + cdf_write_header(cdf); + + return 1; +} + +int cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay) +{ + return 1; +} + +int cdf_write_data(CDataFile *cdf, int size, void *data) +{ + /* write data */ + if(!fwrite(data, size, 1, cdf->writef)) + return 0; + + return 1; +} + +void cdf_write_close(CDataFile *cdf) +{ + if(cdf->writef) { + fclose(cdf->writef); + cdf->writef= NULL; + } +} + +void cdf_remove(char *filename) +{ + BLI_delete(filename, 0, 0); +} + +/********************************** Layers ***********************************/ + +CDataFileLayer *cdf_layer_find(CDataFile *cdf, int type, char *name) +{ + CDataFileLayer *layer; + int a; + + for(a=0; atotlayer; a++) { + layer= &cdf->layer[a]; + + if(layer->type == type && strcmp(layer->name, name) == 0) + return layer; + } + + return NULL; +} + +CDataFileLayer *cdf_layer_add(CDataFile *cdf, int type, char *name, size_t datasize) +{ + CDataFileLayer *newlayer, *layer; + + /* expand array */ + newlayer= MEM_callocN(sizeof(CDataFileLayer)*(cdf->totlayer+1), "CDataFileLayer"); + memcpy(newlayer, cdf->layer, sizeof(CDataFileLayer)*cdf->totlayer); + cdf->layer= newlayer; + + cdf->totlayer++; + + /* fill in new layer */ + layer= &cdf->layer[cdf->totlayer-1]; + layer->structbytes= sizeof(CDataFileLayer); + layer->datatype= CDF_DATA_FLOAT; + layer->datasize= datasize; + layer->type= type; + BLI_strncpy(layer->name, name, CDF_LAYER_NAME_MAX); + + return layer; +} + diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 8a76d659d5f..20ba360a231 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -41,7 +41,6 @@ #include "BLI_blenlib.h" #include "BLI_pbvh.h" -#include "BKE_btex.h" #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" @@ -250,7 +249,7 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object int levels = mmd->totlvl - lvl; MDisps *mdisps; - CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); multires_force_update(ob); @@ -286,7 +285,7 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object } } else { - CustomData_external_remove(&me->fdata, CD_MDISPS, me->totface); + CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface); CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface); } } @@ -538,7 +537,7 @@ static void multiresModifier_update(DerivedMesh *dm) ob = ccgdm->multires.ob; me = ccgdm->multires.ob->data; mmd = ccgdm->multires.mmd; - CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); if(mdisps) { @@ -690,7 +689,7 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize); } - CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface); + CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl); for(i = 0; i < numGrids; i++) -- cgit v1.2.3 From e7bd63c128975b75afa02a31b4b4e962f8d7d2fd Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 10 Dec 2009 17:37:04 +0000 Subject: Sculpt Branch: * Multires 2.50 -> Branch compatibility code converting to the new displacement format. 2.49 -> 2.50 is not functional yet. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_multires.h | 5 +- source/blender/blenkernel/intern/multires.c | 171 ++++++++++++++++++++++++---- 3 files changed, 153 insertions(+), 25 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 7bbcb63a7f5..08503a3d00c 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ struct bContext; struct ReportList; #define BLENDER_VERSION 250 -#define BLENDER_SUBVERSION 8 +#define BLENDER_SUBVERSION 9 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index ff320bc7d25..2f372f80957 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -54,8 +54,9 @@ int multiresModifier_reshape(struct MultiresModifierData *mmd, struct Object *ds void multires_stitch_grids(struct Object *); /* Related to the old multires */ -void multires_load_old(struct DerivedMesh *, struct Multires *); -void multires_free(struct Multires*); +void multires_free(struct Multires *mr); +void multires_load_old(struct Object *ob, struct Mesh *me); +void multires_load_old_250(struct Mesh *); #endif diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 20ba360a231..bf02bd89f72 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -614,12 +614,16 @@ static void multiresModifier_update(DerivedMesh *dm) } } +static void multires_dm_mark_as_modified(struct DerivedMesh *dm) +{ + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; + ccgdm->multires.modified = 1; +} + void multires_mark_as_modified(struct Object *ob) { - if(ob && ob->derivedFinal) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)ob->derivedFinal; - ccgdm->multires.modified = 1; - } + if(ob && ob->derivedFinal) + multires_dm_mark_as_modified(ob->derivedFinal); } void multires_force_update(Object *ob) @@ -702,35 +706,99 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i /**** Old Multires code **** ***************************/ -#if 0 -static void mdisp_copy_grid(float (*new)[3], int newstride, float (*old)[3], int oldstride, int xoff, int yoff, int xsize, int ysize) +/* Adapted from sculptmode.c */ +static void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) { - int x, y; + int x, y, x2, y2; + const int st_max = st - 1; + float urat, vrat, uopp; + float d[4][3], d2[2][3]; + + if(u < 0) + u = 0; + else if(u >= st) + u = st_max; + if(v < 0) + v = 0; + else if(v >= st) + v = st_max; + + x = floor(u); + y = floor(v); + x2 = x + 1; + y2 = y + 1; + + if(x2 >= st) x2 = st_max; + if(y2 >= st) y2 = st_max; + + urat = u - x; + vrat = v - y; + uopp = 1 - urat; - for(y = 0; y < ysize; ++y) - for(x = 0; x < xsize; ++x) - copy_v3_v3(disps[x + y*side], mdisp->disps[(x + xoffs) + (y + yoffs)*oldside]); + mul_v3_v3fl(d[0], disps[y * st + x], uopp); + mul_v3_v3fl(d[1], disps[y * st + x2], urat); + mul_v3_v3fl(d[2], disps[y2 * st + x], uopp); + mul_v3_v3fl(d[3], disps[y2 * st + x2], urat); + add_v3_v3v3(d2[0], d[0], d[1]); + add_v3_v3v3(d2[1], d[2], d[3]); + mul_v3_fl(d2[0], 1 - vrat); + mul_v3_fl(d2[1], vrat); + + add_v3_v3v3(out, d2[0], d2[1]); } -static void mdisps_convert(MFace *mface, MDisps *mdisp, int lvl) +static void old_mdisps_rotate(int S, int newside, int oldside, int x, int y, float *u, float *v) { - int side = multires_side_tot[lvl]; + float offset = oldside*0.5f - 0.5f; + + if(S == 1) { *u= offset + x; *v = offset - y; } + if(S == 2) { *u= offset + y; *v = offset + x; } + if(S == 3) { *u= offset - x; *v = offset + y; } + if(S == 0) { *u= offset - y; *v = offset - x; } +} + +static void old_mdisps_convert(MFace *mface, MDisps *mdisp) +{ + int newlvl = log(sqrt(mdisp->totdisp)-1)/log(2); + int oldlvl = newlvl+1; + int oldside = multires_side_tot[oldlvl]; + int newside = multires_side_tot[newlvl]; int nvert = (mface->v4)? 4: 3; - int totdisp = multires_grid_tot[lvl]*nvert; - int x, y; - float (*disps)[3]; + int newtotdisp = multires_grid_tot[newlvl]*nvert; + int x, y, S; + float (*disps)[3], (*out)[3], u, v; + + disps = MEM_callocN(sizeof(float) * 3 * newtotdisp, "multires disps"); + + out = disps; + for(S = 0; S < nvert; S++) { + for(y = 0; y < newside; ++y) { + for(x = 0; x < newside; ++x, ++out) { + old_mdisps_rotate(S, newside, oldside, x, y, &u, &v); + old_mdisps_bilinear(*out, mdisp->disps, oldside, u, v); + } + } + } - disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + MEM_freeN(mdisp->disps); + mdisp->totdisp= newtotdisp; + mdisp->disps= disps; +} +void multires_load_old_250(Mesh *me) +{ + MDisps *mdisps; + int a; -static const int multires_max_levels = 13; -static const int multires_grid_tot[] = {1, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; -static const int multires_side_tot[] = {1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; + mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); + if(mdisps) { + for(a=0; atotface; a++) + old_mdisps_convert(&me->mface[a], &mdisps[a]); + } } -#endif /* Does not actually free lvl itself */ static void multires_free_level(MultiresLevel *lvl) @@ -770,6 +838,7 @@ void multires_free(Multires *mr) } } +#if 0 static void create_old_vert_face_map(ListBase **map, IndexNode **mem, const MultiresFace *mface, const int totvert, const int totface) { @@ -893,12 +962,11 @@ static void multires_load_old_faces(ListBase **fmap, ListBase **emap, MultiresLe } /* Loads a multires object stored in the old Multires struct into the new format */ -void multires_load_old(DerivedMesh *dm, Multires *mr) +static void multires_load_old_dm(DerivedMesh *dm, Multires *mr, int totlvl) { MultiresLevel *lvl, *lvl1; MVert *vsrc, *vdst; int src, dst; - int totlvl = 2; // XXX MultiresDM_get_totlvl(dm); int st = multires_side_tot[totlvl - 1] - 1; int extedgelen = multires_side_tot[totlvl] - 2; int *vvmap; // inorder for dst, map to src @@ -1056,4 +1124,63 @@ void multires_load_old(DerivedMesh *dm, Multires *mr) MEM_freeN(vvmap); } +#endif + +void multires_load_old(Object *ob, Mesh *me) +{ + /* XXX not implemented */ +#if 0 + MultiresLevel *lvl; + ModifierData *md; + MultiresModifierData *mmd; + DerivedMesh *dm, *orig; + int i; + + /* Load original level into the mesh */ + lvl = me->mr->levels.first; + CustomData_free_layers(&me->vdata, CD_MVERT, lvl->totvert); + CustomData_free_layers(&me->edata, CD_MEDGE, lvl->totedge); + CustomData_free_layers(&me->fdata, CD_MFACE, lvl->totface); + me->totvert = lvl->totvert; + me->totedge = lvl->totedge; + me->totface = lvl->totface; + me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); + me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge); + me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); + memcpy(me->mvert, me->mr->verts, sizeof(MVert) * me->totvert); + for(i = 0; i < me->totedge; ++i) { + me->medge[i].v1 = lvl->edges[i].v[0]; + me->medge[i].v2 = lvl->edges[i].v[1]; + } + for(i = 0; i < me->totface; ++i) { + me->mface[i].v1 = lvl->faces[i].v[0]; + me->mface[i].v2 = lvl->faces[i].v[1]; + me->mface[i].v3 = lvl->faces[i].v[2]; + me->mface[i].v4 = lvl->faces[i].v[3]; + } + + /* Add a multires modifier to the object */ + md = ob->modifiers.first; + while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) + md = md->next; + mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires); + BLI_insertlinkbefore(&ob->modifiers, md, mmd); + + for(i = 0; i < me->mr->level_count - 1; ++i) + multiresModifier_subdivide(mmd, ob, 1, 0); + + mmd->lvl = mmd->totlvl; + orig = CDDM_from_mesh(me, NULL); + dm = multires_dm_create_from_derived(mmd, 0, orig, ob, 0, 0); + + multires_load_old_dm(dm, me->mr, mmd->totlvl); + + multires_dm_mark_as_modified(dm); + dm->release(dm); + orig->release(orig); +#endif + + /* Remove the old multires */ + multires_free(me->mr); +} -- cgit v1.2.3 From 98dff9b1c71b6936621641897589f1fb59220312 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Fri, 11 Dec 2009 00:09:58 +0000 Subject: For for [#20330] Can't open a file made in 2.49 Hair clothsim internal_friction wasn't being initialised correctly. --- source/blender/blenkernel/intern/cloth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 6c4c7daea7f..dc9a70f2767 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -154,6 +154,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->defgoal = 0.0f; clmd->sim_parms->goalspring = 1.0f; clmd->sim_parms->goalfrict = 0.0f; + clmd->sim_parms->velocity_smooth = 0.0f; if(!clmd->sim_parms->effector_weights) clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL); -- cgit v1.2.3 From 877c47fe350de17f58e55358fe28887a8131cca8 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Fri, 11 Dec 2009 05:23:00 +0000 Subject: Fix for [#20331] adding and removing render layers in specific sequence creates layers with the same name Render layers now use the same consistent 'unique name' function as other parts of Blender (i.e. RenderLayer.001). Updated the defaults for consistency. --- source/blender/blenkernel/intern/scene.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index cd9487862ea..368e05fa441 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -29,6 +29,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include #include #include @@ -862,7 +863,8 @@ void scene_add_render_layer(Scene *sce) int tot= 1 + BLI_countlist(&sce->r.layers); srl= MEM_callocN(sizeof(SceneRenderLayer), "new render layer"); - sprintf(srl->name, "%d RenderLayer", tot); + sprintf(srl->name, "RenderLayer"); + BLI_uniquename(&sce->r.layers, srl, "RenderLayer", '.', offsetof(SceneRenderLayer, name), 32); BLI_addtail(&sce->r.layers, srl); /* note, this is also in render, pipeline.c, to make layer when scenedata doesnt have it */ -- cgit v1.2.3 From 89b6d94e387d4b127dfa7095146b641053a01617 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 11 Dec 2009 10:56:20 +0000 Subject: Sculpt Branch: multires conversion from 2.4 working again. --- source/blender/blenkernel/intern/CCGSubSurf.c | 42 +++++++++++++++ source/blender/blenkernel/intern/CCGSubSurf.h | 1 + source/blender/blenkernel/intern/multires.c | 76 ++++++++++++++++++++++++--- 3 files changed, 111 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 4bd0586c592..dc863869ad8 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -2188,6 +2188,48 @@ CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF return eCCGError_None; } +/* copy other places to face grid coordinates */ +CCGError ccgSubSurf_updateToFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF) +{ + int i, S, x, gridSize, cornerIdx, subdivLevels; + int vertDataSize = ss->meshIFC.vertDataSize, freeF; + + subdivLevels = ss->subdivLevels; + lvl = (lvl)? lvl: subdivLevels; + gridSize = 1 + (1<<(lvl-1)); + cornerIdx = gridSize-1; + + ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF); + + for (i=0; inumVerts; S++) { + int prevS = (S+f->numVerts-1)%f->numVerts; + CCGEdge *e = FACE_getEdges(f)[S]; + CCGEdge *prevE = FACE_getEdges(f)[prevS]; + + for (x=0; xss; + DMGridData *vd; + int index; + int totvert, totedge, totface; + int gridSize = ccgSubSurf_getGridSize(ss); + int edgeSize = ccgSubSurf_getEdgeSize(ss); + int i = 0; + + totface = ccgSubSurf_getNumFaces(ss); + for(index = 0; index < totface; index++) { + CCGFace *f = ccgdm->faceMap[index].face; + int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); + + vd= ccgSubSurf_getFaceCenterData(f); + copy_v3_v3(vd->co, mvert[i].co); + i++; + + for(S = 0; S < numVerts; S++) { + for(x = 1; x < gridSize - 1; x++, i++) { + vd= ccgSubSurf_getFaceGridEdgeData(ss, f, S, x); + copy_v3_v3(vd->co, mvert[i].co); + } + } + + for(S = 0; S < numVerts; S++) { + for(y = 1; y < gridSize - 1; y++) { + for(x = 1; x < gridSize - 1; x++, i++) { + vd= ccgSubSurf_getFaceGridData(ss, f, S, x, y); + copy_v3_v3(vd->co, mvert[i].co); + } + } + } + } + + totedge = ccgSubSurf_getNumEdges(ss); + for(index = 0; index < totedge; index++) { + 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(vd->co, mvert[i].co); + } + } + + totvert = ccgSubSurf_getNumVerts(ss); + for(index = 0; index < totvert; index++) { + CCGVert *v = ccgdm->vertMap[index].vert; + + vd= ccgSubSurf_getVertData(ss, v); + copy_v3_v3(vd->co, mvert[i].co); + i++; + } + + ccgSubSurf_updateToFaces(ss, 0, NULL, 0); +} + /* Loads a multires object stored in the old Multires struct into the new format */ -static void multires_load_old_dm(DerivedMesh *dm, Multires *mr, int totlvl) +static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) { MultiresLevel *lvl, *lvl1; + Multires *mr= me->mr; MVert *vsrc, *vdst; int src, dst; int st = multires_side_tot[totlvl - 1] - 1; @@ -976,7 +1036,7 @@ static void multires_load_old_dm(DerivedMesh *dm, Multires *mr, int totlvl) src = 0; dst = 0; vsrc = mr->verts; - vdst = CDDM_get_verts(dm); + vdst = dm->getVertArray(dm); totvert = dm->getNumVerts(dm); vvmap = MEM_callocN(sizeof(int) * totvert, "multires vvmap"); @@ -1123,13 +1183,13 @@ static void multires_load_old_dm(DerivedMesh *dm, Multires *mr, int totlvl) copy_v3_v3(vdst[i].co, vsrc[vvmap[i]].co); MEM_freeN(vvmap); + + multires_old_mvert_to_ss(dm, vdst); } -#endif + void multires_load_old(Object *ob, Mesh *me) { - /* XXX not implemented */ -#if 0 MultiresLevel *lvl; ModifierData *md; MultiresModifierData *mmd; @@ -1173,14 +1233,14 @@ void multires_load_old(Object *ob, Mesh *me) orig = CDDM_from_mesh(me, NULL); dm = multires_dm_create_from_derived(mmd, 0, orig, ob, 0, 0); - multires_load_old_dm(dm, me->mr, mmd->totlvl); + multires_load_old_dm(dm, me, mmd->totlvl+1); multires_dm_mark_as_modified(dm); dm->release(dm); orig->release(orig); -#endif /* Remove the old multires */ multires_free(me->mr); + me->mr= NULL; } -- cgit v1.2.3 From 86028a66319a67ed14b6d6cd43053a529df5b4a8 Mon Sep 17 00:00:00 2001 From: Andrea Weikert Date: Fri, 11 Dec 2009 22:51:53 +0000 Subject: Sequencer: Transform Strip updates (Durian wish) Removed the Start/End Settings and the effect_fader from the sequencer transform strip. The transform strip can now only be animated directly by keying the Scale X, Scale Y, Translate X, Translate Y and Rotation values. Caveat: The uniform scale re-uses the Scale X value, so when changing the animation on Scale X in the non-uniform scaling case, the uniform scaling will be affected too. This was done to not break files for Durian. Note: As much as I would have liked to clean up the TransformVars, it caused crashes of earlier versions of blender when opening the file. The rna identifiers were also kept as to not break any existing animation on those keys. --- source/blender/blenkernel/BKE_sequence.h | 2 +- source/blender/blenkernel/intern/seqeffects.c | 173 ++++++++++++++------------ source/blender/blenkernel/intern/sequence.c | 10 +- 3 files changed, 97 insertions(+), 88 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequence.h b/source/blender/blenkernel/BKE_sequence.h index b42f023d12a..5b146cd5ecd 100644 --- a/source/blender/blenkernel/BKE_sequence.h +++ b/source/blender/blenkernel/BKE_sequence.h @@ -125,7 +125,7 @@ struct SeqEffectHandle { float-rects or byte-rects (mixed cases are handled one layer up...) */ - void (*execute)(struct Sequence *seq, int cfra, + void (*execute)(struct Scene *scene, struct Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 50fa34b52e3..8af3bf5fac7 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -231,7 +231,7 @@ static ImBuf * IMB_cast_away_list(ImBuf * i) return (ImBuf*) (((void**) i) + 2); } -static void do_plugin_effect(Sequence * seq,int cfra, +static void do_plugin_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -477,7 +477,7 @@ static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, } } -static void do_alphaover_effect(Sequence * seq,int cfra, +static void do_alphaover_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -644,7 +644,7 @@ static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, } } -static void do_alphaunder_effect(Sequence * seq,int cfra, +static void do_alphaunder_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -764,7 +764,7 @@ void do_cross_effect_float(float facf0, float facf1, int x, int y, /* carefull: also used by speed effect! */ -static void do_cross_effect(Sequence * seq,int cfra, +static void do_cross_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -1026,7 +1026,7 @@ static void do_gammacross_effect_float(float facf0, float facf1, } } -static void do_gammacross_effect(Sequence * seq,int cfra, +static void do_gammacross_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -1140,7 +1140,7 @@ static void do_add_effect_float(float facf0, float facf1, int x, int y, } } -static void do_add_effect(Sequence * seq,int cfra, +static void do_add_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -1252,7 +1252,7 @@ static void do_sub_effect_float(float facf0, float facf1, int x, int y, } } -static void do_sub_effect(Sequence * seq,int cfra, +static void do_sub_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -1360,7 +1360,7 @@ static void do_drop_effect_float(float facf0, float facf1, int x, int y, } -static void do_drop_effect(Sequence * seq,int cfra, +static void do_drop_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf * ibuf3, @@ -1481,7 +1481,7 @@ static void do_mul_effect_float(float facf0, float facf1, int x, int y, } } -static void do_mul_effect(Sequence * seq,int cfra, +static void do_mul_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -1931,7 +1931,7 @@ static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1, } } -static void do_wipe_effect(Sequence * seq,int cfra, +static void do_wipe_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -1953,27 +1953,29 @@ static void do_wipe_effect(Sequence * seq,int cfra, ********************************************************************** */ static void init_transform_effect(Sequence *seq) { - TransformVars *scale; + TransformVars *transform; if(seq->effectdata)MEM_freeN(seq->effectdata); seq->effectdata = MEM_callocN(sizeof(struct TransformVars), "transformvars"); - scale = (TransformVars *)seq->effectdata; - scale->ScalexIni = 1; - scale->ScaleyIni = 1; - scale->ScalexFin = 1; - scale->ScaleyFin = 1; - - scale->xIni=0; - scale->xFin=0; - scale->yIni=0; - scale->yFin=0; - - scale->rotIni=0; - scale->rotFin=0; + transform = (TransformVars *)seq->effectdata; + + transform->ScalexIni = 1.0f; + transform->ScaleyIni = 1.0f; + transform->ScalexFin = 1.0f; + transform->ScalexFin = 1.0f; + + transform->xIni=0.0f; + transform->xFin=0.0f; + transform->yIni=0.0f; + transform->yFin=0.0f; + + transform->rotIni=0.0f; + transform->rotFin=0.0f; - scale->interpolation=1; - scale->percent=1; + transform->interpolation=1; + transform->percent=1; + transform->uniform_scale=0; } static int num_inputs_transform() @@ -1992,86 +1994,94 @@ static void copy_transform_effect(Sequence *dst, Sequence *src) dst->effectdata = MEM_dupallocN(src->effectdata); } -static void do_transform(Sequence * seq,float facf0, int x, int y, - struct ImBuf *ibuf1,struct ImBuf *out) +static void transform_image(int x, int y, struct ImBuf *ibuf1, struct ImBuf *out, + float scale_x, float scale_y, float translate_x, float translate_y, + float rotate, int interpolation) { int xo, yo, xi, yi; - float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py; - TransformVars *scale; - - // XXX struct RenderData *rd = NULL; // 2.5 global: &G.scene->r; + float xt, yt, xr, yr; + float s,c; - - scale = (TransformVars *)seq->effectdata; xo = x; yo = y; - - //factor scale - if (scale->uniform_scale) { - factxScale = factyScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0; - } else { - factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0; - factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0; - } - - //Factor translate - if(!scale->percent){ - float rd_s = 0.0f; // XXX 2.5 global: (rd->size / 100.0f); - - tx = scale->xIni * rd_s+(xo / 2.0f) + (scale->xFin * rd_s -(xo / 2.0f) - scale->xIni * rd_s +(xo / 2.0f)) * facf0; - ty = scale->yIni * rd_s+(yo / 2.0f) + (scale->yFin * rd_s -(yo / 2.0f) - scale->yIni * rd_s +(yo / 2.0f)) * facf0; - }else{ - tx = xo*(scale->xIni/100.0f)+(xo / 2.0f) + (xo*(scale->xFin/100.0f)-(xo / 2.0f) - xo*(scale->xIni/100.0f)+(xo / 2.0f)) * facf0; - ty = yo*(scale->yIni/100.0f)+(yo / 2.0f) + (yo*(scale->yFin/100.0f)-(yo / 2.0f) - yo*(scale->yIni/100.0f)+(yo / 2.0f)) * facf0; - } - - //factor Rotate - factRot = scale->rotIni + (scale->rotFin - scale->rotIni) * facf0; - rad = (M_PI * factRot) / 180.0f; - s= sin(rad); - c= cos(rad); - + + // Rotate + s= sin(rotate); + c= cos(rotate); for (yi = 0; yi < yo; yi++) { for (xi = 0; xi < xo; xi++) { - //tranlate point - px = xi-tx; - py = yi-ty; + + //translate point + xt = xi-translate_x; + yt = yi-translate_y; //rotate point with center ref - xaux = c*px + py*s ; - yaux = -s*px + c*py; + xr = c*xt + s*yt; + yr = -s*xt + c*yt; //scale point with center ref - xs = xaux / factxScale; - ys = yaux / factyScale; + xt = xr / scale_x; + yt = yr / scale_y; //undo reference center point - xs += (xo / 2.0f); - ys += (yo / 2.0f); + xt += (xo / 2.0f); + yt += (yo / 2.0f); //interpolate - switch(scale->interpolation) { + switch(interpolation) { case 0: - neareast_interpolation(ibuf1,out, xs,ys,xi,yi); + neareast_interpolation(ibuf1,out, xt,yt,xi,yi); break; case 1: - bilinear_interpolation(ibuf1,out, xs,ys,xi,yi); + bilinear_interpolation(ibuf1,out, xt,yt,xi,yi); break; case 2: - bicubic_interpolation(ibuf1,out, xs,ys,xi,yi); + bicubic_interpolation(ibuf1,out, xt,yt,xi,yi); break; } } - } + } +} + +static void do_transform(Scene *scene, Sequence *seq, float facf0, int x, int y, + struct ImBuf *ibuf1,struct ImBuf *out) +{ + TransformVars *transform = (TransformVars *)seq->effectdata; + float scale_x, scale_y, translate_x, translate_y, rotate_radians; + + // Scale + if (transform->uniform_scale) { + scale_x = scale_y = transform->ScalexIni; + } else { + scale_x = transform->ScalexIni; + scale_y = transform->ScaleyIni; + } + + // Translate + if(!transform->percent){ + float rd_s = (scene->r.size/100.0f); + translate_x = transform->xIni*rd_s+(x/2.0f); + translate_y = transform->yIni*rd_s+(y/2.0f); + }else{ + translate_x = x*(transform->xIni/100.0f)+(x/2.0f); + translate_y = y*(transform->yIni/100.0f)+(y/2.0f); + } + + // Rotate + rotate_radians = (M_PI*transform->rotIni)/180.0f; + + transform_image(x,y, ibuf1, out, scale_x, scale_y, translate_x, translate_y, rotate_radians, transform->interpolation); } -static void do_transform_effect(Sequence * seq,int cfra, + + +static void do_transform_effect(Scene *scene, Sequence *seq,int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) { - do_transform(seq, facf0, x, y, ibuf1, out); + do_transform(scene, seq, facf0, x, y, ibuf1, out); } @@ -2578,7 +2588,7 @@ static void do_glow_effect_float(Sequence *seq, float facf0, float facf1, RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y); } -static void do_glow_effect(Sequence * seq,int cfra, +static void do_glow_effect(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -2633,7 +2643,7 @@ static int early_out_color(struct Sequence *seq, return -1; } -static void do_solid_color(Sequence * seq,int cfra, +static void do_solid_color(Scene *scene, Sequence *seq, int cfra, float facf0, float facf1, int x, int y, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3, struct ImBuf *out) @@ -2996,16 +3006,16 @@ static void get_default_fac_fade(struct Sequence *seq, int cfra, *facf1 /= seq->len; } -static void do_overdrop_effect(struct Sequence * seq, int cfra, +static void do_overdrop_effect(Scene *scene, Sequence *seq, int cfra, float fac, float facf, int x, int y, struct ImBuf * ibuf1, struct ImBuf * ibuf2, struct ImBuf * ibuf3, struct ImBuf * out) { - do_drop_effect(seq, cfra, fac, facf, x, y, + do_drop_effect(scene, seq, cfra, fac, facf, x, y, ibuf1, ibuf2, ibuf3, out); - do_alphaover_effect(seq, cfra, fac, facf, x, y, + do_alphaover_effect(scene, seq, cfra, fac, facf, x, y, ibuf1, ibuf2, ibuf3, out); } @@ -3084,7 +3094,6 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.free = free_transform_effect; rval.copy = copy_transform_effect; rval.execute = do_transform_effect; - rval.get_default_fac = get_default_fac_fade; break; case SEQ_SPEED: rval.init = init_speed_effect; diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index 71382a53d5d..8d3b1a7955b 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -839,7 +839,7 @@ static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se) early_out = sh.early_out(seq, fac, facf); if (early_out == -1) { /* no input needed */ - sh.execute(seq, cfra, fac, facf, + sh.execute(scene, seq, cfra, fac, facf, se->ibuf->x, se->ibuf->y, 0, 0, 0, se->ibuf); return; @@ -928,7 +928,7 @@ static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se) IMB_rect_from_float(se3->ibuf); } - sh.execute(seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf, + sh.execute(scene, seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf, se->ibuf); } @@ -2276,7 +2276,7 @@ static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra } else { sh = get_sequence_effect(seq); - sh.execute(seq, cfra, + sh.execute(scene, seq, cfra, f_cfra - (float) cfra_left, f_cfra - (float) cfra_left, se->ibuf->x, se->ibuf->y, @@ -2510,12 +2510,12 @@ static TStripElem* do_build_seq_array_recursively(Scene *scene, } if (swap_input) { - sh.execute(seq, cfra, + sh.execute(scene, seq, cfra, facf, facf, x, y, se2->ibuf, se1->ibuf_comp, 0, se2->ibuf_comp); } else { - sh.execute(seq, cfra, + sh.execute(scene, seq, cfra, facf, facf, x, y, se1->ibuf_comp, se2->ibuf, 0, se2->ibuf_comp); -- cgit v1.2.3 From abe8c09b8a98f8a4b71e47324b2c6b12624d5440 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 Dec 2009 14:56:45 +0000 Subject: * renamed BKE_sequence.h and sequence.c --> sequencer * renamed util.c --> path_util.c since there are more then 1 of these files which makes setting breakpoints annoying. --- source/blender/blenkernel/BKE_sequence.h | 228 -- source/blender/blenkernel/BKE_sequencer.h | 228 ++ source/blender/blenkernel/intern/blender.c | 2 +- source/blender/blenkernel/intern/scene.c | 2 +- source/blender/blenkernel/intern/seqeffects.c | 2 +- source/blender/blenkernel/intern/sequence.c | 3758 ------------------------- source/blender/blenkernel/intern/sequencer.c | 3758 +++++++++++++++++++++++++ 7 files changed, 3989 insertions(+), 3989 deletions(-) delete mode 100644 source/blender/blenkernel/BKE_sequence.h create mode 100644 source/blender/blenkernel/BKE_sequencer.h delete mode 100644 source/blender/blenkernel/intern/sequence.c create mode 100644 source/blender/blenkernel/intern/sequencer.c (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequence.h b/source/blender/blenkernel/BKE_sequence.h deleted file mode 100644 index 5b146cd5ecd..00000000000 --- a/source/blender/blenkernel/BKE_sequence.h +++ /dev/null @@ -1,228 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2004 Blender Foundation. - * All rights reserved. - * - * Contributor(s): Blender Foundation (2008). - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef BKE_SEQUENCE_H -#define BKE_SEQUENCE_H - -struct Editing; -struct Sequence; -struct Strip; -struct StripElem; -struct ImBuf; -struct Scene; -struct bContext; - -#define MAXSEQ 32 - -#define BUILD_SEQAR_COUNT_NOTHING 0 -#define BUILD_SEQAR_COUNT_CURRENT 1 -#define BUILD_SEQAR_COUNT_CHILDREN 2 - -/* sequence iterator */ - -typedef struct SeqIterator { - struct Sequence **array; - int tot, cur; - - struct Sequence *seq; - int valid; -} SeqIterator; - -void seq_begin(struct Editing *ed, SeqIterator *iter, int use_pointer); -void seq_next(SeqIterator *iter); -void seq_end(SeqIterator *iter); -void seq_array(struct Editing *ed, struct Sequence ***seqarray, int *tot, int use_pointer); - -#define SEQP_BEGIN(ed, seq) \ -{ \ - SeqIterator iter;\ - for(seq_begin(ed, &iter, 1); iter.valid; seq_next(&iter)) { \ - seq= iter.seq; - -#define SEQ_BEGIN(ed, seq) \ - { \ - SeqIterator iter;\ - for(seq_begin(ed, &iter, 0); iter.valid; seq_next(&iter)) { \ - seq= iter.seq; - -#define SEQ_END \ - } \ - seq_end(&iter); \ - } - -#endif - - -/* Wipe effect */ -enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE, - DO_IRIS_WIPE,DO_CLOCK_WIPE}; - - -struct SeqEffectHandle { - /* constructors & destructor */ - /* init & init_plugin are _only_ called on first creation */ - void (*init)(struct Sequence *seq); - void (*init_plugin)(struct Sequence *seq, const char *fname); - - /* number of input strips needed - (called directly after construction) */ - int (*num_inputs)(); - - /* load is called first time after readblenfile in - get_sequence_effect automatically */ - void (*load)(struct Sequence *seq); - - /* duplicate */ - void (*copy)(struct Sequence *dst, struct Sequence *src); - - /* destruct */ - void (*free)(struct Sequence *seq); - - /* returns: -1: no input needed, - 0: no early out, - 1: out = ibuf1, - 2: out = ibuf2 */ - int (*early_out)(struct Sequence *seq, - float facf0, float facf1); - - /* stores the y-range of the effect IPO */ - void (*store_icu_yrange)(struct Sequence * seq, - short adrcode, float *ymin, float *ymax); - - /* stores the default facf0 and facf1 if no IPO is present */ - void (*get_default_fac)(struct Sequence *seq, int cfra, - float * facf0, float * facf1); - - /* execute the effect - sequence effects are only required to either support - float-rects or byte-rects - (mixed cases are handled one layer up...) */ - - void (*execute)(struct Scene *scene, struct Sequence *seq, int cfra, - float facf0, float facf1, - int x, int y, - struct ImBuf *ibuf1, struct ImBuf *ibuf2, - struct ImBuf *ibuf3, struct ImBuf *out); -}; - -/* ********************* prototypes *************** */ - -/* sequence.c */ -void printf_strip(struct Sequence *seq); - -// extern -void seq_free_sequence(struct Scene *scene, struct Sequence *seq); -void seq_free_strip(struct Strip *strip); -void seq_free_editing(struct Scene *scene); -struct Editing *seq_give_editing(struct Scene *scene, int alloc); -char *give_seqname(struct Sequence *seq); -struct ImBuf *give_ibuf_seq(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); -struct ImBuf *give_ibuf_seq_threaded(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); -struct ImBuf *give_ibuf_seq_direct(struct Scene *scene, int rectx, int recty, int cfra, int render_size, struct Sequence *seq); -void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, int render_size); -void calc_sequence(struct Sequence *seq); -void calc_sequence_disp(struct Sequence *seq); -void new_tstripdata(struct Sequence *seq); -void reload_sequence_new_file(struct Scene *scene, struct Sequence * seq); -void sort_seq(struct Scene *scene); -void build_seqar_cb(struct ListBase *seqbase, struct Sequence ***seqar, int *totseq, - int (*test_func)(struct Sequence * seq)); -int evaluate_seq_frame(struct Scene *scene, int cfra); -struct StripElem *give_stripelem(struct Sequence *seq, int cfra); - -// intern? -void update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change); - -/* seqeffects.c */ -// intern? -struct SeqEffectHandle get_sequence_blend(struct Sequence *seq); -void sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, int force); - -// extern -struct SeqEffectHandle get_sequence_effect(struct Sequence *seq); -int get_sequence_effect_num_inputs(int seq_type); - -/* for transform but also could use elsewhere */ -int seq_tx_get_start(struct Sequence *seq); -int seq_tx_get_end(struct Sequence *seq); -int seq_tx_get_final_left(struct Sequence *seq, int metaclip); -int seq_tx_get_final_right(struct Sequence *seq, int metaclip); -void seq_tx_set_final_left(struct Sequence *seq, int val); -void seq_tx_set_final_right(struct Sequence *seq, int val); -void seq_tx_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag); -int seq_tx_test(struct Sequence * seq); -int check_single_seq(struct Sequence *seq); -void fix_single_seq(struct Sequence *seq); -int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test); -void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); -int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test); -int shuffle_seq_time(ListBase * seqbasep); -void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage); - -void seq_update_sound(struct Sequence *seq); -void seq_update_muting(struct Editing *ed); - -void clear_scene_in_allseqs(struct Scene *sce); - -struct Sequence *active_seq_get(struct Scene *scene); -void active_seq_set(struct Scene *scene, struct Sequence *seq); - -/* api for adding new sequence strips */ -typedef struct SeqLoadInfo { - int start_frame; - int channel; - int flag; /* use sound, replace sel */ - int type; - int tot_success; - int tot_error; - int len; /* only for image strips */ - char path[512]; - char name[32]; -} SeqLoadInfo; - -/* SeqLoadInfo.flag */ -#define SEQ_LOAD_REPLACE_SEL 1<<0 -#define SEQ_LOAD_FRAME_ADVANCE 1<<1 -#define SEQ_LOAD_MOVIE_SOUND 1<<2 -#define SEQ_LOAD_SOUND_CACHE 1<<3 - -/* use as an api function */ -typedef struct Sequence *(*SeqLoadFunc)(struct bContext *, ListBase *, struct SeqLoadInfo *); - -struct Sequence *alloc_sequence(ListBase *lb, int cfra, int machine); - -void seq_load_apply(struct Scene *scene, struct Sequence *seq, struct SeqLoadInfo *seq_load); - -void seqUniqueName(ListBase *seqbasep, struct Sequence *seq); - -struct Sequence *sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); -struct Sequence *sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); -struct Sequence *sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); - diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h new file mode 100644 index 00000000000..5b146cd5ecd --- /dev/null +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -0,0 +1,228 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation (2008). + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BKE_SEQUENCE_H +#define BKE_SEQUENCE_H + +struct Editing; +struct Sequence; +struct Strip; +struct StripElem; +struct ImBuf; +struct Scene; +struct bContext; + +#define MAXSEQ 32 + +#define BUILD_SEQAR_COUNT_NOTHING 0 +#define BUILD_SEQAR_COUNT_CURRENT 1 +#define BUILD_SEQAR_COUNT_CHILDREN 2 + +/* sequence iterator */ + +typedef struct SeqIterator { + struct Sequence **array; + int tot, cur; + + struct Sequence *seq; + int valid; +} SeqIterator; + +void seq_begin(struct Editing *ed, SeqIterator *iter, int use_pointer); +void seq_next(SeqIterator *iter); +void seq_end(SeqIterator *iter); +void seq_array(struct Editing *ed, struct Sequence ***seqarray, int *tot, int use_pointer); + +#define SEQP_BEGIN(ed, seq) \ +{ \ + SeqIterator iter;\ + for(seq_begin(ed, &iter, 1); iter.valid; seq_next(&iter)) { \ + seq= iter.seq; + +#define SEQ_BEGIN(ed, seq) \ + { \ + SeqIterator iter;\ + for(seq_begin(ed, &iter, 0); iter.valid; seq_next(&iter)) { \ + seq= iter.seq; + +#define SEQ_END \ + } \ + seq_end(&iter); \ + } + +#endif + + +/* Wipe effect */ +enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE, + DO_IRIS_WIPE,DO_CLOCK_WIPE}; + + +struct SeqEffectHandle { + /* constructors & destructor */ + /* init & init_plugin are _only_ called on first creation */ + void (*init)(struct Sequence *seq); + void (*init_plugin)(struct Sequence *seq, const char *fname); + + /* number of input strips needed + (called directly after construction) */ + int (*num_inputs)(); + + /* load is called first time after readblenfile in + get_sequence_effect automatically */ + void (*load)(struct Sequence *seq); + + /* duplicate */ + void (*copy)(struct Sequence *dst, struct Sequence *src); + + /* destruct */ + void (*free)(struct Sequence *seq); + + /* returns: -1: no input needed, + 0: no early out, + 1: out = ibuf1, + 2: out = ibuf2 */ + int (*early_out)(struct Sequence *seq, + float facf0, float facf1); + + /* stores the y-range of the effect IPO */ + void (*store_icu_yrange)(struct Sequence * seq, + short adrcode, float *ymin, float *ymax); + + /* stores the default facf0 and facf1 if no IPO is present */ + void (*get_default_fac)(struct Sequence *seq, int cfra, + float * facf0, float * facf1); + + /* execute the effect + sequence effects are only required to either support + float-rects or byte-rects + (mixed cases are handled one layer up...) */ + + void (*execute)(struct Scene *scene, struct Sequence *seq, int cfra, + float facf0, float facf1, + int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out); +}; + +/* ********************* prototypes *************** */ + +/* sequence.c */ +void printf_strip(struct Sequence *seq); + +// extern +void seq_free_sequence(struct Scene *scene, struct Sequence *seq); +void seq_free_strip(struct Strip *strip); +void seq_free_editing(struct Scene *scene); +struct Editing *seq_give_editing(struct Scene *scene, int alloc); +char *give_seqname(struct Sequence *seq); +struct ImBuf *give_ibuf_seq(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); +struct ImBuf *give_ibuf_seq_threaded(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); +struct ImBuf *give_ibuf_seq_direct(struct Scene *scene, int rectx, int recty, int cfra, int render_size, struct Sequence *seq); +void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, int render_size); +void calc_sequence(struct Sequence *seq); +void calc_sequence_disp(struct Sequence *seq); +void new_tstripdata(struct Sequence *seq); +void reload_sequence_new_file(struct Scene *scene, struct Sequence * seq); +void sort_seq(struct Scene *scene); +void build_seqar_cb(struct ListBase *seqbase, struct Sequence ***seqar, int *totseq, + int (*test_func)(struct Sequence * seq)); +int evaluate_seq_frame(struct Scene *scene, int cfra); +struct StripElem *give_stripelem(struct Sequence *seq, int cfra); + +// intern? +void update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change); + +/* seqeffects.c */ +// intern? +struct SeqEffectHandle get_sequence_blend(struct Sequence *seq); +void sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, int force); + +// extern +struct SeqEffectHandle get_sequence_effect(struct Sequence *seq); +int get_sequence_effect_num_inputs(int seq_type); + +/* for transform but also could use elsewhere */ +int seq_tx_get_start(struct Sequence *seq); +int seq_tx_get_end(struct Sequence *seq); +int seq_tx_get_final_left(struct Sequence *seq, int metaclip); +int seq_tx_get_final_right(struct Sequence *seq, int metaclip); +void seq_tx_set_final_left(struct Sequence *seq, int val); +void seq_tx_set_final_right(struct Sequence *seq, int val); +void seq_tx_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag); +int seq_tx_test(struct Sequence * seq); +int check_single_seq(struct Sequence *seq); +void fix_single_seq(struct Sequence *seq); +int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test); +void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); +int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test); +int shuffle_seq_time(ListBase * seqbasep); +void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage); + +void seq_update_sound(struct Sequence *seq); +void seq_update_muting(struct Editing *ed); + +void clear_scene_in_allseqs(struct Scene *sce); + +struct Sequence *active_seq_get(struct Scene *scene); +void active_seq_set(struct Scene *scene, struct Sequence *seq); + +/* api for adding new sequence strips */ +typedef struct SeqLoadInfo { + int start_frame; + int channel; + int flag; /* use sound, replace sel */ + int type; + int tot_success; + int tot_error; + int len; /* only for image strips */ + char path[512]; + char name[32]; +} SeqLoadInfo; + +/* SeqLoadInfo.flag */ +#define SEQ_LOAD_REPLACE_SEL 1<<0 +#define SEQ_LOAD_FRAME_ADVANCE 1<<1 +#define SEQ_LOAD_MOVIE_SOUND 1<<2 +#define SEQ_LOAD_SOUND_CACHE 1<<3 + +/* use as an api function */ +typedef struct Sequence *(*SeqLoadFunc)(struct bContext *, ListBase *, struct SeqLoadInfo *); + +struct Sequence *alloc_sequence(ListBase *lb, int cfra, int machine); + +void seq_load_apply(struct Scene *scene, struct Sequence *seq, struct SeqLoadInfo *seq_load); + +void seqUniqueName(ListBase *seqbasep, struct Sequence *seq); + +struct Sequence *sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); +struct Sequence *sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); +struct Sequence *sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); + diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 8391ebdebb7..afb1335b86b 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -83,7 +83,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_sequence.h" +#include "BKE_sequencer.h" #include "BKE_sound.h" #include "BLI_editVert.h" diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 368e05fa441..43017a75835 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -80,7 +80,7 @@ #include "BKE_paint.h" #include "BKE_pointcache.h" #include "BKE_scene.h" -#include "BKE_sequence.h" +#include "BKE_sequencer.h" #include "BKE_world.h" #include "BKE_utildefines.h" diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 8af3bf5fac7..2c532bfed1c 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -44,7 +44,7 @@ #include "BKE_global.h" #include "BKE_fcurve.h" #include "BKE_plugin_types.h" -#include "BKE_sequence.h" +#include "BKE_sequencer.h" #include "BKE_texture.h" #include "BKE_utildefines.h" diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c deleted file mode 100644 index 8d3b1a7955b..00000000000 --- a/source/blender/blenkernel/intern/sequence.c +++ /dev/null @@ -1,3758 +0,0 @@ -/** -* $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): - * - Blender Foundation, 2003-2009 - * - Peter Schlaile 2005/2006 - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include -#include -#include -#include - -#include "MEM_guardedalloc.h" -#include "MEM_CacheLimiterC-Api.h" - -#include "DNA_listBase.h" -#include "DNA_sequence_types.h" -#include "DNA_scene_types.h" -#include "DNA_anim_types.h" - -#include "BKE_global.h" -#include "BKE_image.h" -#include "BKE_main.h" -#include "BKE_sequence.h" -#include "BKE_fcurve.h" -#include "BKE_utildefines.h" -#include "RNA_access.h" -#include "RE_pipeline.h" - -#include "BLI_blenlib.h" -#include "BLI_util.h" - -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" - -#include "BLI_threads.h" -#include - -#include "BKE_context.h" -#include "BKE_sound.h" -#include "AUD_C-API.h" - -#ifdef WIN32 -#define snprintf _snprintf -#endif - -/* **** XXX ******** */ -static int seqrectx= 0; /* bad bad global! */ -static int seqrecty= 0; -//static void waitcursor(int val) {} -//static int blender_test_break() {return 0;} - -/* **** XXX ******** */ - - -void printf_strip(Sequence *seq) -{ - fprintf(stderr, "name: '%s', len:%d, start:%d, (startofs:%d, endofs:%d), (startstill:%d, endstill:%d), machine:%d, (startdisp:%d, enddisp:%d)\n", - seq->name, seq->len, seq->start, seq->startofs, seq->endofs, seq->startstill, seq->endstill, seq->machine, seq->startdisp, seq->enddisp); - fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0), seq_tx_get_final_right(seq, 0)); -} - -/* ********************************************************************** - alloc / free functions - ********************************************************************** */ - -static void free_tstripdata(int len, TStripElem *se) -{ - TStripElem *seo; - int a; - - seo= se; - if (!se) - return; - - for(a=0; aibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = 0; - } - if(se->ibuf_comp) { - IMB_freeImBuf(se->ibuf_comp); - se->ibuf_comp = 0; - } - } - - MEM_freeN(seo); -} - - -void new_tstripdata(Sequence *seq) -{ - if(seq->strip) { - free_tstripdata(seq->strip->len, seq->strip->tstripdata); - free_tstripdata(seq->strip->endstill, - seq->strip->tstripdata_endstill); - free_tstripdata(seq->strip->startstill, - seq->strip->tstripdata_startstill); - - seq->strip->tstripdata= 0; - seq->strip->tstripdata_endstill= 0; - seq->strip->tstripdata_startstill= 0; - - if(seq->strip->ibuf_startstill) { - IMB_freeImBuf(seq->strip->ibuf_startstill); - seq->strip->ibuf_startstill = 0; - } - - if(seq->strip->ibuf_endstill) { - IMB_freeImBuf(seq->strip->ibuf_endstill); - seq->strip->ibuf_endstill = 0; - } - - seq->strip->len= seq->len; - } -} - - -/* free */ - -static void free_proxy_seq(Sequence *seq) -{ - if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { - IMB_free_anim(seq->strip->proxy->anim); - seq->strip->proxy->anim = 0; - } -} - -void seq_free_strip(Strip *strip) -{ - strip->us--; - if(strip->us>0) return; - if(strip->us<0) { - printf("error: negative users in strip\n"); - return; - } - - if (strip->stripdata) { - MEM_freeN(strip->stripdata); - } - - if (strip->proxy) { - if (strip->proxy->anim) { - IMB_free_anim(strip->proxy->anim); - } - - MEM_freeN(strip->proxy); - } - if (strip->crop) { - MEM_freeN(strip->crop); - } - if (strip->transform) { - MEM_freeN(strip->transform); - } - if (strip->color_balance) { - MEM_freeN(strip->color_balance); - } - - free_tstripdata(strip->len, strip->tstripdata); - free_tstripdata(strip->endstill, strip->tstripdata_endstill); - free_tstripdata(strip->startstill, strip->tstripdata_startstill); - - if(strip->ibuf_startstill) { - IMB_freeImBuf(strip->ibuf_startstill); - strip->ibuf_startstill = 0; - } - - if(strip->ibuf_endstill) { - IMB_freeImBuf(strip->ibuf_endstill); - strip->ibuf_endstill = 0; - } - - MEM_freeN(strip); -} - -void seq_free_sequence(Scene *scene, Sequence *seq) -{ - Editing *ed = scene->ed; - - if(seq->strip) seq_free_strip(seq->strip); - - if(seq->anim) IMB_free_anim(seq->anim); - - if(seq->sound_handle) - sound_delete_handle(scene, seq->sound_handle); - - if (seq->type & SEQ_EFFECT) { - struct SeqEffectHandle sh = get_sequence_effect(seq); - - sh.free(seq); - } - - if (ed->act_seq==seq) - ed->act_seq= NULL; - - MEM_freeN(seq); -} - -Editing *seq_give_editing(Scene *scene, int alloc) -{ - if (scene->ed == NULL && alloc) { - Editing *ed; - - ed= scene->ed= MEM_callocN( sizeof(Editing), "addseq"); - ed->seqbasep= &ed->seqbase; - } - return scene->ed; -} - -void seq_free_editing(Scene *scene) -{ - Editing *ed = scene->ed; - MetaStack *ms; - Sequence *seq; - - if(ed==NULL) - return; - - SEQ_BEGIN(ed, seq) { - seq_free_sequence(scene, seq); - } - SEQ_END - - while((ms= ed->metastack.first)) { - BLI_remlink(&ed->metastack, ms); - MEM_freeN(ms); - } - - MEM_freeN(ed); -} - -/* ************************* itterator ************************** */ -/* *************** (replaces old WHILE_SEQ) ********************* */ -/* **************** use now SEQ_BEGIN() SEQ_END ***************** */ - -/* sequence strip iterator: - * - builds a full array, recursively into meta strips */ - -static void seq_count(ListBase *seqbase, int *tot) -{ - Sequence *seq; - - for(seq=seqbase->first; seq; seq=seq->next) { - (*tot)++; - - if(seq->seqbase.first) - seq_count(&seq->seqbase, tot); - } -} - -static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth) -{ - Sequence *seq; - - for(seq=seqbase->first; seq; seq=seq->next) { - seq->depth= depth; - - if(seq->seqbase.first) - seq_build_array(&seq->seqbase, array, depth+1); - - **array= seq; - (*array)++; - } -} - -void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_pointer) -{ - Sequence **array; - - *seqarray= NULL; - *tot= 0; - - if(ed == NULL) - return; - - if(use_pointer) - seq_count(ed->seqbasep, tot); - else - seq_count(&ed->seqbase, tot); - - if(*tot == 0) - return; - - *seqarray= array= MEM_mallocN(sizeof(Sequence *)*(*tot), "SeqArray"); - if(use_pointer) - seq_build_array(ed->seqbasep, &array, 0); - else - seq_build_array(&ed->seqbase, &array, 0); -} - -void seq_begin(Editing *ed, SeqIterator *iter, int use_pointer) -{ - memset(iter, 0, sizeof(*iter)); - seq_array(ed, &iter->array, &iter->tot, use_pointer); - - if(iter->tot) { - iter->cur= 0; - iter->seq= iter->array[iter->cur]; - iter->valid= 1; - } -} - -void seq_next(SeqIterator *iter) -{ - if(++iter->cur < iter->tot) - iter->seq= iter->array[iter->cur]; - else - iter->valid= 0; -} - -void seq_end(SeqIterator *iter) -{ - if(iter->array) - MEM_freeN(iter->array); - - iter->valid= 0; -} - -/* - ********************************************************************** - * build_seqar - ********************************************************************** - * Build a complete array of _all_ sequencies (including those - * in metastrips!) - ********************************************************************** -*/ - -static void do_seq_count(ListBase *seqbase, int *totseq) -{ - Sequence *seq; - - seq= seqbase->first; - while(seq) { - (*totseq)++; - if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq); - seq= seq->next; - } -} - -static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth) -{ - Sequence *seq; - - seq= seqbase->first; - while(seq) { - seq->depth= depth; - if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1); - **seqar= seq; - (*seqar)++; - seq= seq->next; - } -} - -void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq) -{ - Sequence **tseqar; - - *totseq= 0; - do_seq_count(seqbase, totseq); - - if(*totseq==0) { - *seqar= 0; - return; - } - *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); - tseqar= *seqar; - - do_build_seqar(seqbase, seqar, 0); - *seqar= tseqar; -} - -static void do_seq_count_cb(ListBase *seqbase, int *totseq, - int (*test_func)(Sequence * seq)) -{ - Sequence *seq; - - seq= seqbase->first; - while(seq) { - int test = test_func(seq); - if (test & BUILD_SEQAR_COUNT_CURRENT) { - (*totseq)++; - } - if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { - do_seq_count_cb(&seq->seqbase, totseq, test_func); - } - seq= seq->next; - } -} - -static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth, - int (*test_func)(Sequence * seq)) -{ - Sequence *seq; - - seq= seqbase->first; - while(seq) { - int test = test_func(seq); - seq->depth= depth; - - if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { - do_build_seqar_cb(&seq->seqbase, seqar, depth+1, - test_func); - } - if (test & BUILD_SEQAR_COUNT_CURRENT) { - **seqar= seq; - (*seqar)++; - } - seq= seq->next; - } -} - -void build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int *totseq, - int (*test_func)(Sequence * seq)) -{ - Sequence **tseqar; - - *totseq= 0; - do_seq_count_cb(seqbase, totseq, test_func); - - if(*totseq==0) { - *seqar= 0; - return; - } - *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); - tseqar= *seqar; - - do_build_seqar_cb(seqbase, seqar, 0, test_func); - *seqar= tseqar; -} - - -void calc_sequence_disp(Sequence *seq) -{ - if(seq->startofs && seq->startstill) seq->startstill= 0; - if(seq->endofs && seq->endstill) seq->endstill= 0; - - seq->startdisp= seq->start + seq->startofs - seq->startstill; - seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill; - - seq->handsize= 10.0; /* 10 frames */ - if( seq->enddisp-seq->startdisp < 10 ) { - seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp)); - } - else if(seq->enddisp-seq->startdisp > 250) { - seq->handsize= (float)((seq->enddisp-seq->startdisp)/25); - } - - seq_update_sound(seq); -} - -void calc_sequence(Sequence *seq) -{ - Sequence *seqm; - int min, max; - - /* check all metas recursively */ - seqm= seq->seqbase.first; - while(seqm) { - if(seqm->seqbase.first) calc_sequence(seqm); - seqm= seqm->next; - } - - /* effects and meta: automatic start and end */ - - if(seq->type & SEQ_EFFECT) { - /* pointers */ - if(seq->seq2==0) seq->seq2= seq->seq1; - if(seq->seq3==0) seq->seq3= seq->seq1; - - /* effecten go from seq1 -> seq2: test */ - - /* we take the largest start and smallest end */ - - // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp); - // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp); - - if (seq->seq1) { - seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp); - seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp); - seq->len= seq->enddisp - seq->startdisp; - } else { - calc_sequence_disp(seq); - } - - if(seq->strip && seq->len!=seq->strip->len) { - new_tstripdata(seq); - } - - } - else { - if(seq->type==SEQ_META) { - seqm= seq->seqbase.first; - if(seqm) { - min= 1000000; - max= -1000000; - while(seqm) { - if(seqm->startdisp < min) min= seqm->startdisp; - if(seqm->enddisp > max) max= seqm->enddisp; - seqm= seqm->next; - } - seq->start= min + seq->anim_startofs; - seq->len = max-min; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - - if(seq->strip && seq->len!=seq->strip->len) { - new_tstripdata(seq); - } - } - } - calc_sequence_disp(seq); - } -} - -void reload_sequence_new_file(Scene *scene, Sequence * seq) -{ - char str[FILE_MAXDIR+FILE_MAXFILE]; - - if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE || - seq->type == SEQ_SOUND || - seq->type == SEQ_SCENE || seq->type == SEQ_META)) { - return; - } - - new_tstripdata(seq); - - if (seq->type != SEQ_SCENE && seq->type != SEQ_META && - seq->type != SEQ_IMAGE) { - BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name); - BLI_convertstringcode(str, G.sce); - BLI_convertstringframe(str, scene->r.cfra); - - } - - if (seq->type == SEQ_IMAGE) { - /* Hack? */ - int olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem); - seq->len = olen; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } else if (seq->type == SEQ_MOVIE) { - if(seq->anim) IMB_free_anim(seq->anim); - seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0)); - - if (!seq->anim) { - return; - } - - seq->len = IMB_anim_get_duration(seq->anim); - - seq->anim_preseek = IMB_anim_get_preseek(seq->anim); - - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } else if (seq->type == SEQ_SOUND) { - seq->len = AUD_getInfo(seq->sound->handle).length * FPS; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } else if (seq->type == SEQ_SCENE) { - Scene * sce = G.main->scene.first; - int nr = 1; - - while(sce) { - if(nr == seq->scenenr) { - break; - } - nr++; - sce= sce->id.next; - } - - if (sce) { - seq->scene = sce; - } else { - sce = seq->scene; - } - - BLI_strncpy(seq->name+2, sce->id.name + 2, SEQ_NAME_MAXSTR-2); - seqUniqueName(scene->ed->seqbasep, seq); - - seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } - - free_proxy_seq(seq); - - calc_sequence(seq); -} - -void sort_seq(Scene *scene) -{ - /* all strips together per kind, and in order of y location ("machine") */ - ListBase seqbase, effbase; - Editing *ed= seq_give_editing(scene, FALSE); - Sequence *seq, *seqt; - - - if(ed==NULL) return; - - seqbase.first= seqbase.last= 0; - effbase.first= effbase.last= 0; - - while( (seq= ed->seqbasep->first) ) { - BLI_remlink(ed->seqbasep, seq); - - if(seq->type & SEQ_EFFECT) { - seqt= effbase.first; - while(seqt) { - if(seqt->machine>=seq->machine) { - BLI_insertlinkbefore(&effbase, seqt, seq); - break; - } - seqt= seqt->next; - } - if(seqt==0) BLI_addtail(&effbase, seq); - } - else { - seqt= seqbase.first; - while(seqt) { - if(seqt->machine>=seq->machine) { - BLI_insertlinkbefore(&seqbase, seqt, seq); - break; - } - seqt= seqt->next; - } - if(seqt==0) BLI_addtail(&seqbase, seq); - } - } - - addlisttolist(&seqbase, &effbase); - *(ed->seqbasep)= seqbase; -} - - -void clear_scene_in_allseqs(Scene *sce) -{ - Scene *sce1; - Editing *ed; - Sequence *seq; - - /* when a scene is deleted: test all seqs */ - - sce1= G.main->scene.first; - while(sce1) { - if(sce1!=sce && sce1->ed) { - ed= sce1->ed; - - SEQ_BEGIN(ed, seq) { - - if(seq->scene==sce) seq->scene= 0; - - } - SEQ_END - } - - sce1= sce1->id.next; - } -} - -static char *give_seqname_by_type(int type) -{ - switch(type) { - case SEQ_META: return "Meta"; - case SEQ_IMAGE: return "Image"; - case SEQ_SCENE: return "Scene"; - case SEQ_MOVIE: return "Movie"; - case SEQ_SOUND: return "Audio"; - case SEQ_CROSS: return "Cross"; - case SEQ_GAMCROSS: return "Gamma Cross"; - case SEQ_ADD: return "Add"; - case SEQ_SUB: return "Sub"; - case SEQ_MUL: return "Mul"; - case SEQ_ALPHAOVER: return "Alpha Over"; - case SEQ_ALPHAUNDER: return "Alpha Under"; - case SEQ_OVERDROP: return "Over Drop"; - case SEQ_WIPE: return "Wipe"; - case SEQ_GLOW: return "Glow"; - case SEQ_TRANSFORM: return "Transform"; - case SEQ_COLOR: return "Color"; - case SEQ_SPEED: return "Speed"; - default: - return 0; - } -} - -char *give_seqname(Sequence *seq) -{ - char * name = give_seqname_by_type(seq->type); - - if (!name) { - if(seq->typestrip->dir; - } else if(seq->type==SEQ_PLUGIN) { - if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) && - seq->plugin && seq->plugin->doit) { - return seq->plugin->pname; - } else { - return "Plugin"; - } - } else { - return "Effect"; - } - } - return name; -} - -/* ***************** DO THE SEQUENCE ***************** */ - -static void make_black_ibuf(ImBuf *ibuf) -{ - unsigned int *rect; - float *rect_float; - int tot; - - if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return; - - tot= ibuf->x*ibuf->y; - - rect= ibuf->rect; - rect_float = ibuf->rect_float; - - if (rect) { - memset(rect, 0, tot * sizeof(char) * 4); - } - - if (rect_float) { - memset(rect_float, 0, tot * sizeof(float) * 4); - } -} - -static void multibuf(ImBuf *ibuf, float fmul) -{ - char *rt; - float *rt_float; - - int a, mul, icol; - - mul= (int)(256.0*fmul); - rt= (char *)ibuf->rect; - rt_float = ibuf->rect_float; - - if (rt) { - a= ibuf->x*ibuf->y; - while(a--) { - - icol= (mul*rt[0])>>8; - if(icol>254) rt[0]= 255; else rt[0]= icol; - icol= (mul*rt[1])>>8; - if(icol>254) rt[1]= 255; else rt[1]= icol; - icol= (mul*rt[2])>>8; - if(icol>254) rt[2]= 255; else rt[2]= icol; - icol= (mul*rt[3])>>8; - if(icol>254) rt[3]= 255; else rt[3]= icol; - - rt+= 4; - } - } - if (rt_float) { - a= ibuf->x*ibuf->y; - while(a--) { - rt_float[0] *= fmul; - rt_float[1] *= fmul; - rt_float[2] *= fmul; - rt_float[3] *= fmul; - - rt_float += 4; - } - } -} - -static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se) -{ - TStripElem *se1, *se2, *se3; - float fac, facf; - int x, y; - int early_out; - struct SeqEffectHandle sh = get_sequence_effect(seq); - FCurve *fcu= NULL; - - if (!sh.execute) { /* effect not supported in this version... */ - make_black_ibuf(se->ibuf); - return; - } - - if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { - sh.get_default_fac(seq, cfra, &fac, &facf); - if( scene->r.mode & R_FIELDS ); else facf= fac; - } else { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, - "effect_fader", 0); - if (fcu) { - fac = facf = evaluate_fcurve(fcu, cfra); - if( scene->r.mode & R_FIELDS ) { - facf = evaluate_fcurve(fcu, cfra + 0.5); - } - } else { - fac = facf = seq->effect_fader; - } - } - - early_out = sh.early_out(seq, fac, facf); - - if (early_out == -1) { /* no input needed */ - sh.execute(scene, seq, cfra, fac, facf, - se->ibuf->x, se->ibuf->y, - 0, 0, 0, se->ibuf); - return; - } - - switch (early_out) { - case 0: - if (se->se1==0 || se->se2==0 || se->se3==0) { - make_black_ibuf(se->ibuf); - return; - } - - se1= se->se1; - se2= se->se2; - se3= se->se3; - - if ( (se1==0 || se2==0 || se3==0) - || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) { - make_black_ibuf(se->ibuf); - return; - } - - break; - case 1: - if (se->se1 == 0) { - make_black_ibuf(se->ibuf); - return; - } - - se1= se->se1; - - if (se1 == 0 || se1->ibuf == 0) { - make_black_ibuf(se->ibuf); - return; - } - - if (se->ibuf != se1->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = se1->ibuf; - IMB_refImBuf(se->ibuf); - } - return; - case 2: - if (se->se2 == 0) { - make_black_ibuf(se->ibuf); - return; - } - - se2= se->se2; - - if (se2 == 0 || se2->ibuf == 0) { - make_black_ibuf(se->ibuf); - return; - } - if (se->ibuf != se2->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = se2->ibuf; - IMB_refImBuf(se->ibuf); - } - return; - default: - make_black_ibuf(se->ibuf); - return; - } - - x= se2->ibuf->x; - y= se2->ibuf->y; - - if (!se1->ibuf->rect_float && se->ibuf->rect_float) { - IMB_float_from_rect(se1->ibuf); - } - if (!se2->ibuf->rect_float && se->ibuf->rect_float) { - IMB_float_from_rect(se2->ibuf); - } - if (!se3->ibuf->rect_float && se->ibuf->rect_float) { - IMB_float_from_rect(se3->ibuf); - } - - if (!se1->ibuf->rect && !se->ibuf->rect_float) { - IMB_rect_from_float(se1->ibuf); - } - if (!se2->ibuf->rect && !se->ibuf->rect_float) { - IMB_rect_from_float(se2->ibuf); - } - if (!se3->ibuf->rect && !se->ibuf->rect_float) { - IMB_rect_from_float(se3->ibuf); - } - - sh.execute(scene, seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf, - se->ibuf); -} - -static int give_stripelem_index(Sequence *seq, int cfra) -{ - int nr; - - if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1; - if(seq->len == 0) return -1; - if(seq->flag&SEQ_REVERSE_FRAMES) { - /*reverse frame in this sequence */ - if(cfra <= seq->start) nr= seq->len-1; - else if(cfra >= seq->start+seq->len-1) nr= 0; - else nr= (seq->start + seq->len) - cfra; - } else { - if(cfra <= seq->start) nr= 0; - else if(cfra >= seq->start+seq->len-1) nr= seq->len-1; - else nr= cfra-seq->start; - } - if (seq->strobe < 1.0) seq->strobe = 1.0; - if (seq->strobe > 1.0) { - nr -= (int)fmod((double)nr, (double)seq->strobe); - } - - return nr; -} - -static TStripElem* alloc_tstripdata(int len, const char * name) -{ - int i; - TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name); - for (i = 0; i < len; i++) { - se[i].ok = STRIPELEM_OK; - } - return se; -} - -static TStripElem *give_tstripelem(Sequence *seq, int cfra) -{ - TStripElem *se; - int nr; - - se = seq->strip->tstripdata; - if (se == 0 && seq->len > 0) { - se = seq->strip->tstripdata = alloc_tstripdata(seq->len, - "tstripelems"); - } - nr = give_stripelem_index(seq, cfra); - - if (nr == -1) return 0; - if (se == 0) return 0; - - se += nr; - - /* if there are IPOs with blend modes active, one has to watch out - for startstill + endstill area: we can't use the same tstripelem - here for all ibufs, since then, blending with IPOs won't work! - - Rather common case, if you use a single image and try to fade - it in and out... or want to use your strip as a watermark in - alpha over mode... - */ - if (seq->blend_mode != SEQ_BLEND_REPLACE || - (/*seq->ipo && seq->ipo->curve.first &&*/ - (!(seq->type & SEQ_EFFECT) || !seq->seq1))) { - Strip * s = seq->strip; - if (cfra < seq->start) { - se = s->tstripdata_startstill; - if (seq->startstill > s->startstill) { - free_tstripdata(s->startstill, - s->tstripdata_startstill); - se = 0; - } - - if (se == 0) { - s->startstill = seq->startstill; - se = seq->strip->tstripdata_startstill - = alloc_tstripdata( - s->startstill, - "tstripelems_startstill"); - } - se += seq->start - cfra - 1; - - } else if (cfra > seq->start + seq->len-1) { - se = s->tstripdata_endstill; - if (seq->endstill > s->endstill) { - free_tstripdata(s->endstill, - s->tstripdata_endstill); - se = 0; - } - - if (se == 0) { - s->endstill = seq->endstill; - se = seq->strip->tstripdata_endstill - = alloc_tstripdata( - s->endstill, - "tstripelems_endstill"); - } - se += cfra - (seq->start + seq->len-1) - 1; - } - } - - - se->nr= nr; - - return se; -} - -StripElem *give_stripelem(Sequence *seq, int cfra) -{ - StripElem *se; - int nr; - - se = seq->strip->stripdata; - nr = give_stripelem_index(seq, cfra); - - if (nr == -1) return 0; - if (se == 0) return 0; - - se += nr + seq->anim_startofs; - - return se; -} - -static int evaluate_seq_frame_gen(Sequence ** seq_arr, ListBase *seqbase, int cfra) -{ - Sequence *seq; - int totseq=0; - - memset(seq_arr, 0, sizeof(Sequence*) * (MAXSEQ+1)); - - seq= seqbase->first; - while(seq) { - if(seq->startdisp <=cfra && seq->enddisp > cfra) { - seq_arr[seq->machine]= seq; - totseq++; - } - seq= seq->next; - } - - return totseq; -} - -int evaluate_seq_frame(Scene *scene, int cfra) -{ - Editing *ed= seq_give_editing(scene, FALSE); - Sequence *seq_arr[MAXSEQ+1]; - - if(ed==NULL) return 0; - return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra); -} - -static int video_seq_is_rendered(Sequence * seq) -{ - return (seq - && !(seq->flag & SEQ_MUTE) - && seq->type != SEQ_SOUND); -} - -static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out) -{ - Sequence *seq_arr[MAXSEQ+1]; - int b = chanshown; - int cnt = 0; - - if (b > MAXSEQ) { - return 0; - } - - if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) { - if (b > 0) { - if (seq_arr[b] == 0) { - return 0; - } - } else { - for (b = MAXSEQ; b > 0; b--) { - if (video_seq_is_rendered(seq_arr[b])) { - break; - } - } - } - } - - chanshown = b; - - for (;b > 0; b--) { - if (video_seq_is_rendered(seq_arr[b])) { - if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) { - break; - } - } - } - - for (;b <= chanshown; b++) { - if (video_seq_is_rendered(seq_arr[b])) { - seq_arr_out[cnt++] = seq_arr[b]; - } - } - - return cnt; -} - - -/* ********************************************************************** - proxy management - ********************************************************************** */ - -#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE) - -static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name, int render_size) -{ - int frameno; - char dir[FILE_MAXDIR]; - - if (!seq->strip->proxy) { - return FALSE; - } - - if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { - strcpy(dir, seq->strip->proxy->dir); - } else { - if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) { - snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", - seq->strip->dir); - } else { - return FALSE; - } - } - - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { - BLI_join_dirfile(name, dir, seq->strip->proxy->file); - BLI_convertstringcode(name, G.sce); - BLI_convertstringframe(name, cfra); - - return TRUE; - } - - /* generate a separate proxy directory for each preview size */ - - if (seq->type == SEQ_IMAGE) { - StripElem * se = give_stripelem(seq, cfra); - snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", - dir, render_size, se->name); - frameno = 1; - } else if (seq->type == SEQ_MOVIE) { - TStripElem * tse = give_tstripelem(seq, cfra); - - frameno = tse->nr + seq->anim_startofs; - - snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir, - seq->strip->stripdata->name, - render_size); - } else { - TStripElem * tse = give_tstripelem(seq, cfra); - - frameno = tse->nr + seq->anim_startofs; - - snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, - render_size); - } - - BLI_convertstringcode(name, G.sce); - BLI_convertstringframe(name, frameno); - - - strcat(name, ".jpg"); - - return TRUE; -} - -static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, int render_size) -{ - char name[PROXY_MAXFILE]; - - if (!(seq->flag & SEQ_USE_PROXY)) { - return 0; - } - - /* rendering at 100% ? No real sense in proxy-ing, right? */ - if (render_size == 100) { - return 0; - } - - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { - TStripElem * tse = give_tstripelem(seq, cfra); - int frameno = tse->nr + seq->anim_startofs; - if (!seq->strip->proxy->anim) { - if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { - return 0; - } - - seq->strip->proxy->anim = openanim(name, IB_rect); - } - if (!seq->strip->proxy->anim) { - return 0; - } - - return IMB_anim_absolute(seq->strip->proxy->anim, frameno); - } - - if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { - return 0; - } - - if (BLI_exists(name)) { - return IMB_loadiffname(name, IB_rect); - } else { - return 0; - } -} - -#if 0 -static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, - int build_proxy_run, int render_size); - -static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size) -{ - char name[PROXY_MAXFILE]; - int quality; - TStripElem * se; - int ok; - int rectx, recty; - struct ImBuf * ibuf; - - if (!(seq->flag & SEQ_USE_PROXY)) { - return; - } - - /* rendering at 100% ? No real sense in proxy-ing, right? */ - if (render_size == 100) { - return; - } - - /* that's why it is called custom... */ - if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { - return; - } - - if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { - return; - } - - se = give_tstripelem(seq, cfra); - if (!se) { - return; - } - - if(se->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = 0; - } - - do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size); - - if (!se->ibuf) { - return; - } - - rectx= (render_size*scene->r.xsch)/100; - recty= (render_size*scene->r.ysch)/100; - - ibuf = se->ibuf; - - if (ibuf->x != rectx || ibuf->y != recty) { - IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty); - } - - /* quality is fixed, otherwise one has to generate separate - directories for every quality... - - depth = 32 is intentionally left in, otherwise ALPHA channels - won't work... */ - quality = seq->strip->proxy->quality; - ibuf->ftype= JPG | quality; - - BLI_make_existing_file(name); - - ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); - if (ok == 0) { - perror(name); - } - - IMB_freeImBuf(ibuf); - se->ibuf = 0; -} - -static void seq_proxy_rebuild(Scene *scene, Sequence * seq) -{ - int cfra; - float rsize = seq->strip->proxy->size; - - waitcursor(1); - - G.afbreek = 0; - - /* flag management tries to account for strobe and - other "non-linearities", that might come in the future... - better way would be to "touch" the files, so that _really_ - no one is rebuild twice. - */ - - for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) { - TStripElem * tse = give_tstripelem(seq, cfra); - - tse->flag &= ~STRIPELEM_PREVIEW_DONE; - } - - - - /* a _lot_ faster for movie files, if we read frames in - sequential order */ - if (seq->flag & SEQ_REVERSE_FRAMES) { - for (cfra = seq->enddisp-seq->endstill-1; - cfra >= seq->startdisp + seq->startstill; cfra--) { - TStripElem * tse = give_tstripelem(seq, cfra); - - if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { -//XXX set_timecursor(cfra); - seq_proxy_build_frame(scene, seq, cfra, rsize); - tse->flag |= STRIPELEM_PREVIEW_DONE; - } - if (blender_test_break()) { - break; - } - } - } else { - for (cfra = seq->startdisp + seq->startstill; - cfra < seq->enddisp - seq->endstill; cfra++) { - TStripElem * tse = give_tstripelem(seq, cfra); - - if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { -//XXX set_timecursor(cfra); - seq_proxy_build_frame(scene, seq, cfra, rsize); - tse->flag |= STRIPELEM_PREVIEW_DONE; - } - if (blender_test_break()) { - break; - } - } - } - waitcursor(0); -} -#endif - - -/* ********************************************************************** - color balance - ********************************************************************** */ - -static StripColorBalance calc_cb(StripColorBalance * cb_) -{ - StripColorBalance cb = *cb_; - int c; - - if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) { - for (c = 0; c < 3; c++) { - cb.lift[c] = 1.0 - cb.lift[c]; - } - } else { - for (c = 0; c < 3; c++) { - cb.lift[c] = -(1.0 - cb.lift[c]); - } - } - if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) { - for (c = 0; c < 3; c++) { - if (cb.gain[c] != 0.0) { - cb.gain[c] = 1.0/cb.gain[c]; - } else { - cb.gain[c] = 1000000; /* should be enough :) */ - } - } - } - - if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) { - for (c = 0; c < 3; c++) { - if (cb.gamma[c] != 0.0) { - cb.gamma[c] = 1.0/cb.gamma[c]; - } else { - cb.gamma[c] = 1000000; /* should be enough :) */ - } - } - } - - return cb; -} - -static void make_cb_table_byte(float lift, float gain, float gamma, - unsigned char * table, float mul) -{ - int y; - - for (y = 0; y < 256; y++) { - float v = 1.0 * y / 255; - v *= gain; - v += lift; - v = pow(v, gamma); - v *= mul; - if ( v > 1.0) { - v = 1.0; - } else if (v < 0.0) { - v = 0.0; - } - table[y] = v * 255; - } - -} - -static void make_cb_table_float(float lift, float gain, float gamma, - float * table, float mul) -{ - int y; - - for (y = 0; y < 256; y++) { - float v = (float) y * 1.0 / 255.0; - v *= gain; - v += lift; - v = pow(v, gamma); - v *= mul; - table[y] = v; - } -} - -static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul) -{ - unsigned char cb_tab[3][256]; - int c; - unsigned char * p = (unsigned char*) se->ibuf->rect; - unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; - - StripColorBalance cb = calc_cb(seq->strip->color_balance); - - for (c = 0; c < 3; c++) { - make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], - cb_tab[c], mul); - } - - while (p < e) { - p[0] = cb_tab[0][p[0]]; - p[1] = cb_tab[1][p[1]]; - p[2] = cb_tab[2][p[2]]; - - p += 4; - } -} - -static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul) -{ - float cb_tab[4][256]; - int c,i; - unsigned char * p = (unsigned char*) se->ibuf->rect; - unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; - float * o; - StripColorBalance cb; - - imb_addrectfloatImBuf(se->ibuf); - - o = se->ibuf->rect_float; - - cb = calc_cb(seq->strip->color_balance); - - for (c = 0; c < 3; c++) { - make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], - cb_tab[c], mul); - } - - for (i = 0; i < 256; i++) { - cb_tab[3][i] = ((float)i)*(1.0f/255.0f); - } - - while (p < e) { - o[0] = cb_tab[0][p[0]]; - o[1] = cb_tab[1][p[1]]; - o[2] = cb_tab[2][p[2]]; - o[3] = cb_tab[3][p[3]]; - - p += 4; o += 4; - } -} - -static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul) -{ - float * p = se->ibuf->rect_float; - float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y; - StripColorBalance cb = calc_cb(seq->strip->color_balance); - - while (p < e) { - int c; - for (c = 0; c < 3; c++) { - p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], - cb.gamma[c]) * mul; - } - p += 4; - } -} - -static void color_balance(Sequence * seq, TStripElem* se, float mul) -{ - if (se->ibuf->rect_float) { - color_balance_float_float(seq, se, mul); - } else if(seq->flag & SEQ_MAKE_FLOAT) { - color_balance_byte_float(seq, se, mul); - } else { - color_balance_byte_byte(seq, se, mul); - } -} - -/* - input preprocessing for SEQ_IMAGE, SEQ_MOVIE and SEQ_SCENE - - Do all the things you can't really do afterwards using sequence effects - (read: before rescaling to render resolution has been done) - - Order is important! - - - Deinterlace - - Crop and transform in image source coordinate space - - Flip X + Flip Y (could be done afterwards, backward compatibility) - - Promote image to float data (affects pipeline operations afterwards) - - Color balance (is most efficient in the byte -> float - (future: half -> float should also work fine!) - case, if done on load, since we can use lookup tables) - - Premultiply - -*/ - -static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra) -{ - float mul; - - if ((seq->flag & SEQ_FILTERY) || - (seq->flag & SEQ_USE_CROP) || - (seq->flag & SEQ_USE_TRANSFORM) || - (seq->flag & SEQ_FLIPX) || - (seq->flag & SEQ_FLIPY) || - (seq->flag & SEQ_USE_COLOR_BALANCE) || - (seq->flag & SEQ_MAKE_PREMUL) || - (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) { - return TRUE; - } - - mul = seq->mul; - - if(seq->blend_mode == SEQ_BLEND_REPLACE && - !(seq->type & SEQ_EFFECT)) { - mul *= seq->blend_opacity / 100.0; - } - - if (mul != 1.0) { - return TRUE; - } - - return FALSE; -} - -static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra) -{ - float mul; - - seq->strip->orx= se->ibuf->x; - seq->strip->ory= se->ibuf->y; - - if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) { - IMB_filtery(se->ibuf); - } - - if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) { - StripCrop c; - StripTransform t; - int sx,sy,dx,dy; - - memset(&c, 0, sizeof(StripCrop)); - memset(&t, 0, sizeof(StripTransform)); - - if(seq->flag & SEQ_USE_CROP && seq->strip->crop) { - c = *seq->strip->crop; - } - if(seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) { - t = *seq->strip->transform; - } - - sx = se->ibuf->x - c.left - c.right; - sy = se->ibuf->y - c.top - c.bottom; - dx = sx; - dy = sy; - - if (seq->flag & SEQ_USE_TRANSFORM) { - dx = scene->r.xsch; - dy = scene->r.ysch; - } - - if (c.top + c.bottom >= se->ibuf->y || - c.left + c.right >= se->ibuf->x || - t.xofs >= dx || t.yofs >= dy) { - make_black_ibuf(se->ibuf); - } else { - ImBuf * i; - - if (se->ibuf->rect_float) { - i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0); - } else { - i = IMB_allocImBuf(dx, dy,32, IB_rect, 0); - } - - IMB_rectcpy(i, se->ibuf, - t.xofs, t.yofs, - c.left, c.bottom, - sx, sy); - - IMB_freeImBuf(se->ibuf); - - se->ibuf = i; - } - } - - if(seq->flag & SEQ_FLIPX) { - IMB_flipx(se->ibuf); - } - if(seq->flag & SEQ_FLIPY) { - IMB_flipy(se->ibuf); - } - - if(seq->mul == 0.0) { - seq->mul = 1.0; - } - - mul = seq->mul; - - if(seq->blend_mode == SEQ_BLEND_REPLACE) { - mul *= seq->blend_opacity / 100.0; - } - - if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) { - color_balance(seq, se, mul); - mul = 1.0; - } - - if(seq->flag & SEQ_MAKE_FLOAT) { - if (!se->ibuf->rect_float) { - IMB_float_from_rect(se->ibuf); - } - if (se->ibuf->rect) { - imb_freerectImBuf(se->ibuf); - } - } - - if(mul != 1.0) { - multibuf(se->ibuf, mul); - } - - if(seq->flag & SEQ_MAKE_PREMUL) { - if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) { - converttopremul(se->ibuf); - } - } - - - if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) { - if(scene->r.mode & R_OSA) { - IMB_scaleImBuf(se->ibuf, - (short)seqrectx, (short)seqrecty); - } else { - IMB_scalefastImBuf(se->ibuf, - (short)seqrectx, (short)seqrecty); - } - } -} - -/* test if image too small or discarded from cache: reload */ - -static void test_and_auto_discard_ibuf(TStripElem * se) -{ - if (se->ibuf) { - if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty - || !(se->ibuf->rect || se->ibuf->rect_float)) { - IMB_freeImBuf(se->ibuf); - - se->ibuf= 0; - se->ok= STRIPELEM_OK; - } - } - if (se->ibuf_comp) { - if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty - || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) { - IMB_freeImBuf(se->ibuf_comp); - - se->ibuf_comp = 0; - } - } -} - -static void test_and_auto_discard_ibuf_stills(Strip * strip) -{ - if (strip->ibuf_startstill) { - if (!strip->ibuf_startstill->rect && - !strip->ibuf_startstill->rect_float) { - IMB_freeImBuf(strip->ibuf_startstill); - strip->ibuf_startstill = 0; - } - } - if (strip->ibuf_endstill) { - if (!strip->ibuf_endstill->rect && - !strip->ibuf_endstill->rect_float) { - IMB_freeImBuf(strip->ibuf_endstill); - strip->ibuf_endstill = 0; - } - } -} - -static void copy_from_ibuf_still(Sequence * seq, TStripElem * se) -{ - if (!se->ibuf) { - if (se->nr == 0 && seq->strip->ibuf_startstill) { - IMB_cache_limiter_touch(seq->strip->ibuf_startstill); - - se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill); - } - if (se->nr == seq->len - 1 - && (seq->len != 1) - && seq->strip->ibuf_endstill) { - IMB_cache_limiter_touch(seq->strip->ibuf_endstill); - - se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill); - } - } -} - -static void copy_to_ibuf_still(Sequence * seq, TStripElem * se) -{ - if (se->ibuf) { - if (se->nr == 0) { - seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf); - - IMB_cache_limiter_insert(seq->strip->ibuf_startstill); - IMB_cache_limiter_touch(seq->strip->ibuf_startstill); - } - if (se->nr == seq->len - 1 && seq->len != 1) { - seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf); - - IMB_cache_limiter_insert(seq->strip->ibuf_endstill); - IMB_cache_limiter_touch(seq->strip->ibuf_endstill); - } - } -} - -static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown) -{ - Sequence* seq_arr[MAXSEQ+1]; - int i; - TStripElem* se = 0; - - evaluate_seq_frame_gen(seq_arr, seqbasep, cfra); - - for (i = 0; i < MAXSEQ; i++) { - if (!video_seq_is_rendered(seq_arr[i])) { - continue; - } - se = give_tstripelem(seq_arr[i], cfra); - if (se) { - if (se->ibuf) { - IMB_freeImBuf(se->ibuf); - - se->ibuf= 0; - se->ok= STRIPELEM_OK; - } - - if (se->ibuf_comp) { - IMB_freeImBuf(se->ibuf_comp); - - se->ibuf_comp = 0; - } - } - } - -} - -static void check_limiter_refcount(const char * func, TStripElem *se) -{ - if (se && se->ibuf) { - int refcount = IMB_cache_limiter_get_refcount(se->ibuf); - if (refcount != 1) { - /* can happen on complex pipelines */ - if (refcount > 1 && (G.f & G_DEBUG) == 0) { - return; - } - - fprintf(stderr, - "sequencer: (ibuf) %s: " - "suspicious memcache " - "limiter refcount: %d\n", func, refcount); - } - } -} - -static void check_limiter_refcount_comp(const char * func, TStripElem *se) -{ - if (se && se->ibuf_comp) { - int refcount = IMB_cache_limiter_get_refcount(se->ibuf_comp); - if (refcount != 1) { - /* can happen on complex pipelines */ - if (refcount > 1 && (G.f & G_DEBUG) == 0) { - return; - } - fprintf(stderr, - "sequencer: (ibuf comp) %s: " - "suspicious memcache " - "limiter refcount: %d\n", func, refcount); - } - } -} - -static TStripElem* do_build_seq_array_recursively(Scene *scene, - ListBase *seqbasep, int cfra, int chanshown, int render_size); - -static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, - int build_proxy_run, int render_size) -{ - char name[FILE_MAXDIR+FILE_MAXFILE]; - int use_limiter = TRUE; - - test_and_auto_discard_ibuf(se); - test_and_auto_discard_ibuf_stills(seq->strip); - - if(seq->type == SEQ_META) { - TStripElem * meta_se = 0; - int use_preprocess = FALSE; - use_limiter = FALSE; - - if (!build_proxy_run && se->ibuf == 0) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - if (se->ibuf) { - use_limiter = TRUE; - use_preprocess = TRUE; - } - } - - if(!se->ibuf && seq->seqbase.first) { - meta_se = do_build_seq_array_recursively(scene, - &seq->seqbase, seq->start + se->nr, 0, - render_size); - - check_limiter_refcount("do_build_seq_ibuf: for META", meta_se); - } - - se->ok = STRIPELEM_OK; - - if(!se->ibuf && meta_se) { - se->ibuf = meta_se->ibuf_comp; - if(se->ibuf && - (!input_have_to_preprocess(scene, seq, se, cfra) || - build_proxy_run)) { - IMB_refImBuf(se->ibuf); - if (build_proxy_run) { - IMB_cache_limiter_unref(se->ibuf); - } - } else if (se->ibuf) { - struct ImBuf * i = IMB_dupImBuf(se->ibuf); - - IMB_cache_limiter_unref(se->ibuf); - - se->ibuf = i; - - use_limiter = TRUE; - use_preprocess = TRUE; - } - } else if (se->ibuf) { - use_limiter = TRUE; - } - if (meta_se) { - free_metastrip_imbufs( - &seq->seqbase, seq->start + se->nr, 0); - } - - if (use_preprocess) { - input_preprocess(scene, seq, se, cfra); - } - } else if(seq->type & SEQ_EFFECT) { - int use_preprocess = FALSE; - /* should the effect be recalculated? */ - - if (!build_proxy_run && se->ibuf == 0) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - if (se->ibuf) { - use_preprocess = TRUE; - } - } - - if(se->ibuf == 0) { - /* if any inputs are rectfloat, output is float too */ - if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) || - (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float) || - (se->se3 && se->se3->ibuf && se->se3->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - - do_effect(scene, cfra, seq, se); - if (input_have_to_preprocess(scene, seq, se, cfra) && - !build_proxy_run) { - if ((se->se1 && (se->ibuf == se->se1->ibuf)) || - (se->se2 && (se->ibuf == se->se2->ibuf))) { - struct ImBuf * i - = IMB_dupImBuf(se->ibuf); - - IMB_freeImBuf(se->ibuf); - - se->ibuf = i; - } - use_preprocess = TRUE; - } - } - if (use_preprocess) { - input_preprocess(scene, seq, se, cfra); - } - } else if(seq->type == SEQ_IMAGE) { - if(se->ok == STRIPELEM_OK && se->ibuf == 0) { - StripElem * s_elem = give_stripelem(seq, cfra); - BLI_join_dirfile(name, seq->strip->dir, s_elem->name); - BLI_convertstringcode(name, G.sce); - BLI_convertstringframe(name, scene->r.cfra); - if (!build_proxy_run) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } - copy_from_ibuf_still(seq, se); - - if (!se->ibuf) { - se->ibuf= IMB_loadiffname( - name, IB_rect); - /* we don't need both (speed reasons)! */ - if (se->ibuf && - se->ibuf->rect_float && se->ibuf->rect) { - imb_freerectImBuf(se->ibuf); - } - - copy_to_ibuf_still(seq, se); - } - - if(se->ibuf == 0) { - se->ok = STRIPELEM_FAILED; - } else if (!build_proxy_run) { - input_preprocess(scene, seq, se, cfra); - } - } - } else if(seq->type == SEQ_MOVIE) { - if(se->ok == STRIPELEM_OK && se->ibuf==0) { - if(!build_proxy_run) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } - copy_from_ibuf_still(seq, se); - - if (se->ibuf == 0) { - if(seq->anim==0) { - BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name); - BLI_convertstringcode(name, G.sce); - BLI_convertstringframe(name, scene->r.cfra); - - seq->anim = openanim( - name, IB_rect | - ((seq->flag & SEQ_FILTERY) - ? IB_animdeinterlace : 0)); - } - if(seq->anim) { - IMB_anim_set_preseek(seq->anim, seq->anim_preseek); - se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs); - /* we don't need both (speed reasons)! */ - if (se->ibuf - && se->ibuf->rect_float - && se->ibuf->rect) { - imb_freerectImBuf(se->ibuf); - } - - } - copy_to_ibuf_still(seq, se); - } - - if(se->ibuf == 0) { - se->ok = STRIPELEM_FAILED; - } else if (!build_proxy_run) { - input_preprocess(scene, seq, se, cfra); - } - } - } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions - Scene *sce= seq->scene;// *oldsce= scene; - Render *re; - RenderResult rres; - char scenename[64]; - int have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first; - int sce_valid =sce && (sce->camera || have_seq); - - if (se->ibuf == NULL && sce_valid && !build_proxy_run) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - if (se->ibuf) { - input_preprocess(scene, seq, se, cfra); - } - } - - if (se->ibuf == NULL && sce_valid) { - copy_from_ibuf_still(seq, se); - if (se->ibuf) { - input_preprocess(scene, seq, se, cfra); - } - } - - if (!sce_valid) { - se->ok = STRIPELEM_FAILED; - } else if (se->ibuf==NULL && sce_valid) { - int oldcfra; - /* Hack! This function can be called from do_render_seq(), in that case - the seq->scene can already have a Render initialized with same name, - so we have to use a default name. (compositor uses scene name to - find render). - However, when called from within the UI (image preview in sequencer) - we do want to use scene Render, that way the render result is defined - for display in render/imagewindow - - Hmm, don't see, why we can't do that all the time, - and since G.rendering is uhm, gone... (Peter) - */ - - int rendering = 1; - int doseq; - - oldcfra = seq->scene->r.cfra; - - if(rendering) { - BLI_strncpy(scenename, sce->id.name+2, 64); - strcpy(sce->id.name+2, " do_build_seq_ibuf"); - } - re= RE_NewRender(sce->id.name); - - /* prevent eternal loop */ - doseq= scene->r.scemode & R_DOSEQ; - scene->r.scemode &= ~R_DOSEQ; - - RE_BlenderFrame(re, sce, - seq->sfra+se->nr+seq->anim_startofs); - - if(rendering) - BLI_strncpy(sce->id.name+2, scenename, 64); - - RE_AcquireResultImage(re, &rres); - - if(rres.rectf) { - se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); - memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty); - if(rres.rectz) { - addzbuffloatImBuf(se->ibuf); - memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty); - } - } else if (rres.rect32) { - se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); - memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); - } - - RE_ReleaseResultImage(re); - - // BIF_end_render_callbacks(); - - /* restore */ - scene->r.scemode |= doseq; - - seq->scene->r.cfra = oldcfra; - - copy_to_ibuf_still(seq, se); - - if (!build_proxy_run) { - if(se->ibuf == NULL) { - se->ok = STRIPELEM_FAILED; - } else { - input_preprocess(scene, seq, se, cfra); - } - } - - } - } - if (!build_proxy_run) { - if (se->ibuf && use_limiter) { - IMB_cache_limiter_insert(se->ibuf); - IMB_cache_limiter_ref(se->ibuf); - IMB_cache_limiter_touch(se->ibuf); - } - } -} - -static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra, int render_size); - -static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra, int render_size) -{ - float fac, facf; - struct SeqEffectHandle sh = get_sequence_effect(seq); - int early_out; - FCurve *fcu= NULL; - - se->se1 = 0; - se->se2 = 0; - se->se3 = 0; - - if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { - sh.get_default_fac(seq, cfra, &fac, &facf); - if( scene->r.mode & R_FIELDS ); else facf= fac; - } else { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, - "effect_fader", 0); - if (fcu) { - fac = facf = evaluate_fcurve(fcu, cfra); - if( scene->r.mode & R_FIELDS ) { - facf = evaluate_fcurve(fcu, cfra + 0.5); - } - } else { - fac = facf = seq->effect_fader; - } - } - - early_out = sh.early_out(seq, fac, facf); - switch (early_out) { - case -1: - /* no input needed */ - break; - case 0: - se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size); - se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size); - if (seq->seq3) { - se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra, render_size); - } - break; - case 1: - se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size); - break; - case 2: - se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size); - break; - } - - - do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size); - - /* children are not needed anymore ... */ - - if (se->se1 && se->se1->ibuf) { - IMB_cache_limiter_unref(se->se1->ibuf); - } - if (se->se2 && se->se2->ibuf) { - IMB_cache_limiter_unref(se->se2->ibuf); - } - if (se->se3 && se->se3->ibuf) { - IMB_cache_limiter_unref(se->se3->ibuf); - } - check_limiter_refcount("do_effect_seq_recursively", se); -} - -static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra, int render_size) -{ - TStripElem *se; - - se = give_tstripelem(seq, cfra); - - if(se) { - if (seq->type & SEQ_EFFECT) { - do_effect_seq_recursively(scene, seq, se, cfra, render_size); - } else { - do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size); - } - } - return se; -} - -/* FIXME: - -If cfra was float throughout blender (especially in the render -pipeline) one could even _render_ with subframe precision -instead of faking using the blend code below... - -*/ - -static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra, int render_size) -{ - SpeedControlVars * s = (SpeedControlVars *)seq->effectdata; - int nr = cfra - seq->start; - float f_cfra; - int cfra_left; - int cfra_right; - TStripElem * se = 0; - TStripElem * se1 = 0; - TStripElem * se2 = 0; - - sequence_effect_speed_rebuild_map(scene, seq, 0); - - f_cfra = seq->start + s->frameMap[nr]; - - cfra_left = (int) floor(f_cfra); - cfra_right = (int) ceil(f_cfra); - - se = give_tstripelem(seq, cfra); - - if (!se) { - return se; - } - - if (cfra_left == cfra_right || - (s->flags & SEQ_SPEED_BLEND) == 0) { - test_and_auto_discard_ibuf(se); - - if (se->ibuf == NULL) { - se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size); - - if((se1 && se1->ibuf && se1->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - - if (se1 == 0 || se1->ibuf == 0) { - make_black_ibuf(se->ibuf); - } else { - if (se->ibuf != se1->ibuf) { - if (se->ibuf) { - IMB_freeImBuf(se->ibuf); - } - - se->ibuf = se1->ibuf; - IMB_refImBuf(se->ibuf); - } - } - } - } else { - struct SeqEffectHandle sh; - - if(se->ibuf) { - if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty - || !(se->ibuf->rect || se->ibuf->rect_float)) { - IMB_freeImBuf(se->ibuf); - se->ibuf= 0; - } - } - - if (se->ibuf == NULL) { - se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size); - se2 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_right, render_size); - - if((se1 && se1->ibuf && se1->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - - if (!se1 || !se2) { - make_black_ibuf(se->ibuf); - } else { - sh = get_sequence_effect(seq); - - sh.execute(scene, seq, cfra, - f_cfra - (float) cfra_left, - f_cfra - (float) cfra_left, - se->ibuf->x, se->ibuf->y, - se1->ibuf, se2->ibuf, 0, se->ibuf); - } - } - - } - - /* caller expects this to be referenced, so do it! */ - if (se->ibuf) { - IMB_cache_limiter_insert(se->ibuf); - IMB_cache_limiter_ref(se->ibuf); - IMB_cache_limiter_touch(se->ibuf); - } - - /* children are no longer needed */ - if (se1 && se1->ibuf) - IMB_cache_limiter_unref(se1->ibuf); - if (se2 && se2->ibuf) - IMB_cache_limiter_unref(se2->ibuf); - - check_limiter_refcount("do_handle_speed_effect", se); - - return se; -} - -/* - * build all ibufs recursively - * - * if successfull, the returned TStripElem contains the (referenced!) imbuf - * that means: you _must_ call - * - * IMB_cache_limiter_unref(rval); - * - * if rval != 0 - * - */ - -static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra, int render_size) -{ - TStripElem *se; - if (seq->type == SEQ_SPEED) { - se = do_handle_speed_effect(scene, seq, cfra, render_size); - } else { - se = do_build_seq_recursively_impl(scene, seq, cfra, render_size); - } - - check_limiter_refcount("do_build_seq_recursively", se); - - return se; -} - -static TStripElem* do_build_seq_array_recursively(Scene *scene, - ListBase *seqbasep, int cfra, int chanshown, int render_size) -{ - Sequence* seq_arr[MAXSEQ+1]; - int count; - int i; - TStripElem* se = 0; - - count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr); - - if (!count) { - return 0; - } - - se = give_tstripelem(seq_arr[count - 1], cfra); - - if (!se) { - return 0; - } - - test_and_auto_discard_ibuf(se); - - if (se->ibuf_comp != 0) { - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - return se; - } - - - if(count == 1) { - se = do_build_seq_recursively(scene, seq_arr[0], cfra, render_size); - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); - } - return se; - } - - - for (i = count - 1; i >= 0; i--) { - int early_out; - Sequence * seq = seq_arr[i]; - struct SeqEffectHandle sh; - float facf; - - se = give_tstripelem(seq, cfra); - - test_and_auto_discard_ibuf(se); - - if (se->ibuf_comp != 0) { - break; - } - if (seq->blend_mode == SEQ_BLEND_REPLACE) { - do_build_seq_recursively(scene, seq, cfra, render_size); - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf); - } else { - se->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - } - break; - } - - sh = get_sequence_blend(seq); - - facf = seq->blend_opacity / 100.0; - - early_out = sh.early_out(seq, facf, facf); - - switch (early_out) { - case -1: - case 2: - do_build_seq_recursively(scene, seq, cfra, render_size); - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); - } else { - se->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - } - break; - case 1: - if (i == 0) { - se->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - } - break; - case 0: - do_build_seq_recursively(scene, seq, cfra, render_size); - if (!se->ibuf) { - se->ibuf = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf); - IMB_cache_limiter_ref(se->ibuf); - IMB_cache_limiter_touch(se->ibuf); - } - if (i == 0) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); - } - break; - } - - if (se->ibuf_comp) { - break; - } - } - - i++; - - for (; i < count; i++) { - Sequence * seq = seq_arr[i]; - struct SeqEffectHandle sh = get_sequence_blend(seq); - TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra); - TStripElem* se2 = give_tstripelem(seq_arr[i], cfra); - - float facf = seq->blend_opacity / 100.0; - - int early_out = sh.early_out(seq, facf, facf); - switch (early_out) { - case 0: { - int x= se2->ibuf->x; - int y= se2->ibuf->y; - int swap_input = FALSE; - - if (se1->ibuf_comp->rect_float || - se2->ibuf->rect_float) { - se2->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rectfloat, 0); - } else { - se2->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - } - - - if (!se1->ibuf_comp->rect_float && - se2->ibuf_comp->rect_float) { - IMB_float_from_rect(se1->ibuf_comp); - } - if (!se2->ibuf->rect_float && - se2->ibuf_comp->rect_float) { - IMB_float_from_rect(se2->ibuf); - } - - if (!se1->ibuf_comp->rect && - !se2->ibuf_comp->rect_float) { - IMB_rect_from_float(se1->ibuf_comp); - } - if (!se2->ibuf->rect && - !se2->ibuf_comp->rect_float) { - IMB_rect_from_float(se2->ibuf); - } - - /* bad hack, to fix crazy input ordering of - those two effects */ - - if (seq->blend_mode == SEQ_ALPHAOVER || - seq->blend_mode == SEQ_ALPHAUNDER || - seq->blend_mode == SEQ_OVERDROP) { - swap_input = TRUE; - } - - if (swap_input) { - sh.execute(scene, seq, cfra, - facf, facf, x, y, - se2->ibuf, se1->ibuf_comp, 0, - se2->ibuf_comp); - } else { - sh.execute(scene, seq, cfra, - facf, facf, x, y, - se1->ibuf_comp, se2->ibuf, 0, - se2->ibuf_comp); - } - - IMB_cache_limiter_insert(se2->ibuf_comp); - IMB_cache_limiter_ref(se2->ibuf_comp); - IMB_cache_limiter_touch(se2->ibuf_comp); - - IMB_cache_limiter_unref(se1->ibuf_comp); - IMB_cache_limiter_unref(se2->ibuf); - - break; - } - case 1: { - se2->ibuf_comp = se1->ibuf; - IMB_refImBuf(se2->ibuf_comp); - - break; - } - } - se = se2; - } - - return se; -} - -/* - * returned ImBuf is refed! - * you have to unref after usage! - */ - -static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) -{ - Editing *ed= seq_give_editing(scene, FALSE); - int count; - ListBase *seqbasep; - TStripElem *se; - - - if(ed==NULL) return NULL; - - count = BLI_countlist(&ed->metastack); - if((chanshown < 0) && (count > 0)) { - count = MAX2(count + chanshown, 0); - seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep; - } else { - seqbasep= ed->seqbasep; - } - - seqrectx= rectx; /* bad bad global! */ - seqrecty= recty; - - se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown, render_size); - - if(!se) { - return 0; - } - - check_limiter_refcount_comp("give_ibuf_seq_impl", se); - - return se->ibuf_comp; -} - -ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq) -{ - TStripElem* se; - - seqrectx= rectx; /* bad bad global! */ - seqrecty= recty; - - se = do_build_seq_recursively(scene, seq, cfra, render_size); - - if(!se) { - return 0; - } - - check_limiter_refcount("give_ibuf_seq_direct", se); - - if (se->ibuf) { - IMB_cache_limiter_unref(se->ibuf); - } - - return se->ibuf; -} - -ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) -{ - ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown, render_size); - - if (i) { - IMB_cache_limiter_unref(i); - } - return i; -} - -#if 0 -/* check used when we need to change seq->blend_mode but not to effect or audio strips */ -static int seq_can_blend(Sequence *seq) -{ - if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { - return 1; - } else { - return 0; - } -} -#endif - -/* *********************** threading api ******************* */ - -static ListBase running_threads; -static ListBase prefetch_wait; -static ListBase prefetch_done; - -static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t wakeup_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER; - -//static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER; -//static pthread_cond_t prefetch_ready_cond = PTHREAD_COND_INITIALIZER; - -static pthread_mutex_t frame_done_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t frame_done_cond = PTHREAD_COND_INITIALIZER; - -static volatile int seq_thread_shutdown = FALSE; -static volatile int seq_last_given_monoton_cfra = 0; -static int monoton_cfra = 0; - -typedef struct PrefetchThread { - struct PrefetchThread *next, *prev; - - Scene *scene; - struct PrefetchQueueElem *current; - pthread_t pthread; - int running; - -} PrefetchThread; - -typedef struct PrefetchQueueElem { - struct PrefetchQueueElem *next, *prev; - - int rectx; - int recty; - int cfra; - int chanshown; - int render_size; - - int monoton_cfra; - - struct ImBuf * ibuf; -} PrefetchQueueElem; - -#if 0 -static void *seq_prefetch_thread(void * This_) -{ - PrefetchThread * This = This_; - - while (!seq_thread_shutdown) { - PrefetchQueueElem *e; - int s_last; - - pthread_mutex_lock(&queue_lock); - e = prefetch_wait.first; - if (e) { - BLI_remlink(&prefetch_wait, e); - } - s_last = seq_last_given_monoton_cfra; - - This->current = e; - - pthread_mutex_unlock(&queue_lock); - - if (!e) { - pthread_mutex_lock(&prefetch_ready_lock); - - This->running = FALSE; - - pthread_cond_signal(&prefetch_ready_cond); - pthread_mutex_unlock(&prefetch_ready_lock); - - pthread_mutex_lock(&wakeup_lock); - if (!seq_thread_shutdown) { - pthread_cond_wait(&wakeup_cond, &wakeup_lock); - } - pthread_mutex_unlock(&wakeup_lock); - continue; - } - - This->running = TRUE; - - if (e->cfra >= s_last) { - e->ibuf = give_ibuf_seq_impl(This->scene, - e->rectx, e->recty, e->cfra, e->chanshown, - e->render_size); - } - - pthread_mutex_lock(&queue_lock); - - BLI_addtail(&prefetch_done, e); - - for (e = prefetch_wait.first; e; e = e->next) { - if (s_last > e->monoton_cfra) { - BLI_remlink(&prefetch_wait, e); - MEM_freeN(e); - } - } - - for (e = prefetch_done.first; e; e = e->next) { - if (s_last > e->monoton_cfra) { - if (e->ibuf) { - IMB_cache_limiter_unref(e->ibuf); - } - BLI_remlink(&prefetch_done, e); - MEM_freeN(e); - } - } - - pthread_mutex_unlock(&queue_lock); - - pthread_mutex_lock(&frame_done_lock); - pthread_cond_signal(&frame_done_cond); - pthread_mutex_unlock(&frame_done_lock); - } - return 0; -} - -static void seq_start_threads(Scene *scene) -{ - int i; - - running_threads.first = running_threads.last = NULL; - prefetch_wait.first = prefetch_wait.last = NULL; - prefetch_done.first = prefetch_done.last = NULL; - - seq_thread_shutdown = FALSE; - seq_last_given_monoton_cfra = monoton_cfra = 0; - - /* since global structures are modified during the processing - of one frame, only one render thread is currently possible... - - (but we code, in the hope, that we can remove this restriction - soon...) - */ - - fprintf(stderr, "SEQ-THREAD: seq_start_threads\n"); - - for (i = 0; i < 1; i++) { - PrefetchThread *t = MEM_callocN(sizeof(PrefetchThread), "prefetch_thread"); - t->scene= scene; - t->running = TRUE; - BLI_addtail(&running_threads, t); - - pthread_create(&t->pthread, NULL, seq_prefetch_thread, t); - } - - /* init malloc mutex */ - BLI_init_threads(0, 0, 0); -} - -static void seq_stop_threads() -{ - PrefetchThread *tslot; - PrefetchQueueElem *e; - - fprintf(stderr, "SEQ-THREAD: seq_stop_threads()\n"); - - if (seq_thread_shutdown) { - fprintf(stderr, "SEQ-THREAD: ... already stopped\n"); - return; - } - - pthread_mutex_lock(&wakeup_lock); - - seq_thread_shutdown = TRUE; - - pthread_cond_broadcast(&wakeup_cond); - pthread_mutex_unlock(&wakeup_lock); - - for(tslot = running_threads.first; tslot; tslot= tslot->next) { - pthread_join(tslot->pthread, NULL); - } - - - for (e = prefetch_wait.first; e; e = e->next) { - BLI_remlink(&prefetch_wait, e); - MEM_freeN(e); - } - - for (e = prefetch_done.first; e; e = e->next) { - if (e->ibuf) { - IMB_cache_limiter_unref(e->ibuf); - } - BLI_remlink(&prefetch_done, e); - MEM_freeN(e); - } - - BLI_freelistN(&running_threads); - - /* deinit malloc mutex */ - BLI_end_threads(0); -} -#endif - -void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, - int render_size) -{ - PrefetchQueueElem *e; - if (seq_thread_shutdown) { - return; - } - - e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem"); - e->rectx = rectx; - e->recty = recty; - e->cfra = cfra; - e->chanshown = chanshown; - e->render_size = render_size; - e->monoton_cfra = monoton_cfra++; - - pthread_mutex_lock(&queue_lock); - BLI_addtail(&prefetch_wait, e); - pthread_mutex_unlock(&queue_lock); - - pthread_mutex_lock(&wakeup_lock); - pthread_cond_signal(&wakeup_cond); - pthread_mutex_unlock(&wakeup_lock); -} - -#if 0 -static void seq_wait_for_prefetch_ready() -{ - PrefetchThread *tslot; - - if (seq_thread_shutdown) { - return; - } - - fprintf(stderr, "SEQ-THREAD: rendering prefetch frames...\n"); - - pthread_mutex_lock(&prefetch_ready_lock); - - for(;;) { - for(tslot = running_threads.first; tslot; tslot= tslot->next) { - if (tslot->running) { - break; - } - } - if (!tslot) { - break; - } - pthread_cond_wait(&prefetch_ready_cond, &prefetch_ready_lock); - } - - pthread_mutex_unlock(&prefetch_ready_lock); - - fprintf(stderr, "SEQ-THREAD: prefetch done\n"); -} -#endif - -ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) -{ - PrefetchQueueElem *e = NULL; - int found_something = FALSE; - - if (seq_thread_shutdown) { - return give_ibuf_seq(scene, rectx, recty, cfra, chanshown, render_size); - } - - while (!e) { - int success = FALSE; - pthread_mutex_lock(&queue_lock); - - for (e = prefetch_done.first; e; e = e->next) { - if (cfra == e->cfra && - chanshown == e->chanshown && - rectx == e->rectx && - recty == e->recty && - render_size == e->render_size) { - success = TRUE; - found_something = TRUE; - break; - } - } - - if (!e) { - for (e = prefetch_wait.first; e; e = e->next) { - if (cfra == e->cfra && - chanshown == e->chanshown && - rectx == e->rectx && - recty == e->recty && - render_size == e->render_size) { - found_something = TRUE; - break; - } - } - } - - if (!e) { - PrefetchThread *tslot; - - for(tslot = running_threads.first; - tslot; tslot= tslot->next) { - if (tslot->current && - cfra == tslot->current->cfra && - chanshown == tslot->current->chanshown && - rectx == tslot->current->rectx && - recty == tslot->current->recty && - render_size== tslot->current->render_size){ - found_something = TRUE; - break; - } - } - } - - /* e->ibuf is unrefed by render thread on next round. */ - - if (e) { - seq_last_given_monoton_cfra = e->monoton_cfra; - } - - pthread_mutex_unlock(&queue_lock); - - if (!success) { - e = NULL; - - if (!found_something) { - fprintf(stderr, - "SEQ-THREAD: Requested frame " - "not in queue ???\n"); - break; - } - pthread_mutex_lock(&frame_done_lock); - pthread_cond_wait(&frame_done_cond, &frame_done_lock); - pthread_mutex_unlock(&frame_done_lock); - } - } - - return e ? e->ibuf : 0; -} - -/* Functions to free imbuf and anim data on changes */ - -static void free_imbuf_strip_elem(TStripElem *se) -{ - if(se->ibuf) { - IMB_freeImBuf(se->ibuf); - } - if(se->ibuf_comp) { - IMB_freeImBuf(se->ibuf_comp); - } - se->ibuf_comp = 0; - se->ibuf= 0; - se->ok= STRIPELEM_OK; - se->se1= se->se2= se->se3= 0; -} - -static void free_anim_seq(Sequence *seq) -{ - if(seq->anim) { - IMB_free_anim(seq->anim); - seq->anim = 0; - } -} - -#if 0 -static void free_imbuf_seq_except(Scene *scene, int cfra) -{ - Editing *ed= seq_give_editing(scene, FALSE); - Sequence *seq; - TStripElem *se; - int a; - - if(ed==NULL) return; - - SEQ_BEGIN(ed, seq) { - if(seq->strip) { - TStripElem * curelem = give_tstripelem(seq, cfra); - - for(a = 0, se = seq->strip->tstripdata; - a < seq->strip->len && se; a++, se++) { - if(se != curelem) { - free_imbuf_strip_elem(se); - } - } - for(a = 0, se = seq->strip->tstripdata_startstill; - a < seq->strip->startstill && se; a++, se++) { - if(se != curelem) { - free_imbuf_strip_elem(se); - } - } - for(a = 0, se = seq->strip->tstripdata_endstill; - a < seq->strip->endstill && se; a++, se++) { - if(se != curelem) { - free_imbuf_strip_elem(se); - } - } - if(seq->strip->ibuf_startstill) { - IMB_freeImBuf(seq->strip->ibuf_startstill); - seq->strip->ibuf_startstill = 0; - } - - if(seq->strip->ibuf_endstill) { - IMB_freeImBuf(seq->strip->ibuf_endstill); - seq->strip->ibuf_endstill = 0; - } - - if(seq->type==SEQ_MOVIE) - if(seq->startdisp > cfra || seq->enddisp < cfra) - free_anim_seq(seq); - free_proxy_seq(seq); - } - } - SEQ_END -} -#endif - -void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage) -{ - Sequence *seq; - TStripElem *se; - int a; - - if (check_mem_usage) { - /* Let the cache limitor take care of this (schlaile) */ - /* While render let's keep all memory available for render - (ton) - At least if free memory is tight... - This can make a big difference in encoding speed - (it is around 4 times(!) faster, if we do not waste time - on freeing _all_ buffers every time on long timelines...) - (schlaile) - */ - - uintptr_t mem_in_use; - uintptr_t mmap_in_use; - uintptr_t max; - - mem_in_use= MEM_get_memory_in_use(); - mmap_in_use= MEM_get_mapped_memory_in_use(); - max = MEM_CacheLimiter_get_maximum(); - - if (max == 0 || mem_in_use + mmap_in_use <= max) { - return; - } - } - - - for(seq= seqbase->first; seq; seq= seq->next) { - if(seq->strip) { - for(a = 0, se = seq->strip->tstripdata; - a < seq->strip->len && se; a++, se++) { - free_imbuf_strip_elem(se); - } - for(a = 0, se = seq->strip->tstripdata_startstill; - a < seq->strip->startstill && se; a++, se++) { - free_imbuf_strip_elem(se); - } - for(a = 0, se = seq->strip->tstripdata_endstill; - a < seq->strip->endstill && se; a++, se++) { - free_imbuf_strip_elem(se); - } - if(seq->strip->ibuf_startstill) { - IMB_freeImBuf(seq->strip->ibuf_startstill); - seq->strip->ibuf_startstill = 0; - } - - if(seq->strip->ibuf_endstill) { - IMB_freeImBuf(seq->strip->ibuf_endstill); - seq->strip->ibuf_endstill = 0; - } - - if(seq->type==SEQ_MOVIE) - free_anim_seq(seq); - if(seq->type==SEQ_SPEED) { - sequence_effect_speed_rebuild_map(scene, seq, 1); - } - } - if(seq->type==SEQ_META) { - free_imbuf_seq(scene, &seq->seqbase, FALSE); - } - if(seq->type==SEQ_SCENE) { - /* FIXME: recurs downwards, - but do recurs protection somehow! */ - } - } - -} - -static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change) -{ - Sequence *subseq; - int a, free_imbuf = 0; - TStripElem *se; - - /* recurs downwards to see if this seq depends on the changed seq */ - - if(seq == NULL) - return 0; - - if(seq == changed_seq) - free_imbuf = 1; - - for(subseq=seq->seqbase.first; subseq; subseq=subseq->next) - if(update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change)) - free_imbuf = TRUE; - - if(seq->seq1) - if(update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change)) - free_imbuf = TRUE; - if(seq->seq2 && (seq->seq2 != seq->seq1)) - if(update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change)) - free_imbuf = TRUE; - if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) - if(update_changed_seq_recurs(scene, seq->seq3, changed_seq, len_change, ibuf_change)) - free_imbuf = TRUE; - - if(free_imbuf) { - if(ibuf_change) { - se= seq->strip->tstripdata; - if (se) { - for(a=0; alen; a++, se++) - free_imbuf_strip_elem(se); - } - - if(seq->type == SEQ_MOVIE) - free_anim_seq(seq); - if(seq->type == SEQ_SPEED) { - sequence_effect_speed_rebuild_map(scene, seq, 1); - } - } - - if(len_change) - calc_sequence(seq); - } - - return free_imbuf; -} - -void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change) -{ - Editing *ed= seq_give_editing(scene, FALSE); - Sequence *seq; - - if (ed==NULL) return; - - for (seq=ed->seqbase.first; seq; seq=seq->next) - update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change); -} - -#if 0 // XXX from 2.4x, needs updating -void free_imbuf_seq() -{ - Scene * sce = G.main->scene.first; - while(sce) { - free_imbuf_seq_editing(sce->ed); - sce= sce->id.next; - } -} -#endif - -#if 0 // XXX old animation system -static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) -{ - /* force update of all sequences with this ipo, on ipo changes */ - Editing *ed= seq_give_editing(scene, FALSE); - Sequence *seq; - - if(ed==NULL) return; - - SEQ_BEGIN(ed, seq) { - if(seq->ipo == ipo) { - update_changed_seq_and_deps(scene, seq, 0, 1); - if(seq->type == SEQ_SPEED) { - sequence_effect_speed_rebuild_map(seq, 1); - } - free_proxy_seq(seq); - } - } - SEQ_END -} -#endif - -/* seq funcs's for transforming internally - notice the difference between start/end and left/right. - - left and right are the bounds at which the sequence is rendered, -start and end are from the start and fixed length of the sequence. -*/ -int seq_tx_get_start(Sequence *seq) { - return seq->start; -} -int seq_tx_get_end(Sequence *seq) -{ - return seq->start+seq->len; -} - -int seq_tx_get_final_left(Sequence *seq, int metaclip) -{ - if (metaclip && seq->tmp) { - /* return the range clipped by the parents range */ - return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) ); - } else { - return (seq->start - seq->startstill) + seq->startofs; - } - -} -int seq_tx_get_final_right(Sequence *seq, int metaclip) -{ - if (metaclip && seq->tmp) { - /* return the range clipped by the parents range */ - return MIN2( seq_tx_get_final_right(seq, 0), seq_tx_get_final_right((Sequence *)seq->tmp, 1) ); - } else { - return ((seq->start+seq->len) + seq->endstill) - seq->endofs; - } -} - -void seq_tx_set_final_left(Sequence *seq, int val) -{ - if (val < (seq)->start) { - seq->startstill = abs(val - (seq)->start); - seq->startofs = 0; - } else { - seq->startofs = abs(val - (seq)->start); - seq->startstill = 0; - } -} - -void seq_tx_set_final_right(Sequence *seq, int val) -{ - if (val > (seq)->start + (seq)->len) { - seq->endstill = abs(val - (seq->start + (seq)->len)); - seq->endofs = 0; - } else { - seq->endofs = abs(val - ((seq)->start + (seq)->len)); - seq->endstill = 0; - } -} - -/* used so we can do a quick check for single image seq - since they work a bit differently to normal image seq's (during transform) */ -int check_single_seq(Sequence *seq) -{ - if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR)) - return 1; - else - return 0; -} - -/* use to impose limits when dragging/extending - so impossible situations dont happen - * Cant use the SEQ_LEFTSEL and SEQ_LEFTSEL directly because the strip may be in a metastrip */ -void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) -{ - if(leftflag) { - if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_final_right(seq, 0)) { - seq_tx_set_final_left(seq, seq_tx_get_final_right(seq, 0)-1); - } - - if (check_single_seq(seq)==0) { - if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_end(seq)) { - seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1); - } - - /* dosnt work now - TODO */ - /* - if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) { - int ofs; - ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0); - seq->start -= ofs; - seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs ); - }*/ - - } - } - - if(rightflag) { - if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_final_left(seq, 0)) { - seq_tx_set_final_right(seq, seq_tx_get_final_left(seq, 0)+1); - } - - if (check_single_seq(seq)==0) { - if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_start(seq)) { - seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1); - } - } - } - - /* sounds cannot be extended past their endpoints */ - if (seq->type == SEQ_SOUND) { - seq->startstill= 0; - seq->endstill= 0; - } -} - -void fix_single_seq(Sequence *seq) -{ - int left, start, offset; - if (!check_single_seq(seq)) - return; - - /* make sure the image is always at the start since there is only one, - adjusting its start should be ok */ - left = seq_tx_get_final_left(seq, 0); - start = seq->start; - if (start != left) { - offset = left - start; - seq_tx_set_final_left( seq, seq_tx_get_final_left(seq, 0) - offset ); - seq_tx_set_final_right( seq, seq_tx_get_final_right(seq, 0) - offset ); - seq->start += offset; - } -} - -int seq_tx_test(Sequence * seq) -{ - return (seq->type < SEQ_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0); -} - -static int seq_overlap(Sequence *seq1, Sequence *seq2) -{ - if(seq1 != seq2) - if(seq1->machine==seq2->machine) - if(((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0) - return 1; - - return 0; -} - -int seq_test_overlap(ListBase * seqbasep, Sequence *test) -{ - Sequence *seq; - - seq= seqbasep->first; - while(seq) { - if(seq_overlap(test, seq)) - return 1; - - seq= seq->next; - } - return 0; -} - - -static void seq_translate(Sequence *seq, int delta) -{ - seq->start += delta; - if(seq->type==SEQ_META) { - Sequence *seq_child; - for(seq_child= seq->seqbase.first; seq_child; seq_child= seq_child->next) { - seq_translate(seq_child, delta); - } - } - - calc_sequence_disp(seq); -} - -/* return 0 if there werent enough space */ -int shuffle_seq(ListBase * seqbasep, Sequence *test) -{ - int orig_machine= test->machine; - test->machine++; - calc_sequence(test); - while( seq_test_overlap(seqbasep, test) ) { - if(test->machine >= MAXSEQ) { - break; - } - test->machine++; - calc_sequence(test); // XXX - I dont think this is needed since were only moving vertically, Campbell. - } - - - if(test->machine >= MAXSEQ) { - /* Blender 2.4x would remove the strip. - * nicer to move it to the end */ - - Sequence *seq; - int new_frame= test->enddisp; - - for(seq= seqbasep->first; seq; seq= seq->next) { - if (seq->machine == orig_machine) - new_frame = MAX2(new_frame, seq->enddisp); - } - - test->machine= orig_machine; - new_frame = new_frame + (test->start-test->startdisp); /* adjust by the startdisp */ - seq_translate(test, new_frame - test->start); - - calc_sequence(test); - return 0; - } else { - return 1; - } -} - -static int shuffle_seq_time_offset_test(ListBase * seqbasep, char dir) -{ - int offset= 0; - Sequence *seq, *seq_other; - - for(seq= seqbasep->first; seq; seq= seq->next) { - if(seq->tmp) { - for(seq_other= seqbasep->first; seq_other; seq_other= seq_other->next) { - if(!seq_other->tmp && seq_overlap(seq, seq_other)) { - if(dir=='L') { - offset= MIN2(offset, seq_other->startdisp - seq->enddisp); - } - else { - offset= MAX2(offset, seq_other->enddisp - seq->startdisp); - } - } - } - } - } - return offset; -} - -static int shuffle_seq_time_offset(ListBase * seqbasep, char dir) -{ - int ofs= 0; - int tot_ofs= 0; - Sequence *seq; - while( (ofs= shuffle_seq_time_offset_test(seqbasep, dir)) ) { - for(seq= seqbasep->first; seq; seq= seq->next) { - if(seq->tmp) { - /* seq_test_overlap only tests display values */ - seq->startdisp += ofs; - seq->enddisp += ofs; - } - } - - tot_ofs+= ofs; - } - - for(seq= seqbasep->first; seq; seq= seq->next) { - if(seq->tmp) - calc_sequence_disp(seq); /* corrects dummy startdisp/enddisp values */ - } - - return tot_ofs; -} - -int shuffle_seq_time(ListBase * seqbasep) -{ - /* note: seq->tmp is used to tag strips to move */ - - Sequence *seq; - - int offset_l = shuffle_seq_time_offset(seqbasep, 'L'); - int offset_r = shuffle_seq_time_offset(seqbasep, 'R'); - int offset = (-offset_l < offset_r) ? offset_l:offset_r; - - if(offset) { - for(seq= seqbasep->first; seq; seq= seq->next) { - if(seq->tmp) { - seq_translate(seq, offset); - seq->flag &= ~SEQ_OVERLAP; - } - } - } - - return offset? 0:1; -} - -void seq_update_sound(Sequence *seq) -{ - if(seq->type == SEQ_SOUND && seq->sound_handle) - { - seq->sound_handle->startframe = seq->startdisp; - seq->sound_handle->endframe = seq->enddisp; - seq->sound_handle->frameskip = seq->startofs + seq->anim_startofs; - seq->sound_handle->changed = -1; - /* mute is set in seq_update_muting_recursive */ - } -} - -static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute) -{ - Sequence *seq; - int seqmute; - - /* for sound we go over full meta tree to update muted state, - since sound is played outside of evaluating the imbufs, */ - for(seq=seqbasep->first; seq; seq=seq->next) { - seqmute= (mute || (seq->flag & SEQ_MUTE)); - - if(seq->type == SEQ_META) { - /* if this is the current meta sequence, unmute because - all sequences above this were set to mute */ - if(seq == metaseq) - seqmute= 0; - - seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute); - } - else if(seq->type == SEQ_SOUND) { - if(seq->sound_handle && seqmute != seq->sound_handle->mute) { - seq->sound_handle->mute = seqmute; - seq->sound_handle->changed = -1; - } - } - } -} - -void seq_update_muting(Editing *ed) -{ - if(ed) { - /* mute all sounds up to current metastack list */ - MetaStack *ms= ed->metastack.last; - - if(ms) - seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1); - else - seq_update_muting_recursive(&ed->seqbase, NULL, 0); - } -} - - -/* XXX - hackish function needed for transforming strips! TODO - have some better solution */ -void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) -{ - char str[32]; - FCurve *fcu; - - if(scene->adt==NULL || ofs==0) - return; - - sprintf(str, "[\"%s\"]", seq->name+2); - - for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) { - if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { - int i; - for (i = 0; i < fcu->totvert; i++) { - BezTriple *bezt= &fcu->bezt[i]; - bezt->vec[0][0] += ofs; - bezt->vec[1][0] += ofs; - bezt->vec[2][0] += ofs; - } - } - } -} - - -Sequence *active_seq_get(Scene *scene) -{ - Editing *ed= seq_give_editing(scene, FALSE); - if(ed==NULL) return NULL; - return ed->act_seq; -} - -void active_seq_set(Scene *scene, Sequence *seq) -{ - Editing *ed= seq_give_editing(scene, FALSE); - if(ed==NULL) return; - - ed->act_seq= seq; -} - -/* api like funcs for adding */ - -void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) -{ - if(seq) { - strcpy(seq->name, seq_load->name); - seqUniqueName(scene->ed->seqbasep, seq); - - if(seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) { - seq_load->start_frame += (seq->enddisp - seq->startdisp); - } - - if(seq_load->flag & SEQ_LOAD_REPLACE_SEL) { - seq_load->flag |= 1; /* SELECT */ - active_seq_set(scene, seq); - } - - if(seq_load->flag & SEQ_LOAD_SOUND_CACHE) { - if(seq->sound) - sound_cache(seq->sound, 0); - } - - seq_load->tot_success++; - } - else { - seq_load->tot_error++; - } -} - -Sequence *alloc_sequence(ListBase *lb, int cfra, int machine) -{ - Sequence *seq; - - seq= MEM_callocN( sizeof(Sequence), "addseq"); - BLI_addtail(lb, seq); - - *( (short *)seq->name )= ID_SEQ; - seq->name[2]= 0; - - seq->flag= 1; /* SELECT */ - seq->start= cfra; - seq->machine= machine; - seq->mul= 1.0; - seq->blend_opacity = 100.0; - - return seq; -} - -void seqUniqueName(ListBase *seqbasep, Sequence *seq) -{ - BLI_uniquename(seqbasep, seq, "Sequence", '.', offsetof(Sequence, name), SEQ_NAME_MAXSTR); -} - -/* NOTE: this function doesn't fill in iamge names */ -Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - Scene *scene= CTX_data_scene(C); /* only for active seq */ - Sequence *seq; - Strip *strip; - StripElem *se; - - seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); - seq->type= SEQ_IMAGE; - BLI_strncpy(seq->name+2, "Image", SEQ_NAME_MAXSTR-2); - seqUniqueName(seqbasep, seq); - - /* basic defaults */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - - strip->len = seq->len = seq_load->len ? seq_load->len : 1; - strip->us= 1; - strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name); - - seq_load_apply(scene, seq, seq_load); - - return seq; -} - -Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - Scene *scene= CTX_data_scene(C); /* only for sound */ - Editing *ed= seq_give_editing(scene, TRUE); - bSound *sound; - - Sequence *seq; /* generic strip vars */ - Strip *strip; - StripElem *se; - - AUD_SoundInfo info; - - sound = sound_new_file(CTX_data_main(C), seq_load->path); - - if (sound==NULL || sound->handle == NULL) { - //if(op) - // BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - return NULL; - } - - info = AUD_getInfo(sound->handle); - - if (info.specs.format == AUD_FORMAT_INVALID) { - sound_delete(C, sound); - //if(op) - // BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - return NULL; - } - - seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); - - seq->type= SEQ_SOUND; - seq->sound= sound; - BLI_strncpy(seq->name+2, "Sound", SEQ_NAME_MAXSTR-2); - seqUniqueName(seqbasep, seq); - - /* basic defaults */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len = seq->len = (int) (info.length * FPS); - strip->us= 1; - - strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - - BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name); - - seq->sound_handle = sound_new_handle(scene, sound, seq_load->start_frame, seq_load->start_frame + strip->len, 0); - - calc_sequence_disp(seq); - - /* last active name */ - strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR-1); - - seq_load_apply(scene, seq, seq_load); - - return seq; -} - -Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - Scene *scene= CTX_data_scene(C); /* only for sound */ - - Sequence *seq, *soundseq; /* generic strip vars */ - Strip *strip; - StripElem *se; - - struct anim *an; - - an = openanim(seq_load->path, IB_rect); - - if(an==NULL) - return NULL; - - seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); - - seq->type= SEQ_MOVIE; - seq->anim= an; - seq->anim_preseek = IMB_anim_get_preseek(an); - BLI_strncpy(seq->name+2, "Movie", SEQ_NAME_MAXSTR-2); - seqUniqueName(seqbasep, seq); - - /* basic defaults */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len = seq->len = IMB_anim_get_duration( an ); - strip->us= 1; - - strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - - BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name); - - calc_sequence_disp(seq); - - - if(seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { - int start_frame_back= seq_load->start_frame; - seq_load->channel++; - - soundseq = sequencer_add_sound_strip(C, seqbasep, seq_load); - - seq_load->start_frame= start_frame_back; - seq_load->channel--; - } - - /* can be NULL */ - seq_load_apply(scene, seq, seq_load); - - return seq; -} diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c new file mode 100644 index 00000000000..c5ca24bec45 --- /dev/null +++ b/source/blender/blenkernel/intern/sequencer.c @@ -0,0 +1,3758 @@ +/** +* $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): + * - Blender Foundation, 2003-2009 + * - Peter Schlaile 2005/2006 + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include + +#include "MEM_guardedalloc.h" +#include "MEM_CacheLimiterC-Api.h" + +#include "DNA_listBase.h" +#include "DNA_sequence_types.h" +#include "DNA_scene_types.h" +#include "DNA_anim_types.h" + +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_sequencer.h" +#include "BKE_fcurve.h" +#include "BKE_utildefines.h" +#include "RNA_access.h" +#include "RE_pipeline.h" + +#include "BLI_blenlib.h" +#include "BLI_util.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BLI_threads.h" +#include + +#include "BKE_context.h" +#include "BKE_sound.h" +#include "AUD_C-API.h" + +#ifdef WIN32 +#define snprintf _snprintf +#endif + +/* **** XXX ******** */ +static int seqrectx= 0; /* bad bad global! */ +static int seqrecty= 0; +//static void waitcursor(int val) {} +//static int blender_test_break() {return 0;} + +/* **** XXX ******** */ + + +void printf_strip(Sequence *seq) +{ + fprintf(stderr, "name: '%s', len:%d, start:%d, (startofs:%d, endofs:%d), (startstill:%d, endstill:%d), machine:%d, (startdisp:%d, enddisp:%d)\n", + seq->name, seq->len, seq->start, seq->startofs, seq->endofs, seq->startstill, seq->endstill, seq->machine, seq->startdisp, seq->enddisp); + fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0), seq_tx_get_final_right(seq, 0)); +} + +/* ********************************************************************** + alloc / free functions + ********************************************************************** */ + +static void free_tstripdata(int len, TStripElem *se) +{ + TStripElem *seo; + int a; + + seo= se; + if (!se) + return; + + for(a=0; aibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = 0; + } + if(se->ibuf_comp) { + IMB_freeImBuf(se->ibuf_comp); + se->ibuf_comp = 0; + } + } + + MEM_freeN(seo); +} + + +void new_tstripdata(Sequence *seq) +{ + if(seq->strip) { + free_tstripdata(seq->strip->len, seq->strip->tstripdata); + free_tstripdata(seq->strip->endstill, + seq->strip->tstripdata_endstill); + free_tstripdata(seq->strip->startstill, + seq->strip->tstripdata_startstill); + + seq->strip->tstripdata= 0; + seq->strip->tstripdata_endstill= 0; + seq->strip->tstripdata_startstill= 0; + + if(seq->strip->ibuf_startstill) { + IMB_freeImBuf(seq->strip->ibuf_startstill); + seq->strip->ibuf_startstill = 0; + } + + if(seq->strip->ibuf_endstill) { + IMB_freeImBuf(seq->strip->ibuf_endstill); + seq->strip->ibuf_endstill = 0; + } + + seq->strip->len= seq->len; + } +} + + +/* free */ + +static void free_proxy_seq(Sequence *seq) +{ + if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { + IMB_free_anim(seq->strip->proxy->anim); + seq->strip->proxy->anim = 0; + } +} + +void seq_free_strip(Strip *strip) +{ + strip->us--; + if(strip->us>0) return; + if(strip->us<0) { + printf("error: negative users in strip\n"); + return; + } + + if (strip->stripdata) { + MEM_freeN(strip->stripdata); + } + + if (strip->proxy) { + if (strip->proxy->anim) { + IMB_free_anim(strip->proxy->anim); + } + + MEM_freeN(strip->proxy); + } + if (strip->crop) { + MEM_freeN(strip->crop); + } + if (strip->transform) { + MEM_freeN(strip->transform); + } + if (strip->color_balance) { + MEM_freeN(strip->color_balance); + } + + free_tstripdata(strip->len, strip->tstripdata); + free_tstripdata(strip->endstill, strip->tstripdata_endstill); + free_tstripdata(strip->startstill, strip->tstripdata_startstill); + + if(strip->ibuf_startstill) { + IMB_freeImBuf(strip->ibuf_startstill); + strip->ibuf_startstill = 0; + } + + if(strip->ibuf_endstill) { + IMB_freeImBuf(strip->ibuf_endstill); + strip->ibuf_endstill = 0; + } + + MEM_freeN(strip); +} + +void seq_free_sequence(Scene *scene, Sequence *seq) +{ + Editing *ed = scene->ed; + + if(seq->strip) seq_free_strip(seq->strip); + + if(seq->anim) IMB_free_anim(seq->anim); + + if(seq->sound_handle) + sound_delete_handle(scene, seq->sound_handle); + + if (seq->type & SEQ_EFFECT) { + struct SeqEffectHandle sh = get_sequence_effect(seq); + + sh.free(seq); + } + + if (ed->act_seq==seq) + ed->act_seq= NULL; + + MEM_freeN(seq); +} + +Editing *seq_give_editing(Scene *scene, int alloc) +{ + if (scene->ed == NULL && alloc) { + Editing *ed; + + ed= scene->ed= MEM_callocN( sizeof(Editing), "addseq"); + ed->seqbasep= &ed->seqbase; + } + return scene->ed; +} + +void seq_free_editing(Scene *scene) +{ + Editing *ed = scene->ed; + MetaStack *ms; + Sequence *seq; + + if(ed==NULL) + return; + + SEQ_BEGIN(ed, seq) { + seq_free_sequence(scene, seq); + } + SEQ_END + + while((ms= ed->metastack.first)) { + BLI_remlink(&ed->metastack, ms); + MEM_freeN(ms); + } + + MEM_freeN(ed); +} + +/* ************************* itterator ************************** */ +/* *************** (replaces old WHILE_SEQ) ********************* */ +/* **************** use now SEQ_BEGIN() SEQ_END ***************** */ + +/* sequence strip iterator: + * - builds a full array, recursively into meta strips */ + +static void seq_count(ListBase *seqbase, int *tot) +{ + Sequence *seq; + + for(seq=seqbase->first; seq; seq=seq->next) { + (*tot)++; + + if(seq->seqbase.first) + seq_count(&seq->seqbase, tot); + } +} + +static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth) +{ + Sequence *seq; + + for(seq=seqbase->first; seq; seq=seq->next) { + seq->depth= depth; + + if(seq->seqbase.first) + seq_build_array(&seq->seqbase, array, depth+1); + + **array= seq; + (*array)++; + } +} + +void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_pointer) +{ + Sequence **array; + + *seqarray= NULL; + *tot= 0; + + if(ed == NULL) + return; + + if(use_pointer) + seq_count(ed->seqbasep, tot); + else + seq_count(&ed->seqbase, tot); + + if(*tot == 0) + return; + + *seqarray= array= MEM_mallocN(sizeof(Sequence *)*(*tot), "SeqArray"); + if(use_pointer) + seq_build_array(ed->seqbasep, &array, 0); + else + seq_build_array(&ed->seqbase, &array, 0); +} + +void seq_begin(Editing *ed, SeqIterator *iter, int use_pointer) +{ + memset(iter, 0, sizeof(*iter)); + seq_array(ed, &iter->array, &iter->tot, use_pointer); + + if(iter->tot) { + iter->cur= 0; + iter->seq= iter->array[iter->cur]; + iter->valid= 1; + } +} + +void seq_next(SeqIterator *iter) +{ + if(++iter->cur < iter->tot) + iter->seq= iter->array[iter->cur]; + else + iter->valid= 0; +} + +void seq_end(SeqIterator *iter) +{ + if(iter->array) + MEM_freeN(iter->array); + + iter->valid= 0; +} + +/* + ********************************************************************** + * build_seqar + ********************************************************************** + * Build a complete array of _all_ sequencies (including those + * in metastrips!) + ********************************************************************** +*/ + +static void do_seq_count(ListBase *seqbase, int *totseq) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + (*totseq)++; + if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq); + seq= seq->next; + } +} + +static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + seq->depth= depth; + if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1); + **seqar= seq; + (*seqar)++; + seq= seq->next; + } +} + +void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq) +{ + Sequence **tseqar; + + *totseq= 0; + do_seq_count(seqbase, totseq); + + if(*totseq==0) { + *seqar= 0; + return; + } + *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); + tseqar= *seqar; + + do_build_seqar(seqbase, seqar, 0); + *seqar= tseqar; +} + +static void do_seq_count_cb(ListBase *seqbase, int *totseq, + int (*test_func)(Sequence * seq)) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + int test = test_func(seq); + if (test & BUILD_SEQAR_COUNT_CURRENT) { + (*totseq)++; + } + if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { + do_seq_count_cb(&seq->seqbase, totseq, test_func); + } + seq= seq->next; + } +} + +static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth, + int (*test_func)(Sequence * seq)) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + int test = test_func(seq); + seq->depth= depth; + + if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { + do_build_seqar_cb(&seq->seqbase, seqar, depth+1, + test_func); + } + if (test & BUILD_SEQAR_COUNT_CURRENT) { + **seqar= seq; + (*seqar)++; + } + seq= seq->next; + } +} + +void build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int *totseq, + int (*test_func)(Sequence * seq)) +{ + Sequence **tseqar; + + *totseq= 0; + do_seq_count_cb(seqbase, totseq, test_func); + + if(*totseq==0) { + *seqar= 0; + return; + } + *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); + tseqar= *seqar; + + do_build_seqar_cb(seqbase, seqar, 0, test_func); + *seqar= tseqar; +} + + +void calc_sequence_disp(Sequence *seq) +{ + if(seq->startofs && seq->startstill) seq->startstill= 0; + if(seq->endofs && seq->endstill) seq->endstill= 0; + + seq->startdisp= seq->start + seq->startofs - seq->startstill; + seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill; + + seq->handsize= 10.0; /* 10 frames */ + if( seq->enddisp-seq->startdisp < 10 ) { + seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp)); + } + else if(seq->enddisp-seq->startdisp > 250) { + seq->handsize= (float)((seq->enddisp-seq->startdisp)/25); + } + + seq_update_sound(seq); +} + +void calc_sequence(Sequence *seq) +{ + Sequence *seqm; + int min, max; + + /* check all metas recursively */ + seqm= seq->seqbase.first; + while(seqm) { + if(seqm->seqbase.first) calc_sequence(seqm); + seqm= seqm->next; + } + + /* effects and meta: automatic start and end */ + + if(seq->type & SEQ_EFFECT) { + /* pointers */ + if(seq->seq2==0) seq->seq2= seq->seq1; + if(seq->seq3==0) seq->seq3= seq->seq1; + + /* effecten go from seq1 -> seq2: test */ + + /* we take the largest start and smallest end */ + + // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp); + // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp); + + if (seq->seq1) { + seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp); + seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp); + seq->len= seq->enddisp - seq->startdisp; + } else { + calc_sequence_disp(seq); + } + + if(seq->strip && seq->len!=seq->strip->len) { + new_tstripdata(seq); + } + + } + else { + if(seq->type==SEQ_META) { + seqm= seq->seqbase.first; + if(seqm) { + min= 1000000; + max= -1000000; + while(seqm) { + if(seqm->startdisp < min) min= seqm->startdisp; + if(seqm->enddisp > max) max= seqm->enddisp; + seqm= seqm->next; + } + seq->start= min + seq->anim_startofs; + seq->len = max-min; + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + + if(seq->strip && seq->len!=seq->strip->len) { + new_tstripdata(seq); + } + } + } + calc_sequence_disp(seq); + } +} + +void reload_sequence_new_file(Scene *scene, Sequence * seq) +{ + char str[FILE_MAXDIR+FILE_MAXFILE]; + + if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE || + seq->type == SEQ_SOUND || + seq->type == SEQ_SCENE || seq->type == SEQ_META)) { + return; + } + + new_tstripdata(seq); + + if (seq->type != SEQ_SCENE && seq->type != SEQ_META && + seq->type != SEQ_IMAGE) { + BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name); + BLI_convertstringcode(str, G.sce); + BLI_convertstringframe(str, scene->r.cfra); + + } + + if (seq->type == SEQ_IMAGE) { + /* Hack? */ + int olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem); + seq->len = olen; + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } else if (seq->type == SEQ_MOVIE) { + if(seq->anim) IMB_free_anim(seq->anim); + seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0)); + + if (!seq->anim) { + return; + } + + seq->len = IMB_anim_get_duration(seq->anim); + + seq->anim_preseek = IMB_anim_get_preseek(seq->anim); + + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } else if (seq->type == SEQ_SOUND) { + seq->len = AUD_getInfo(seq->sound->handle).length * FPS; + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } else if (seq->type == SEQ_SCENE) { + Scene * sce = G.main->scene.first; + int nr = 1; + + while(sce) { + if(nr == seq->scenenr) { + break; + } + nr++; + sce= sce->id.next; + } + + if (sce) { + seq->scene = sce; + } else { + sce = seq->scene; + } + + BLI_strncpy(seq->name+2, sce->id.name + 2, SEQ_NAME_MAXSTR-2); + seqUniqueName(scene->ed->seqbasep, seq); + + seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1; + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } + + free_proxy_seq(seq); + + calc_sequence(seq); +} + +void sort_seq(Scene *scene) +{ + /* all strips together per kind, and in order of y location ("machine") */ + ListBase seqbase, effbase; + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq, *seqt; + + + if(ed==NULL) return; + + seqbase.first= seqbase.last= 0; + effbase.first= effbase.last= 0; + + while( (seq= ed->seqbasep->first) ) { + BLI_remlink(ed->seqbasep, seq); + + if(seq->type & SEQ_EFFECT) { + seqt= effbase.first; + while(seqt) { + if(seqt->machine>=seq->machine) { + BLI_insertlinkbefore(&effbase, seqt, seq); + break; + } + seqt= seqt->next; + } + if(seqt==0) BLI_addtail(&effbase, seq); + } + else { + seqt= seqbase.first; + while(seqt) { + if(seqt->machine>=seq->machine) { + BLI_insertlinkbefore(&seqbase, seqt, seq); + break; + } + seqt= seqt->next; + } + if(seqt==0) BLI_addtail(&seqbase, seq); + } + } + + addlisttolist(&seqbase, &effbase); + *(ed->seqbasep)= seqbase; +} + + +void clear_scene_in_allseqs(Scene *sce) +{ + Scene *sce1; + Editing *ed; + Sequence *seq; + + /* when a scene is deleted: test all seqs */ + + sce1= G.main->scene.first; + while(sce1) { + if(sce1!=sce && sce1->ed) { + ed= sce1->ed; + + SEQ_BEGIN(ed, seq) { + + if(seq->scene==sce) seq->scene= 0; + + } + SEQ_END + } + + sce1= sce1->id.next; + } +} + +static char *give_seqname_by_type(int type) +{ + switch(type) { + case SEQ_META: return "Meta"; + case SEQ_IMAGE: return "Image"; + case SEQ_SCENE: return "Scene"; + case SEQ_MOVIE: return "Movie"; + case SEQ_SOUND: return "Audio"; + case SEQ_CROSS: return "Cross"; + case SEQ_GAMCROSS: return "Gamma Cross"; + case SEQ_ADD: return "Add"; + case SEQ_SUB: return "Sub"; + case SEQ_MUL: return "Mul"; + case SEQ_ALPHAOVER: return "Alpha Over"; + case SEQ_ALPHAUNDER: return "Alpha Under"; + case SEQ_OVERDROP: return "Over Drop"; + case SEQ_WIPE: return "Wipe"; + case SEQ_GLOW: return "Glow"; + case SEQ_TRANSFORM: return "Transform"; + case SEQ_COLOR: return "Color"; + case SEQ_SPEED: return "Speed"; + default: + return 0; + } +} + +char *give_seqname(Sequence *seq) +{ + char * name = give_seqname_by_type(seq->type); + + if (!name) { + if(seq->typestrip->dir; + } else if(seq->type==SEQ_PLUGIN) { + if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) && + seq->plugin && seq->plugin->doit) { + return seq->plugin->pname; + } else { + return "Plugin"; + } + } else { + return "Effect"; + } + } + return name; +} + +/* ***************** DO THE SEQUENCE ***************** */ + +static void make_black_ibuf(ImBuf *ibuf) +{ + unsigned int *rect; + float *rect_float; + int tot; + + if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return; + + tot= ibuf->x*ibuf->y; + + rect= ibuf->rect; + rect_float = ibuf->rect_float; + + if (rect) { + memset(rect, 0, tot * sizeof(char) * 4); + } + + if (rect_float) { + memset(rect_float, 0, tot * sizeof(float) * 4); + } +} + +static void multibuf(ImBuf *ibuf, float fmul) +{ + char *rt; + float *rt_float; + + int a, mul, icol; + + mul= (int)(256.0*fmul); + rt= (char *)ibuf->rect; + rt_float = ibuf->rect_float; + + if (rt) { + a= ibuf->x*ibuf->y; + while(a--) { + + icol= (mul*rt[0])>>8; + if(icol>254) rt[0]= 255; else rt[0]= icol; + icol= (mul*rt[1])>>8; + if(icol>254) rt[1]= 255; else rt[1]= icol; + icol= (mul*rt[2])>>8; + if(icol>254) rt[2]= 255; else rt[2]= icol; + icol= (mul*rt[3])>>8; + if(icol>254) rt[3]= 255; else rt[3]= icol; + + rt+= 4; + } + } + if (rt_float) { + a= ibuf->x*ibuf->y; + while(a--) { + rt_float[0] *= fmul; + rt_float[1] *= fmul; + rt_float[2] *= fmul; + rt_float[3] *= fmul; + + rt_float += 4; + } + } +} + +static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se) +{ + TStripElem *se1, *se2, *se3; + float fac, facf; + int x, y; + int early_out; + struct SeqEffectHandle sh = get_sequence_effect(seq); + FCurve *fcu= NULL; + + if (!sh.execute) { /* effect not supported in this version... */ + make_black_ibuf(se->ibuf); + return; + } + + if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { + sh.get_default_fac(seq, cfra, &fac, &facf); + if( scene->r.mode & R_FIELDS ); else facf= fac; + } else { + fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, + "effect_fader", 0); + if (fcu) { + fac = facf = evaluate_fcurve(fcu, cfra); + if( scene->r.mode & R_FIELDS ) { + facf = evaluate_fcurve(fcu, cfra + 0.5); + } + } else { + fac = facf = seq->effect_fader; + } + } + + early_out = sh.early_out(seq, fac, facf); + + if (early_out == -1) { /* no input needed */ + sh.execute(scene, seq, cfra, fac, facf, + se->ibuf->x, se->ibuf->y, + 0, 0, 0, se->ibuf); + return; + } + + switch (early_out) { + case 0: + if (se->se1==0 || se->se2==0 || se->se3==0) { + make_black_ibuf(se->ibuf); + return; + } + + se1= se->se1; + se2= se->se2; + se3= se->se3; + + if ( (se1==0 || se2==0 || se3==0) + || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) { + make_black_ibuf(se->ibuf); + return; + } + + break; + case 1: + if (se->se1 == 0) { + make_black_ibuf(se->ibuf); + return; + } + + se1= se->se1; + + if (se1 == 0 || se1->ibuf == 0) { + make_black_ibuf(se->ibuf); + return; + } + + if (se->ibuf != se1->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = se1->ibuf; + IMB_refImBuf(se->ibuf); + } + return; + case 2: + if (se->se2 == 0) { + make_black_ibuf(se->ibuf); + return; + } + + se2= se->se2; + + if (se2 == 0 || se2->ibuf == 0) { + make_black_ibuf(se->ibuf); + return; + } + if (se->ibuf != se2->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = se2->ibuf; + IMB_refImBuf(se->ibuf); + } + return; + default: + make_black_ibuf(se->ibuf); + return; + } + + x= se2->ibuf->x; + y= se2->ibuf->y; + + if (!se1->ibuf->rect_float && se->ibuf->rect_float) { + IMB_float_from_rect(se1->ibuf); + } + if (!se2->ibuf->rect_float && se->ibuf->rect_float) { + IMB_float_from_rect(se2->ibuf); + } + if (!se3->ibuf->rect_float && se->ibuf->rect_float) { + IMB_float_from_rect(se3->ibuf); + } + + if (!se1->ibuf->rect && !se->ibuf->rect_float) { + IMB_rect_from_float(se1->ibuf); + } + if (!se2->ibuf->rect && !se->ibuf->rect_float) { + IMB_rect_from_float(se2->ibuf); + } + if (!se3->ibuf->rect && !se->ibuf->rect_float) { + IMB_rect_from_float(se3->ibuf); + } + + sh.execute(scene, seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf, + se->ibuf); +} + +static int give_stripelem_index(Sequence *seq, int cfra) +{ + int nr; + + if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1; + if(seq->len == 0) return -1; + if(seq->flag&SEQ_REVERSE_FRAMES) { + /*reverse frame in this sequence */ + if(cfra <= seq->start) nr= seq->len-1; + else if(cfra >= seq->start+seq->len-1) nr= 0; + else nr= (seq->start + seq->len) - cfra; + } else { + if(cfra <= seq->start) nr= 0; + else if(cfra >= seq->start+seq->len-1) nr= seq->len-1; + else nr= cfra-seq->start; + } + if (seq->strobe < 1.0) seq->strobe = 1.0; + if (seq->strobe > 1.0) { + nr -= (int)fmod((double)nr, (double)seq->strobe); + } + + return nr; +} + +static TStripElem* alloc_tstripdata(int len, const char * name) +{ + int i; + TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name); + for (i = 0; i < len; i++) { + se[i].ok = STRIPELEM_OK; + } + return se; +} + +static TStripElem *give_tstripelem(Sequence *seq, int cfra) +{ + TStripElem *se; + int nr; + + se = seq->strip->tstripdata; + if (se == 0 && seq->len > 0) { + se = seq->strip->tstripdata = alloc_tstripdata(seq->len, + "tstripelems"); + } + nr = give_stripelem_index(seq, cfra); + + if (nr == -1) return 0; + if (se == 0) return 0; + + se += nr; + + /* if there are IPOs with blend modes active, one has to watch out + for startstill + endstill area: we can't use the same tstripelem + here for all ibufs, since then, blending with IPOs won't work! + + Rather common case, if you use a single image and try to fade + it in and out... or want to use your strip as a watermark in + alpha over mode... + */ + if (seq->blend_mode != SEQ_BLEND_REPLACE || + (/*seq->ipo && seq->ipo->curve.first &&*/ + (!(seq->type & SEQ_EFFECT) || !seq->seq1))) { + Strip * s = seq->strip; + if (cfra < seq->start) { + se = s->tstripdata_startstill; + if (seq->startstill > s->startstill) { + free_tstripdata(s->startstill, + s->tstripdata_startstill); + se = 0; + } + + if (se == 0) { + s->startstill = seq->startstill; + se = seq->strip->tstripdata_startstill + = alloc_tstripdata( + s->startstill, + "tstripelems_startstill"); + } + se += seq->start - cfra - 1; + + } else if (cfra > seq->start + seq->len-1) { + se = s->tstripdata_endstill; + if (seq->endstill > s->endstill) { + free_tstripdata(s->endstill, + s->tstripdata_endstill); + se = 0; + } + + if (se == 0) { + s->endstill = seq->endstill; + se = seq->strip->tstripdata_endstill + = alloc_tstripdata( + s->endstill, + "tstripelems_endstill"); + } + se += cfra - (seq->start + seq->len-1) - 1; + } + } + + + se->nr= nr; + + return se; +} + +StripElem *give_stripelem(Sequence *seq, int cfra) +{ + StripElem *se; + int nr; + + se = seq->strip->stripdata; + nr = give_stripelem_index(seq, cfra); + + if (nr == -1) return 0; + if (se == 0) return 0; + + se += nr + seq->anim_startofs; + + return se; +} + +static int evaluate_seq_frame_gen(Sequence ** seq_arr, ListBase *seqbase, int cfra) +{ + Sequence *seq; + int totseq=0; + + memset(seq_arr, 0, sizeof(Sequence*) * (MAXSEQ+1)); + + seq= seqbase->first; + while(seq) { + if(seq->startdisp <=cfra && seq->enddisp > cfra) { + seq_arr[seq->machine]= seq; + totseq++; + } + seq= seq->next; + } + + return totseq; +} + +int evaluate_seq_frame(Scene *scene, int cfra) +{ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq_arr[MAXSEQ+1]; + + if(ed==NULL) return 0; + return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra); +} + +static int video_seq_is_rendered(Sequence * seq) +{ + return (seq + && !(seq->flag & SEQ_MUTE) + && seq->type != SEQ_SOUND); +} + +static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out) +{ + Sequence *seq_arr[MAXSEQ+1]; + int b = chanshown; + int cnt = 0; + + if (b > MAXSEQ) { + return 0; + } + + if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) { + if (b > 0) { + if (seq_arr[b] == 0) { + return 0; + } + } else { + for (b = MAXSEQ; b > 0; b--) { + if (video_seq_is_rendered(seq_arr[b])) { + break; + } + } + } + } + + chanshown = b; + + for (;b > 0; b--) { + if (video_seq_is_rendered(seq_arr[b])) { + if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) { + break; + } + } + } + + for (;b <= chanshown; b++) { + if (video_seq_is_rendered(seq_arr[b])) { + seq_arr_out[cnt++] = seq_arr[b]; + } + } + + return cnt; +} + + +/* ********************************************************************** + proxy management + ********************************************************************** */ + +#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE) + +static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name, int render_size) +{ + int frameno; + char dir[FILE_MAXDIR]; + + if (!seq->strip->proxy) { + return FALSE; + } + + if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { + strcpy(dir, seq->strip->proxy->dir); + } else { + if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) { + snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", + seq->strip->dir); + } else { + return FALSE; + } + } + + if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + BLI_join_dirfile(name, dir, seq->strip->proxy->file); + BLI_convertstringcode(name, G.sce); + BLI_convertstringframe(name, cfra); + + return TRUE; + } + + /* generate a separate proxy directory for each preview size */ + + if (seq->type == SEQ_IMAGE) { + StripElem * se = give_stripelem(seq, cfra); + snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", + dir, render_size, se->name); + frameno = 1; + } else if (seq->type == SEQ_MOVIE) { + TStripElem * tse = give_tstripelem(seq, cfra); + + frameno = tse->nr + seq->anim_startofs; + + snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir, + seq->strip->stripdata->name, + render_size); + } else { + TStripElem * tse = give_tstripelem(seq, cfra); + + frameno = tse->nr + seq->anim_startofs; + + snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, + render_size); + } + + BLI_convertstringcode(name, G.sce); + BLI_convertstringframe(name, frameno); + + + strcat(name, ".jpg"); + + return TRUE; +} + +static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + char name[PROXY_MAXFILE]; + + if (!(seq->flag & SEQ_USE_PROXY)) { + return 0; + } + + /* rendering at 100% ? No real sense in proxy-ing, right? */ + if (render_size == 100) { + return 0; + } + + if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + TStripElem * tse = give_tstripelem(seq, cfra); + int frameno = tse->nr + seq->anim_startofs; + if (!seq->strip->proxy->anim) { + if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { + return 0; + } + + seq->strip->proxy->anim = openanim(name, IB_rect); + } + if (!seq->strip->proxy->anim) { + return 0; + } + + return IMB_anim_absolute(seq->strip->proxy->anim, frameno); + } + + if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { + return 0; + } + + if (BLI_exists(name)) { + return IMB_loadiffname(name, IB_rect); + } else { + return 0; + } +} + +#if 0 +static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, + int build_proxy_run, int render_size); + +static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + char name[PROXY_MAXFILE]; + int quality; + TStripElem * se; + int ok; + int rectx, recty; + struct ImBuf * ibuf; + + if (!(seq->flag & SEQ_USE_PROXY)) { + return; + } + + /* rendering at 100% ? No real sense in proxy-ing, right? */ + if (render_size == 100) { + return; + } + + /* that's why it is called custom... */ + if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + return; + } + + if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { + return; + } + + se = give_tstripelem(seq, cfra); + if (!se) { + return; + } + + if(se->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = 0; + } + + do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size); + + if (!se->ibuf) { + return; + } + + rectx= (render_size*scene->r.xsch)/100; + recty= (render_size*scene->r.ysch)/100; + + ibuf = se->ibuf; + + if (ibuf->x != rectx || ibuf->y != recty) { + IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty); + } + + /* quality is fixed, otherwise one has to generate separate + directories for every quality... + + depth = 32 is intentionally left in, otherwise ALPHA channels + won't work... */ + quality = seq->strip->proxy->quality; + ibuf->ftype= JPG | quality; + + BLI_make_existing_file(name); + + ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); + if (ok == 0) { + perror(name); + } + + IMB_freeImBuf(ibuf); + se->ibuf = 0; +} + +static void seq_proxy_rebuild(Scene *scene, Sequence * seq) +{ + int cfra; + float rsize = seq->strip->proxy->size; + + waitcursor(1); + + G.afbreek = 0; + + /* flag management tries to account for strobe and + other "non-linearities", that might come in the future... + better way would be to "touch" the files, so that _really_ + no one is rebuild twice. + */ + + for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) { + TStripElem * tse = give_tstripelem(seq, cfra); + + tse->flag &= ~STRIPELEM_PREVIEW_DONE; + } + + + + /* a _lot_ faster for movie files, if we read frames in + sequential order */ + if (seq->flag & SEQ_REVERSE_FRAMES) { + for (cfra = seq->enddisp-seq->endstill-1; + cfra >= seq->startdisp + seq->startstill; cfra--) { + TStripElem * tse = give_tstripelem(seq, cfra); + + if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { +//XXX set_timecursor(cfra); + seq_proxy_build_frame(scene, seq, cfra, rsize); + tse->flag |= STRIPELEM_PREVIEW_DONE; + } + if (blender_test_break()) { + break; + } + } + } else { + for (cfra = seq->startdisp + seq->startstill; + cfra < seq->enddisp - seq->endstill; cfra++) { + TStripElem * tse = give_tstripelem(seq, cfra); + + if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { +//XXX set_timecursor(cfra); + seq_proxy_build_frame(scene, seq, cfra, rsize); + tse->flag |= STRIPELEM_PREVIEW_DONE; + } + if (blender_test_break()) { + break; + } + } + } + waitcursor(0); +} +#endif + + +/* ********************************************************************** + color balance + ********************************************************************** */ + +static StripColorBalance calc_cb(StripColorBalance * cb_) +{ + StripColorBalance cb = *cb_; + int c; + + if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) { + for (c = 0; c < 3; c++) { + cb.lift[c] = 1.0 - cb.lift[c]; + } + } else { + for (c = 0; c < 3; c++) { + cb.lift[c] = -(1.0 - cb.lift[c]); + } + } + if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) { + for (c = 0; c < 3; c++) { + if (cb.gain[c] != 0.0) { + cb.gain[c] = 1.0/cb.gain[c]; + } else { + cb.gain[c] = 1000000; /* should be enough :) */ + } + } + } + + if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) { + for (c = 0; c < 3; c++) { + if (cb.gamma[c] != 0.0) { + cb.gamma[c] = 1.0/cb.gamma[c]; + } else { + cb.gamma[c] = 1000000; /* should be enough :) */ + } + } + } + + return cb; +} + +static void make_cb_table_byte(float lift, float gain, float gamma, + unsigned char * table, float mul) +{ + int y; + + for (y = 0; y < 256; y++) { + float v = 1.0 * y / 255; + v *= gain; + v += lift; + v = pow(v, gamma); + v *= mul; + if ( v > 1.0) { + v = 1.0; + } else if (v < 0.0) { + v = 0.0; + } + table[y] = v * 255; + } + +} + +static void make_cb_table_float(float lift, float gain, float gamma, + float * table, float mul) +{ + int y; + + for (y = 0; y < 256; y++) { + float v = (float) y * 1.0 / 255.0; + v *= gain; + v += lift; + v = pow(v, gamma); + v *= mul; + table[y] = v; + } +} + +static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul) +{ + unsigned char cb_tab[3][256]; + int c; + unsigned char * p = (unsigned char*) se->ibuf->rect; + unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; + + StripColorBalance cb = calc_cb(seq->strip->color_balance); + + for (c = 0; c < 3; c++) { + make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], + cb_tab[c], mul); + } + + while (p < e) { + p[0] = cb_tab[0][p[0]]; + p[1] = cb_tab[1][p[1]]; + p[2] = cb_tab[2][p[2]]; + + p += 4; + } +} + +static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul) +{ + float cb_tab[4][256]; + int c,i; + unsigned char * p = (unsigned char*) se->ibuf->rect; + unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; + float * o; + StripColorBalance cb; + + imb_addrectfloatImBuf(se->ibuf); + + o = se->ibuf->rect_float; + + cb = calc_cb(seq->strip->color_balance); + + for (c = 0; c < 3; c++) { + make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], + cb_tab[c], mul); + } + + for (i = 0; i < 256; i++) { + cb_tab[3][i] = ((float)i)*(1.0f/255.0f); + } + + while (p < e) { + o[0] = cb_tab[0][p[0]]; + o[1] = cb_tab[1][p[1]]; + o[2] = cb_tab[2][p[2]]; + o[3] = cb_tab[3][p[3]]; + + p += 4; o += 4; + } +} + +static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul) +{ + float * p = se->ibuf->rect_float; + float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y; + StripColorBalance cb = calc_cb(seq->strip->color_balance); + + while (p < e) { + int c; + for (c = 0; c < 3; c++) { + p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], + cb.gamma[c]) * mul; + } + p += 4; + } +} + +static void color_balance(Sequence * seq, TStripElem* se, float mul) +{ + if (se->ibuf->rect_float) { + color_balance_float_float(seq, se, mul); + } else if(seq->flag & SEQ_MAKE_FLOAT) { + color_balance_byte_float(seq, se, mul); + } else { + color_balance_byte_byte(seq, se, mul); + } +} + +/* + input preprocessing for SEQ_IMAGE, SEQ_MOVIE and SEQ_SCENE + + Do all the things you can't really do afterwards using sequence effects + (read: before rescaling to render resolution has been done) + + Order is important! + + - Deinterlace + - Crop and transform in image source coordinate space + - Flip X + Flip Y (could be done afterwards, backward compatibility) + - Promote image to float data (affects pipeline operations afterwards) + - Color balance (is most efficient in the byte -> float + (future: half -> float should also work fine!) + case, if done on load, since we can use lookup tables) + - Premultiply + +*/ + +static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra) +{ + float mul; + + if ((seq->flag & SEQ_FILTERY) || + (seq->flag & SEQ_USE_CROP) || + (seq->flag & SEQ_USE_TRANSFORM) || + (seq->flag & SEQ_FLIPX) || + (seq->flag & SEQ_FLIPY) || + (seq->flag & SEQ_USE_COLOR_BALANCE) || + (seq->flag & SEQ_MAKE_PREMUL) || + (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) { + return TRUE; + } + + mul = seq->mul; + + if(seq->blend_mode == SEQ_BLEND_REPLACE && + !(seq->type & SEQ_EFFECT)) { + mul *= seq->blend_opacity / 100.0; + } + + if (mul != 1.0) { + return TRUE; + } + + return FALSE; +} + +static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra) +{ + float mul; + + seq->strip->orx= se->ibuf->x; + seq->strip->ory= se->ibuf->y; + + if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) { + IMB_filtery(se->ibuf); + } + + if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) { + StripCrop c; + StripTransform t; + int sx,sy,dx,dy; + + memset(&c, 0, sizeof(StripCrop)); + memset(&t, 0, sizeof(StripTransform)); + + if(seq->flag & SEQ_USE_CROP && seq->strip->crop) { + c = *seq->strip->crop; + } + if(seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) { + t = *seq->strip->transform; + } + + sx = se->ibuf->x - c.left - c.right; + sy = se->ibuf->y - c.top - c.bottom; + dx = sx; + dy = sy; + + if (seq->flag & SEQ_USE_TRANSFORM) { + dx = scene->r.xsch; + dy = scene->r.ysch; + } + + if (c.top + c.bottom >= se->ibuf->y || + c.left + c.right >= se->ibuf->x || + t.xofs >= dx || t.yofs >= dy) { + make_black_ibuf(se->ibuf); + } else { + ImBuf * i; + + if (se->ibuf->rect_float) { + i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0); + } else { + i = IMB_allocImBuf(dx, dy,32, IB_rect, 0); + } + + IMB_rectcpy(i, se->ibuf, + t.xofs, t.yofs, + c.left, c.bottom, + sx, sy); + + IMB_freeImBuf(se->ibuf); + + se->ibuf = i; + } + } + + if(seq->flag & SEQ_FLIPX) { + IMB_flipx(se->ibuf); + } + if(seq->flag & SEQ_FLIPY) { + IMB_flipy(se->ibuf); + } + + if(seq->mul == 0.0) { + seq->mul = 1.0; + } + + mul = seq->mul; + + if(seq->blend_mode == SEQ_BLEND_REPLACE) { + mul *= seq->blend_opacity / 100.0; + } + + if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) { + color_balance(seq, se, mul); + mul = 1.0; + } + + if(seq->flag & SEQ_MAKE_FLOAT) { + if (!se->ibuf->rect_float) { + IMB_float_from_rect(se->ibuf); + } + if (se->ibuf->rect) { + imb_freerectImBuf(se->ibuf); + } + } + + if(mul != 1.0) { + multibuf(se->ibuf, mul); + } + + if(seq->flag & SEQ_MAKE_PREMUL) { + if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) { + converttopremul(se->ibuf); + } + } + + + if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) { + if(scene->r.mode & R_OSA) { + IMB_scaleImBuf(se->ibuf, + (short)seqrectx, (short)seqrecty); + } else { + IMB_scalefastImBuf(se->ibuf, + (short)seqrectx, (short)seqrecty); + } + } +} + +/* test if image too small or discarded from cache: reload */ + +static void test_and_auto_discard_ibuf(TStripElem * se) +{ + if (se->ibuf) { + if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty + || !(se->ibuf->rect || se->ibuf->rect_float)) { + IMB_freeImBuf(se->ibuf); + + se->ibuf= 0; + se->ok= STRIPELEM_OK; + } + } + if (se->ibuf_comp) { + if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty + || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) { + IMB_freeImBuf(se->ibuf_comp); + + se->ibuf_comp = 0; + } + } +} + +static void test_and_auto_discard_ibuf_stills(Strip * strip) +{ + if (strip->ibuf_startstill) { + if (!strip->ibuf_startstill->rect && + !strip->ibuf_startstill->rect_float) { + IMB_freeImBuf(strip->ibuf_startstill); + strip->ibuf_startstill = 0; + } + } + if (strip->ibuf_endstill) { + if (!strip->ibuf_endstill->rect && + !strip->ibuf_endstill->rect_float) { + IMB_freeImBuf(strip->ibuf_endstill); + strip->ibuf_endstill = 0; + } + } +} + +static void copy_from_ibuf_still(Sequence * seq, TStripElem * se) +{ + if (!se->ibuf) { + if (se->nr == 0 && seq->strip->ibuf_startstill) { + IMB_cache_limiter_touch(seq->strip->ibuf_startstill); + + se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill); + } + if (se->nr == seq->len - 1 + && (seq->len != 1) + && seq->strip->ibuf_endstill) { + IMB_cache_limiter_touch(seq->strip->ibuf_endstill); + + se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill); + } + } +} + +static void copy_to_ibuf_still(Sequence * seq, TStripElem * se) +{ + if (se->ibuf) { + if (se->nr == 0) { + seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf); + + IMB_cache_limiter_insert(seq->strip->ibuf_startstill); + IMB_cache_limiter_touch(seq->strip->ibuf_startstill); + } + if (se->nr == seq->len - 1 && seq->len != 1) { + seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf); + + IMB_cache_limiter_insert(seq->strip->ibuf_endstill); + IMB_cache_limiter_touch(seq->strip->ibuf_endstill); + } + } +} + +static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown) +{ + Sequence* seq_arr[MAXSEQ+1]; + int i; + TStripElem* se = 0; + + evaluate_seq_frame_gen(seq_arr, seqbasep, cfra); + + for (i = 0; i < MAXSEQ; i++) { + if (!video_seq_is_rendered(seq_arr[i])) { + continue; + } + se = give_tstripelem(seq_arr[i], cfra); + if (se) { + if (se->ibuf) { + IMB_freeImBuf(se->ibuf); + + se->ibuf= 0; + se->ok= STRIPELEM_OK; + } + + if (se->ibuf_comp) { + IMB_freeImBuf(se->ibuf_comp); + + se->ibuf_comp = 0; + } + } + } + +} + +static void check_limiter_refcount(const char * func, TStripElem *se) +{ + if (se && se->ibuf) { + int refcount = IMB_cache_limiter_get_refcount(se->ibuf); + if (refcount != 1) { + /* can happen on complex pipelines */ + if (refcount > 1 && (G.f & G_DEBUG) == 0) { + return; + } + + fprintf(stderr, + "sequencer: (ibuf) %s: " + "suspicious memcache " + "limiter refcount: %d\n", func, refcount); + } + } +} + +static void check_limiter_refcount_comp(const char * func, TStripElem *se) +{ + if (se && se->ibuf_comp) { + int refcount = IMB_cache_limiter_get_refcount(se->ibuf_comp); + if (refcount != 1) { + /* can happen on complex pipelines */ + if (refcount > 1 && (G.f & G_DEBUG) == 0) { + return; + } + fprintf(stderr, + "sequencer: (ibuf comp) %s: " + "suspicious memcache " + "limiter refcount: %d\n", func, refcount); + } + } +} + +static TStripElem* do_build_seq_array_recursively(Scene *scene, + ListBase *seqbasep, int cfra, int chanshown, int render_size); + +static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, + int build_proxy_run, int render_size) +{ + char name[FILE_MAXDIR+FILE_MAXFILE]; + int use_limiter = TRUE; + + test_and_auto_discard_ibuf(se); + test_and_auto_discard_ibuf_stills(seq->strip); + + if(seq->type == SEQ_META) { + TStripElem * meta_se = 0; + int use_preprocess = FALSE; + use_limiter = FALSE; + + if (!build_proxy_run && se->ibuf == 0) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + if (se->ibuf) { + use_limiter = TRUE; + use_preprocess = TRUE; + } + } + + if(!se->ibuf && seq->seqbase.first) { + meta_se = do_build_seq_array_recursively(scene, + &seq->seqbase, seq->start + se->nr, 0, + render_size); + + check_limiter_refcount("do_build_seq_ibuf: for META", meta_se); + } + + se->ok = STRIPELEM_OK; + + if(!se->ibuf && meta_se) { + se->ibuf = meta_se->ibuf_comp; + if(se->ibuf && + (!input_have_to_preprocess(scene, seq, se, cfra) || + build_proxy_run)) { + IMB_refImBuf(se->ibuf); + if (build_proxy_run) { + IMB_cache_limiter_unref(se->ibuf); + } + } else if (se->ibuf) { + struct ImBuf * i = IMB_dupImBuf(se->ibuf); + + IMB_cache_limiter_unref(se->ibuf); + + se->ibuf = i; + + use_limiter = TRUE; + use_preprocess = TRUE; + } + } else if (se->ibuf) { + use_limiter = TRUE; + } + if (meta_se) { + free_metastrip_imbufs( + &seq->seqbase, seq->start + se->nr, 0); + } + + if (use_preprocess) { + input_preprocess(scene, seq, se, cfra); + } + } else if(seq->type & SEQ_EFFECT) { + int use_preprocess = FALSE; + /* should the effect be recalculated? */ + + if (!build_proxy_run && se->ibuf == 0) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + if (se->ibuf) { + use_preprocess = TRUE; + } + } + + if(se->ibuf == 0) { + /* if any inputs are rectfloat, output is float too */ + if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) || + (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float) || + (se->se3 && se->se3->ibuf && se->se3->ibuf->rect_float)) + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); + else + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + + do_effect(scene, cfra, seq, se); + if (input_have_to_preprocess(scene, seq, se, cfra) && + !build_proxy_run) { + if ((se->se1 && (se->ibuf == se->se1->ibuf)) || + (se->se2 && (se->ibuf == se->se2->ibuf))) { + struct ImBuf * i + = IMB_dupImBuf(se->ibuf); + + IMB_freeImBuf(se->ibuf); + + se->ibuf = i; + } + use_preprocess = TRUE; + } + } + if (use_preprocess) { + input_preprocess(scene, seq, se, cfra); + } + } else if(seq->type == SEQ_IMAGE) { + if(se->ok == STRIPELEM_OK && se->ibuf == 0) { + StripElem * s_elem = give_stripelem(seq, cfra); + BLI_join_dirfile(name, seq->strip->dir, s_elem->name); + BLI_convertstringcode(name, G.sce); + BLI_convertstringframe(name, scene->r.cfra); + if (!build_proxy_run) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + } + copy_from_ibuf_still(seq, se); + + if (!se->ibuf) { + se->ibuf= IMB_loadiffname( + name, IB_rect); + /* we don't need both (speed reasons)! */ + if (se->ibuf && + se->ibuf->rect_float && se->ibuf->rect) { + imb_freerectImBuf(se->ibuf); + } + + copy_to_ibuf_still(seq, se); + } + + if(se->ibuf == 0) { + se->ok = STRIPELEM_FAILED; + } else if (!build_proxy_run) { + input_preprocess(scene, seq, se, cfra); + } + } + } else if(seq->type == SEQ_MOVIE) { + if(se->ok == STRIPELEM_OK && se->ibuf==0) { + if(!build_proxy_run) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + } + copy_from_ibuf_still(seq, se); + + if (se->ibuf == 0) { + if(seq->anim==0) { + BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name); + BLI_convertstringcode(name, G.sce); + BLI_convertstringframe(name, scene->r.cfra); + + seq->anim = openanim( + name, IB_rect | + ((seq->flag & SEQ_FILTERY) + ? IB_animdeinterlace : 0)); + } + if(seq->anim) { + IMB_anim_set_preseek(seq->anim, seq->anim_preseek); + se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs); + /* we don't need both (speed reasons)! */ + if (se->ibuf + && se->ibuf->rect_float + && se->ibuf->rect) { + imb_freerectImBuf(se->ibuf); + } + + } + copy_to_ibuf_still(seq, se); + } + + if(se->ibuf == 0) { + se->ok = STRIPELEM_FAILED; + } else if (!build_proxy_run) { + input_preprocess(scene, seq, se, cfra); + } + } + } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions + Scene *sce= seq->scene;// *oldsce= scene; + Render *re; + RenderResult rres; + char scenename[64]; + int have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first; + int sce_valid =sce && (sce->camera || have_seq); + + if (se->ibuf == NULL && sce_valid && !build_proxy_run) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + if (se->ibuf) { + input_preprocess(scene, seq, se, cfra); + } + } + + if (se->ibuf == NULL && sce_valid) { + copy_from_ibuf_still(seq, se); + if (se->ibuf) { + input_preprocess(scene, seq, se, cfra); + } + } + + if (!sce_valid) { + se->ok = STRIPELEM_FAILED; + } else if (se->ibuf==NULL && sce_valid) { + int oldcfra; + /* Hack! This function can be called from do_render_seq(), in that case + the seq->scene can already have a Render initialized with same name, + so we have to use a default name. (compositor uses scene name to + find render). + However, when called from within the UI (image preview in sequencer) + we do want to use scene Render, that way the render result is defined + for display in render/imagewindow + + Hmm, don't see, why we can't do that all the time, + and since G.rendering is uhm, gone... (Peter) + */ + + int rendering = 1; + int doseq; + + oldcfra = seq->scene->r.cfra; + + if(rendering) { + BLI_strncpy(scenename, sce->id.name+2, 64); + strcpy(sce->id.name+2, " do_build_seq_ibuf"); + } + re= RE_NewRender(sce->id.name); + + /* prevent eternal loop */ + doseq= scene->r.scemode & R_DOSEQ; + scene->r.scemode &= ~R_DOSEQ; + + RE_BlenderFrame(re, sce, + seq->sfra+se->nr+seq->anim_startofs); + + if(rendering) + BLI_strncpy(sce->id.name+2, scenename, 64); + + RE_AcquireResultImage(re, &rres); + + if(rres.rectf) { + se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); + memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty); + if(rres.rectz) { + addzbuffloatImBuf(se->ibuf); + memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty); + } + } else if (rres.rect32) { + se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); + memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); + } + + RE_ReleaseResultImage(re); + + // BIF_end_render_callbacks(); + + /* restore */ + scene->r.scemode |= doseq; + + seq->scene->r.cfra = oldcfra; + + copy_to_ibuf_still(seq, se); + + if (!build_proxy_run) { + if(se->ibuf == NULL) { + se->ok = STRIPELEM_FAILED; + } else { + input_preprocess(scene, seq, se, cfra); + } + } + + } + } + if (!build_proxy_run) { + if (se->ibuf && use_limiter) { + IMB_cache_limiter_insert(se->ibuf); + IMB_cache_limiter_ref(se->ibuf); + IMB_cache_limiter_touch(se->ibuf); + } + } +} + +static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra, int render_size); + +static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra, int render_size) +{ + float fac, facf; + struct SeqEffectHandle sh = get_sequence_effect(seq); + int early_out; + FCurve *fcu= NULL; + + se->se1 = 0; + se->se2 = 0; + se->se3 = 0; + + if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { + sh.get_default_fac(seq, cfra, &fac, &facf); + if( scene->r.mode & R_FIELDS ); else facf= fac; + } else { + fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, + "effect_fader", 0); + if (fcu) { + fac = facf = evaluate_fcurve(fcu, cfra); + if( scene->r.mode & R_FIELDS ) { + facf = evaluate_fcurve(fcu, cfra + 0.5); + } + } else { + fac = facf = seq->effect_fader; + } + } + + early_out = sh.early_out(seq, fac, facf); + switch (early_out) { + case -1: + /* no input needed */ + break; + case 0: + se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size); + se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size); + if (seq->seq3) { + se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra, render_size); + } + break; + case 1: + se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size); + break; + case 2: + se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size); + break; + } + + + do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size); + + /* children are not needed anymore ... */ + + if (se->se1 && se->se1->ibuf) { + IMB_cache_limiter_unref(se->se1->ibuf); + } + if (se->se2 && se->se2->ibuf) { + IMB_cache_limiter_unref(se->se2->ibuf); + } + if (se->se3 && se->se3->ibuf) { + IMB_cache_limiter_unref(se->se3->ibuf); + } + check_limiter_refcount("do_effect_seq_recursively", se); +} + +static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + TStripElem *se; + + se = give_tstripelem(seq, cfra); + + if(se) { + if (seq->type & SEQ_EFFECT) { + do_effect_seq_recursively(scene, seq, se, cfra, render_size); + } else { + do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size); + } + } + return se; +} + +/* FIXME: + +If cfra was float throughout blender (especially in the render +pipeline) one could even _render_ with subframe precision +instead of faking using the blend code below... + +*/ + +static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + SpeedControlVars * s = (SpeedControlVars *)seq->effectdata; + int nr = cfra - seq->start; + float f_cfra; + int cfra_left; + int cfra_right; + TStripElem * se = 0; + TStripElem * se1 = 0; + TStripElem * se2 = 0; + + sequence_effect_speed_rebuild_map(scene, seq, 0); + + f_cfra = seq->start + s->frameMap[nr]; + + cfra_left = (int) floor(f_cfra); + cfra_right = (int) ceil(f_cfra); + + se = give_tstripelem(seq, cfra); + + if (!se) { + return se; + } + + if (cfra_left == cfra_right || + (s->flags & SEQ_SPEED_BLEND) == 0) { + test_and_auto_discard_ibuf(se); + + if (se->ibuf == NULL) { + se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size); + + if((se1 && se1->ibuf && se1->ibuf->rect_float)) + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); + else + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + + if (se1 == 0 || se1->ibuf == 0) { + make_black_ibuf(se->ibuf); + } else { + if (se->ibuf != se1->ibuf) { + if (se->ibuf) { + IMB_freeImBuf(se->ibuf); + } + + se->ibuf = se1->ibuf; + IMB_refImBuf(se->ibuf); + } + } + } + } else { + struct SeqEffectHandle sh; + + if(se->ibuf) { + if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty + || !(se->ibuf->rect || se->ibuf->rect_float)) { + IMB_freeImBuf(se->ibuf); + se->ibuf= 0; + } + } + + if (se->ibuf == NULL) { + se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size); + se2 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_right, render_size); + + if((se1 && se1->ibuf && se1->ibuf->rect_float)) + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); + else + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + + if (!se1 || !se2) { + make_black_ibuf(se->ibuf); + } else { + sh = get_sequence_effect(seq); + + sh.execute(scene, seq, cfra, + f_cfra - (float) cfra_left, + f_cfra - (float) cfra_left, + se->ibuf->x, se->ibuf->y, + se1->ibuf, se2->ibuf, 0, se->ibuf); + } + } + + } + + /* caller expects this to be referenced, so do it! */ + if (se->ibuf) { + IMB_cache_limiter_insert(se->ibuf); + IMB_cache_limiter_ref(se->ibuf); + IMB_cache_limiter_touch(se->ibuf); + } + + /* children are no longer needed */ + if (se1 && se1->ibuf) + IMB_cache_limiter_unref(se1->ibuf); + if (se2 && se2->ibuf) + IMB_cache_limiter_unref(se2->ibuf); + + check_limiter_refcount("do_handle_speed_effect", se); + + return se; +} + +/* + * build all ibufs recursively + * + * if successfull, the returned TStripElem contains the (referenced!) imbuf + * that means: you _must_ call + * + * IMB_cache_limiter_unref(rval); + * + * if rval != 0 + * + */ + +static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + TStripElem *se; + if (seq->type == SEQ_SPEED) { + se = do_handle_speed_effect(scene, seq, cfra, render_size); + } else { + se = do_build_seq_recursively_impl(scene, seq, cfra, render_size); + } + + check_limiter_refcount("do_build_seq_recursively", se); + + return se; +} + +static TStripElem* do_build_seq_array_recursively(Scene *scene, + ListBase *seqbasep, int cfra, int chanshown, int render_size) +{ + Sequence* seq_arr[MAXSEQ+1]; + int count; + int i; + TStripElem* se = 0; + + count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr); + + if (!count) { + return 0; + } + + se = give_tstripelem(seq_arr[count - 1], cfra); + + if (!se) { + return 0; + } + + test_and_auto_discard_ibuf(se); + + if (se->ibuf_comp != 0) { + IMB_cache_limiter_insert(se->ibuf_comp); + IMB_cache_limiter_ref(se->ibuf_comp); + IMB_cache_limiter_touch(se->ibuf_comp); + return se; + } + + + if(count == 1) { + se = do_build_seq_recursively(scene, seq_arr[0], cfra, render_size); + if (se->ibuf) { + se->ibuf_comp = se->ibuf; + IMB_refImBuf(se->ibuf_comp); + } + return se; + } + + + for (i = count - 1; i >= 0; i--) { + int early_out; + Sequence * seq = seq_arr[i]; + struct SeqEffectHandle sh; + float facf; + + se = give_tstripelem(seq, cfra); + + test_and_auto_discard_ibuf(se); + + if (se->ibuf_comp != 0) { + break; + } + if (seq->blend_mode == SEQ_BLEND_REPLACE) { + do_build_seq_recursively(scene, seq, cfra, render_size); + if (se->ibuf) { + se->ibuf_comp = se->ibuf; + IMB_refImBuf(se->ibuf); + } else { + se->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + IMB_cache_limiter_insert(se->ibuf_comp); + IMB_cache_limiter_ref(se->ibuf_comp); + IMB_cache_limiter_touch(se->ibuf_comp); + } + break; + } + + sh = get_sequence_blend(seq); + + facf = seq->blend_opacity / 100.0; + + early_out = sh.early_out(seq, facf, facf); + + switch (early_out) { + case -1: + case 2: + do_build_seq_recursively(scene, seq, cfra, render_size); + if (se->ibuf) { + se->ibuf_comp = se->ibuf; + IMB_refImBuf(se->ibuf_comp); + } else { + se->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + IMB_cache_limiter_insert(se->ibuf_comp); + IMB_cache_limiter_ref(se->ibuf_comp); + IMB_cache_limiter_touch(se->ibuf_comp); + } + break; + case 1: + if (i == 0) { + se->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + IMB_cache_limiter_insert(se->ibuf_comp); + IMB_cache_limiter_ref(se->ibuf_comp); + IMB_cache_limiter_touch(se->ibuf_comp); + } + break; + case 0: + do_build_seq_recursively(scene, seq, cfra, render_size); + if (!se->ibuf) { + se->ibuf = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + IMB_cache_limiter_insert(se->ibuf); + IMB_cache_limiter_ref(se->ibuf); + IMB_cache_limiter_touch(se->ibuf); + } + if (i == 0) { + se->ibuf_comp = se->ibuf; + IMB_refImBuf(se->ibuf_comp); + } + break; + } + + if (se->ibuf_comp) { + break; + } + } + + i++; + + for (; i < count; i++) { + Sequence * seq = seq_arr[i]; + struct SeqEffectHandle sh = get_sequence_blend(seq); + TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra); + TStripElem* se2 = give_tstripelem(seq_arr[i], cfra); + + float facf = seq->blend_opacity / 100.0; + + int early_out = sh.early_out(seq, facf, facf); + switch (early_out) { + case 0: { + int x= se2->ibuf->x; + int y= se2->ibuf->y; + int swap_input = FALSE; + + if (se1->ibuf_comp->rect_float || + se2->ibuf->rect_float) { + se2->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rectfloat, 0); + } else { + se2->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + } + + + if (!se1->ibuf_comp->rect_float && + se2->ibuf_comp->rect_float) { + IMB_float_from_rect(se1->ibuf_comp); + } + if (!se2->ibuf->rect_float && + se2->ibuf_comp->rect_float) { + IMB_float_from_rect(se2->ibuf); + } + + if (!se1->ibuf_comp->rect && + !se2->ibuf_comp->rect_float) { + IMB_rect_from_float(se1->ibuf_comp); + } + if (!se2->ibuf->rect && + !se2->ibuf_comp->rect_float) { + IMB_rect_from_float(se2->ibuf); + } + + /* bad hack, to fix crazy input ordering of + those two effects */ + + if (seq->blend_mode == SEQ_ALPHAOVER || + seq->blend_mode == SEQ_ALPHAUNDER || + seq->blend_mode == SEQ_OVERDROP) { + swap_input = TRUE; + } + + if (swap_input) { + sh.execute(scene, seq, cfra, + facf, facf, x, y, + se2->ibuf, se1->ibuf_comp, 0, + se2->ibuf_comp); + } else { + sh.execute(scene, seq, cfra, + facf, facf, x, y, + se1->ibuf_comp, se2->ibuf, 0, + se2->ibuf_comp); + } + + IMB_cache_limiter_insert(se2->ibuf_comp); + IMB_cache_limiter_ref(se2->ibuf_comp); + IMB_cache_limiter_touch(se2->ibuf_comp); + + IMB_cache_limiter_unref(se1->ibuf_comp); + IMB_cache_limiter_unref(se2->ibuf); + + break; + } + case 1: { + se2->ibuf_comp = se1->ibuf; + IMB_refImBuf(se2->ibuf_comp); + + break; + } + } + se = se2; + } + + return se; +} + +/* + * returned ImBuf is refed! + * you have to unref after usage! + */ + +static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +{ + Editing *ed= seq_give_editing(scene, FALSE); + int count; + ListBase *seqbasep; + TStripElem *se; + + + if(ed==NULL) return NULL; + + count = BLI_countlist(&ed->metastack); + if((chanshown < 0) && (count > 0)) { + count = MAX2(count + chanshown, 0); + seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep; + } else { + seqbasep= ed->seqbasep; + } + + seqrectx= rectx; /* bad bad global! */ + seqrecty= recty; + + se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown, render_size); + + if(!se) { + return 0; + } + + check_limiter_refcount_comp("give_ibuf_seq_impl", se); + + return se->ibuf_comp; +} + +ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq) +{ + TStripElem* se; + + seqrectx= rectx; /* bad bad global! */ + seqrecty= recty; + + se = do_build_seq_recursively(scene, seq, cfra, render_size); + + if(!se) { + return 0; + } + + check_limiter_refcount("give_ibuf_seq_direct", se); + + if (se->ibuf) { + IMB_cache_limiter_unref(se->ibuf); + } + + return se->ibuf; +} + +ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +{ + ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown, render_size); + + if (i) { + IMB_cache_limiter_unref(i); + } + return i; +} + +#if 0 +/* check used when we need to change seq->blend_mode but not to effect or audio strips */ +static int seq_can_blend(Sequence *seq) +{ + if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { + return 1; + } else { + return 0; + } +} +#endif + +/* *********************** threading api ******************* */ + +static ListBase running_threads; +static ListBase prefetch_wait; +static ListBase prefetch_done; + +static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t wakeup_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER; + +//static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER; +//static pthread_cond_t prefetch_ready_cond = PTHREAD_COND_INITIALIZER; + +static pthread_mutex_t frame_done_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t frame_done_cond = PTHREAD_COND_INITIALIZER; + +static volatile int seq_thread_shutdown = FALSE; +static volatile int seq_last_given_monoton_cfra = 0; +static int monoton_cfra = 0; + +typedef struct PrefetchThread { + struct PrefetchThread *next, *prev; + + Scene *scene; + struct PrefetchQueueElem *current; + pthread_t pthread; + int running; + +} PrefetchThread; + +typedef struct PrefetchQueueElem { + struct PrefetchQueueElem *next, *prev; + + int rectx; + int recty; + int cfra; + int chanshown; + int render_size; + + int monoton_cfra; + + struct ImBuf * ibuf; +} PrefetchQueueElem; + +#if 0 +static void *seq_prefetch_thread(void * This_) +{ + PrefetchThread * This = This_; + + while (!seq_thread_shutdown) { + PrefetchQueueElem *e; + int s_last; + + pthread_mutex_lock(&queue_lock); + e = prefetch_wait.first; + if (e) { + BLI_remlink(&prefetch_wait, e); + } + s_last = seq_last_given_monoton_cfra; + + This->current = e; + + pthread_mutex_unlock(&queue_lock); + + if (!e) { + pthread_mutex_lock(&prefetch_ready_lock); + + This->running = FALSE; + + pthread_cond_signal(&prefetch_ready_cond); + pthread_mutex_unlock(&prefetch_ready_lock); + + pthread_mutex_lock(&wakeup_lock); + if (!seq_thread_shutdown) { + pthread_cond_wait(&wakeup_cond, &wakeup_lock); + } + pthread_mutex_unlock(&wakeup_lock); + continue; + } + + This->running = TRUE; + + if (e->cfra >= s_last) { + e->ibuf = give_ibuf_seq_impl(This->scene, + e->rectx, e->recty, e->cfra, e->chanshown, + e->render_size); + } + + pthread_mutex_lock(&queue_lock); + + BLI_addtail(&prefetch_done, e); + + for (e = prefetch_wait.first; e; e = e->next) { + if (s_last > e->monoton_cfra) { + BLI_remlink(&prefetch_wait, e); + MEM_freeN(e); + } + } + + for (e = prefetch_done.first; e; e = e->next) { + if (s_last > e->monoton_cfra) { + if (e->ibuf) { + IMB_cache_limiter_unref(e->ibuf); + } + BLI_remlink(&prefetch_done, e); + MEM_freeN(e); + } + } + + pthread_mutex_unlock(&queue_lock); + + pthread_mutex_lock(&frame_done_lock); + pthread_cond_signal(&frame_done_cond); + pthread_mutex_unlock(&frame_done_lock); + } + return 0; +} + +static void seq_start_threads(Scene *scene) +{ + int i; + + running_threads.first = running_threads.last = NULL; + prefetch_wait.first = prefetch_wait.last = NULL; + prefetch_done.first = prefetch_done.last = NULL; + + seq_thread_shutdown = FALSE; + seq_last_given_monoton_cfra = monoton_cfra = 0; + + /* since global structures are modified during the processing + of one frame, only one render thread is currently possible... + + (but we code, in the hope, that we can remove this restriction + soon...) + */ + + fprintf(stderr, "SEQ-THREAD: seq_start_threads\n"); + + for (i = 0; i < 1; i++) { + PrefetchThread *t = MEM_callocN(sizeof(PrefetchThread), "prefetch_thread"); + t->scene= scene; + t->running = TRUE; + BLI_addtail(&running_threads, t); + + pthread_create(&t->pthread, NULL, seq_prefetch_thread, t); + } + + /* init malloc mutex */ + BLI_init_threads(0, 0, 0); +} + +static void seq_stop_threads() +{ + PrefetchThread *tslot; + PrefetchQueueElem *e; + + fprintf(stderr, "SEQ-THREAD: seq_stop_threads()\n"); + + if (seq_thread_shutdown) { + fprintf(stderr, "SEQ-THREAD: ... already stopped\n"); + return; + } + + pthread_mutex_lock(&wakeup_lock); + + seq_thread_shutdown = TRUE; + + pthread_cond_broadcast(&wakeup_cond); + pthread_mutex_unlock(&wakeup_lock); + + for(tslot = running_threads.first; tslot; tslot= tslot->next) { + pthread_join(tslot->pthread, NULL); + } + + + for (e = prefetch_wait.first; e; e = e->next) { + BLI_remlink(&prefetch_wait, e); + MEM_freeN(e); + } + + for (e = prefetch_done.first; e; e = e->next) { + if (e->ibuf) { + IMB_cache_limiter_unref(e->ibuf); + } + BLI_remlink(&prefetch_done, e); + MEM_freeN(e); + } + + BLI_freelistN(&running_threads); + + /* deinit malloc mutex */ + BLI_end_threads(0); +} +#endif + +void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, + int render_size) +{ + PrefetchQueueElem *e; + if (seq_thread_shutdown) { + return; + } + + e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem"); + e->rectx = rectx; + e->recty = recty; + e->cfra = cfra; + e->chanshown = chanshown; + e->render_size = render_size; + e->monoton_cfra = monoton_cfra++; + + pthread_mutex_lock(&queue_lock); + BLI_addtail(&prefetch_wait, e); + pthread_mutex_unlock(&queue_lock); + + pthread_mutex_lock(&wakeup_lock); + pthread_cond_signal(&wakeup_cond); + pthread_mutex_unlock(&wakeup_lock); +} + +#if 0 +static void seq_wait_for_prefetch_ready() +{ + PrefetchThread *tslot; + + if (seq_thread_shutdown) { + return; + } + + fprintf(stderr, "SEQ-THREAD: rendering prefetch frames...\n"); + + pthread_mutex_lock(&prefetch_ready_lock); + + for(;;) { + for(tslot = running_threads.first; tslot; tslot= tslot->next) { + if (tslot->running) { + break; + } + } + if (!tslot) { + break; + } + pthread_cond_wait(&prefetch_ready_cond, &prefetch_ready_lock); + } + + pthread_mutex_unlock(&prefetch_ready_lock); + + fprintf(stderr, "SEQ-THREAD: prefetch done\n"); +} +#endif + +ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +{ + PrefetchQueueElem *e = NULL; + int found_something = FALSE; + + if (seq_thread_shutdown) { + return give_ibuf_seq(scene, rectx, recty, cfra, chanshown, render_size); + } + + while (!e) { + int success = FALSE; + pthread_mutex_lock(&queue_lock); + + for (e = prefetch_done.first; e; e = e->next) { + if (cfra == e->cfra && + chanshown == e->chanshown && + rectx == e->rectx && + recty == e->recty && + render_size == e->render_size) { + success = TRUE; + found_something = TRUE; + break; + } + } + + if (!e) { + for (e = prefetch_wait.first; e; e = e->next) { + if (cfra == e->cfra && + chanshown == e->chanshown && + rectx == e->rectx && + recty == e->recty && + render_size == e->render_size) { + found_something = TRUE; + break; + } + } + } + + if (!e) { + PrefetchThread *tslot; + + for(tslot = running_threads.first; + tslot; tslot= tslot->next) { + if (tslot->current && + cfra == tslot->current->cfra && + chanshown == tslot->current->chanshown && + rectx == tslot->current->rectx && + recty == tslot->current->recty && + render_size== tslot->current->render_size){ + found_something = TRUE; + break; + } + } + } + + /* e->ibuf is unrefed by render thread on next round. */ + + if (e) { + seq_last_given_monoton_cfra = e->monoton_cfra; + } + + pthread_mutex_unlock(&queue_lock); + + if (!success) { + e = NULL; + + if (!found_something) { + fprintf(stderr, + "SEQ-THREAD: Requested frame " + "not in queue ???\n"); + break; + } + pthread_mutex_lock(&frame_done_lock); + pthread_cond_wait(&frame_done_cond, &frame_done_lock); + pthread_mutex_unlock(&frame_done_lock); + } + } + + return e ? e->ibuf : 0; +} + +/* Functions to free imbuf and anim data on changes */ + +static void free_imbuf_strip_elem(TStripElem *se) +{ + if(se->ibuf) { + IMB_freeImBuf(se->ibuf); + } + if(se->ibuf_comp) { + IMB_freeImBuf(se->ibuf_comp); + } + se->ibuf_comp = 0; + se->ibuf= 0; + se->ok= STRIPELEM_OK; + se->se1= se->se2= se->se3= 0; +} + +static void free_anim_seq(Sequence *seq) +{ + if(seq->anim) { + IMB_free_anim(seq->anim); + seq->anim = 0; + } +} + +#if 0 +static void free_imbuf_seq_except(Scene *scene, int cfra) +{ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq; + TStripElem *se; + int a; + + if(ed==NULL) return; + + SEQ_BEGIN(ed, seq) { + if(seq->strip) { + TStripElem * curelem = give_tstripelem(seq, cfra); + + for(a = 0, se = seq->strip->tstripdata; + a < seq->strip->len && se; a++, se++) { + if(se != curelem) { + free_imbuf_strip_elem(se); + } + } + for(a = 0, se = seq->strip->tstripdata_startstill; + a < seq->strip->startstill && se; a++, se++) { + if(se != curelem) { + free_imbuf_strip_elem(se); + } + } + for(a = 0, se = seq->strip->tstripdata_endstill; + a < seq->strip->endstill && se; a++, se++) { + if(se != curelem) { + free_imbuf_strip_elem(se); + } + } + if(seq->strip->ibuf_startstill) { + IMB_freeImBuf(seq->strip->ibuf_startstill); + seq->strip->ibuf_startstill = 0; + } + + if(seq->strip->ibuf_endstill) { + IMB_freeImBuf(seq->strip->ibuf_endstill); + seq->strip->ibuf_endstill = 0; + } + + if(seq->type==SEQ_MOVIE) + if(seq->startdisp > cfra || seq->enddisp < cfra) + free_anim_seq(seq); + free_proxy_seq(seq); + } + } + SEQ_END +} +#endif + +void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage) +{ + Sequence *seq; + TStripElem *se; + int a; + + if (check_mem_usage) { + /* Let the cache limitor take care of this (schlaile) */ + /* While render let's keep all memory available for render + (ton) + At least if free memory is tight... + This can make a big difference in encoding speed + (it is around 4 times(!) faster, if we do not waste time + on freeing _all_ buffers every time on long timelines...) + (schlaile) + */ + + uintptr_t mem_in_use; + uintptr_t mmap_in_use; + uintptr_t max; + + mem_in_use= MEM_get_memory_in_use(); + mmap_in_use= MEM_get_mapped_memory_in_use(); + max = MEM_CacheLimiter_get_maximum(); + + if (max == 0 || mem_in_use + mmap_in_use <= max) { + return; + } + } + + + for(seq= seqbase->first; seq; seq= seq->next) { + if(seq->strip) { + for(a = 0, se = seq->strip->tstripdata; + a < seq->strip->len && se; a++, se++) { + free_imbuf_strip_elem(se); + } + for(a = 0, se = seq->strip->tstripdata_startstill; + a < seq->strip->startstill && se; a++, se++) { + free_imbuf_strip_elem(se); + } + for(a = 0, se = seq->strip->tstripdata_endstill; + a < seq->strip->endstill && se; a++, se++) { + free_imbuf_strip_elem(se); + } + if(seq->strip->ibuf_startstill) { + IMB_freeImBuf(seq->strip->ibuf_startstill); + seq->strip->ibuf_startstill = 0; + } + + if(seq->strip->ibuf_endstill) { + IMB_freeImBuf(seq->strip->ibuf_endstill); + seq->strip->ibuf_endstill = 0; + } + + if(seq->type==SEQ_MOVIE) + free_anim_seq(seq); + if(seq->type==SEQ_SPEED) { + sequence_effect_speed_rebuild_map(scene, seq, 1); + } + } + if(seq->type==SEQ_META) { + free_imbuf_seq(scene, &seq->seqbase, FALSE); + } + if(seq->type==SEQ_SCENE) { + /* FIXME: recurs downwards, + but do recurs protection somehow! */ + } + } + +} + +static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change) +{ + Sequence *subseq; + int a, free_imbuf = 0; + TStripElem *se; + + /* recurs downwards to see if this seq depends on the changed seq */ + + if(seq == NULL) + return 0; + + if(seq == changed_seq) + free_imbuf = 1; + + for(subseq=seq->seqbase.first; subseq; subseq=subseq->next) + if(update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change)) + free_imbuf = TRUE; + + if(seq->seq1) + if(update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change)) + free_imbuf = TRUE; + if(seq->seq2 && (seq->seq2 != seq->seq1)) + if(update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change)) + free_imbuf = TRUE; + if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) + if(update_changed_seq_recurs(scene, seq->seq3, changed_seq, len_change, ibuf_change)) + free_imbuf = TRUE; + + if(free_imbuf) { + if(ibuf_change) { + se= seq->strip->tstripdata; + if (se) { + for(a=0; alen; a++, se++) + free_imbuf_strip_elem(se); + } + + if(seq->type == SEQ_MOVIE) + free_anim_seq(seq); + if(seq->type == SEQ_SPEED) { + sequence_effect_speed_rebuild_map(scene, seq, 1); + } + } + + if(len_change) + calc_sequence(seq); + } + + return free_imbuf; +} + +void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change) +{ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq; + + if (ed==NULL) return; + + for (seq=ed->seqbase.first; seq; seq=seq->next) + update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change); +} + +#if 0 // XXX from 2.4x, needs updating +void free_imbuf_seq() +{ + Scene * sce = G.main->scene.first; + while(sce) { + free_imbuf_seq_editing(sce->ed); + sce= sce->id.next; + } +} +#endif + +#if 0 // XXX old animation system +static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) +{ + /* force update of all sequences with this ipo, on ipo changes */ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq; + + if(ed==NULL) return; + + SEQ_BEGIN(ed, seq) { + if(seq->ipo == ipo) { + update_changed_seq_and_deps(scene, seq, 0, 1); + if(seq->type == SEQ_SPEED) { + sequence_effect_speed_rebuild_map(seq, 1); + } + free_proxy_seq(seq); + } + } + SEQ_END +} +#endif + +/* seq funcs's for transforming internally + notice the difference between start/end and left/right. + + left and right are the bounds at which the sequence is rendered, +start and end are from the start and fixed length of the sequence. +*/ +int seq_tx_get_start(Sequence *seq) { + return seq->start; +} +int seq_tx_get_end(Sequence *seq) +{ + return seq->start+seq->len; +} + +int seq_tx_get_final_left(Sequence *seq, int metaclip) +{ + if (metaclip && seq->tmp) { + /* return the range clipped by the parents range */ + return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) ); + } else { + return (seq->start - seq->startstill) + seq->startofs; + } + +} +int seq_tx_get_final_right(Sequence *seq, int metaclip) +{ + if (metaclip && seq->tmp) { + /* return the range clipped by the parents range */ + return MIN2( seq_tx_get_final_right(seq, 0), seq_tx_get_final_right((Sequence *)seq->tmp, 1) ); + } else { + return ((seq->start+seq->len) + seq->endstill) - seq->endofs; + } +} + +void seq_tx_set_final_left(Sequence *seq, int val) +{ + if (val < (seq)->start) { + seq->startstill = abs(val - (seq)->start); + seq->startofs = 0; + } else { + seq->startofs = abs(val - (seq)->start); + seq->startstill = 0; + } +} + +void seq_tx_set_final_right(Sequence *seq, int val) +{ + if (val > (seq)->start + (seq)->len) { + seq->endstill = abs(val - (seq->start + (seq)->len)); + seq->endofs = 0; + } else { + seq->endofs = abs(val - ((seq)->start + (seq)->len)); + seq->endstill = 0; + } +} + +/* used so we can do a quick check for single image seq + since they work a bit differently to normal image seq's (during transform) */ +int check_single_seq(Sequence *seq) +{ + if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR)) + return 1; + else + return 0; +} + +/* use to impose limits when dragging/extending - so impossible situations dont happen + * Cant use the SEQ_LEFTSEL and SEQ_LEFTSEL directly because the strip may be in a metastrip */ +void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) +{ + if(leftflag) { + if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_final_right(seq, 0)) { + seq_tx_set_final_left(seq, seq_tx_get_final_right(seq, 0)-1); + } + + if (check_single_seq(seq)==0) { + if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_end(seq)) { + seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1); + } + + /* dosnt work now - TODO */ + /* + if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) { + int ofs; + ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0); + seq->start -= ofs; + seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs ); + }*/ + + } + } + + if(rightflag) { + if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_final_left(seq, 0)) { + seq_tx_set_final_right(seq, seq_tx_get_final_left(seq, 0)+1); + } + + if (check_single_seq(seq)==0) { + if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_start(seq)) { + seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1); + } + } + } + + /* sounds cannot be extended past their endpoints */ + if (seq->type == SEQ_SOUND) { + seq->startstill= 0; + seq->endstill= 0; + } +} + +void fix_single_seq(Sequence *seq) +{ + int left, start, offset; + if (!check_single_seq(seq)) + return; + + /* make sure the image is always at the start since there is only one, + adjusting its start should be ok */ + left = seq_tx_get_final_left(seq, 0); + start = seq->start; + if (start != left) { + offset = left - start; + seq_tx_set_final_left( seq, seq_tx_get_final_left(seq, 0) - offset ); + seq_tx_set_final_right( seq, seq_tx_get_final_right(seq, 0) - offset ); + seq->start += offset; + } +} + +int seq_tx_test(Sequence * seq) +{ + return (seq->type < SEQ_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0); +} + +static int seq_overlap(Sequence *seq1, Sequence *seq2) +{ + if(seq1 != seq2) + if(seq1->machine==seq2->machine) + if(((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0) + return 1; + + return 0; +} + +int seq_test_overlap(ListBase * seqbasep, Sequence *test) +{ + Sequence *seq; + + seq= seqbasep->first; + while(seq) { + if(seq_overlap(test, seq)) + return 1; + + seq= seq->next; + } + return 0; +} + + +static void seq_translate(Sequence *seq, int delta) +{ + seq->start += delta; + if(seq->type==SEQ_META) { + Sequence *seq_child; + for(seq_child= seq->seqbase.first; seq_child; seq_child= seq_child->next) { + seq_translate(seq_child, delta); + } + } + + calc_sequence_disp(seq); +} + +/* return 0 if there werent enough space */ +int shuffle_seq(ListBase * seqbasep, Sequence *test) +{ + int orig_machine= test->machine; + test->machine++; + calc_sequence(test); + while( seq_test_overlap(seqbasep, test) ) { + if(test->machine >= MAXSEQ) { + break; + } + test->machine++; + calc_sequence(test); // XXX - I dont think this is needed since were only moving vertically, Campbell. + } + + + if(test->machine >= MAXSEQ) { + /* Blender 2.4x would remove the strip. + * nicer to move it to the end */ + + Sequence *seq; + int new_frame= test->enddisp; + + for(seq= seqbasep->first; seq; seq= seq->next) { + if (seq->machine == orig_machine) + new_frame = MAX2(new_frame, seq->enddisp); + } + + test->machine= orig_machine; + new_frame = new_frame + (test->start-test->startdisp); /* adjust by the startdisp */ + seq_translate(test, new_frame - test->start); + + calc_sequence(test); + return 0; + } else { + return 1; + } +} + +static int shuffle_seq_time_offset_test(ListBase * seqbasep, char dir) +{ + int offset= 0; + Sequence *seq, *seq_other; + + for(seq= seqbasep->first; seq; seq= seq->next) { + if(seq->tmp) { + for(seq_other= seqbasep->first; seq_other; seq_other= seq_other->next) { + if(!seq_other->tmp && seq_overlap(seq, seq_other)) { + if(dir=='L') { + offset= MIN2(offset, seq_other->startdisp - seq->enddisp); + } + else { + offset= MAX2(offset, seq_other->enddisp - seq->startdisp); + } + } + } + } + } + return offset; +} + +static int shuffle_seq_time_offset(ListBase * seqbasep, char dir) +{ + int ofs= 0; + int tot_ofs= 0; + Sequence *seq; + while( (ofs= shuffle_seq_time_offset_test(seqbasep, dir)) ) { + for(seq= seqbasep->first; seq; seq= seq->next) { + if(seq->tmp) { + /* seq_test_overlap only tests display values */ + seq->startdisp += ofs; + seq->enddisp += ofs; + } + } + + tot_ofs+= ofs; + } + + for(seq= seqbasep->first; seq; seq= seq->next) { + if(seq->tmp) + calc_sequence_disp(seq); /* corrects dummy startdisp/enddisp values */ + } + + return tot_ofs; +} + +int shuffle_seq_time(ListBase * seqbasep) +{ + /* note: seq->tmp is used to tag strips to move */ + + Sequence *seq; + + int offset_l = shuffle_seq_time_offset(seqbasep, 'L'); + int offset_r = shuffle_seq_time_offset(seqbasep, 'R'); + int offset = (-offset_l < offset_r) ? offset_l:offset_r; + + if(offset) { + for(seq= seqbasep->first; seq; seq= seq->next) { + if(seq->tmp) { + seq_translate(seq, offset); + seq->flag &= ~SEQ_OVERLAP; + } + } + } + + return offset? 0:1; +} + +void seq_update_sound(Sequence *seq) +{ + if(seq->type == SEQ_SOUND && seq->sound_handle) + { + seq->sound_handle->startframe = seq->startdisp; + seq->sound_handle->endframe = seq->enddisp; + seq->sound_handle->frameskip = seq->startofs + seq->anim_startofs; + seq->sound_handle->changed = -1; + /* mute is set in seq_update_muting_recursive */ + } +} + +static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute) +{ + Sequence *seq; + int seqmute; + + /* for sound we go over full meta tree to update muted state, + since sound is played outside of evaluating the imbufs, */ + for(seq=seqbasep->first; seq; seq=seq->next) { + seqmute= (mute || (seq->flag & SEQ_MUTE)); + + if(seq->type == SEQ_META) { + /* if this is the current meta sequence, unmute because + all sequences above this were set to mute */ + if(seq == metaseq) + seqmute= 0; + + seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute); + } + else if(seq->type == SEQ_SOUND) { + if(seq->sound_handle && seqmute != seq->sound_handle->mute) { + seq->sound_handle->mute = seqmute; + seq->sound_handle->changed = -1; + } + } + } +} + +void seq_update_muting(Editing *ed) +{ + if(ed) { + /* mute all sounds up to current metastack list */ + MetaStack *ms= ed->metastack.last; + + if(ms) + seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1); + else + seq_update_muting_recursive(&ed->seqbase, NULL, 0); + } +} + + +/* XXX - hackish function needed for transforming strips! TODO - have some better solution */ +void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) +{ + char str[32]; + FCurve *fcu; + + if(scene->adt==NULL || ofs==0) + return; + + sprintf(str, "[\"%s\"]", seq->name+2); + + for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) { + if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { + int i; + for (i = 0; i < fcu->totvert; i++) { + BezTriple *bezt= &fcu->bezt[i]; + bezt->vec[0][0] += ofs; + bezt->vec[1][0] += ofs; + bezt->vec[2][0] += ofs; + } + } + } +} + + +Sequence *active_seq_get(Scene *scene) +{ + Editing *ed= seq_give_editing(scene, FALSE); + if(ed==NULL) return NULL; + return ed->act_seq; +} + +void active_seq_set(Scene *scene, Sequence *seq) +{ + Editing *ed= seq_give_editing(scene, FALSE); + if(ed==NULL) return; + + ed->act_seq= seq; +} + +/* api like funcs for adding */ + +void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) +{ + if(seq) { + strcpy(seq->name, seq_load->name); + seqUniqueName(scene->ed->seqbasep, seq); + + if(seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) { + seq_load->start_frame += (seq->enddisp - seq->startdisp); + } + + if(seq_load->flag & SEQ_LOAD_REPLACE_SEL) { + seq_load->flag |= 1; /* SELECT */ + active_seq_set(scene, seq); + } + + if(seq_load->flag & SEQ_LOAD_SOUND_CACHE) { + if(seq->sound) + sound_cache(seq->sound, 0); + } + + seq_load->tot_success++; + } + else { + seq_load->tot_error++; + } +} + +Sequence *alloc_sequence(ListBase *lb, int cfra, int machine) +{ + Sequence *seq; + + seq= MEM_callocN( sizeof(Sequence), "addseq"); + BLI_addtail(lb, seq); + + *( (short *)seq->name )= ID_SEQ; + seq->name[2]= 0; + + seq->flag= 1; /* SELECT */ + seq->start= cfra; + seq->machine= machine; + seq->mul= 1.0; + seq->blend_opacity = 100.0; + + return seq; +} + +void seqUniqueName(ListBase *seqbasep, Sequence *seq) +{ + BLI_uniquename(seqbasep, seq, "Sequence", '.', offsetof(Sequence, name), SEQ_NAME_MAXSTR); +} + +/* NOTE: this function doesn't fill in iamge names */ +Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +{ + Scene *scene= CTX_data_scene(C); /* only for active seq */ + Sequence *seq; + Strip *strip; + StripElem *se; + + seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); + seq->type= SEQ_IMAGE; + BLI_strncpy(seq->name+2, "Image", SEQ_NAME_MAXSTR-2); + seqUniqueName(seqbasep, seq); + + /* basic defaults */ + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + + strip->len = seq->len = seq_load->len ? seq_load->len : 1; + strip->us= 1; + strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name); + + seq_load_apply(scene, seq, seq_load); + + return seq; +} + +Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +{ + Scene *scene= CTX_data_scene(C); /* only for sound */ + Editing *ed= seq_give_editing(scene, TRUE); + bSound *sound; + + Sequence *seq; /* generic strip vars */ + Strip *strip; + StripElem *se; + + AUD_SoundInfo info; + + sound = sound_new_file(CTX_data_main(C), seq_load->path); + + if (sound==NULL || sound->handle == NULL) { + //if(op) + // BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); + return NULL; + } + + info = AUD_getInfo(sound->handle); + + if (info.specs.format == AUD_FORMAT_INVALID) { + sound_delete(C, sound); + //if(op) + // BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); + return NULL; + } + + seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); + + seq->type= SEQ_SOUND; + seq->sound= sound; + BLI_strncpy(seq->name+2, "Sound", SEQ_NAME_MAXSTR-2); + seqUniqueName(seqbasep, seq); + + /* basic defaults */ + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strip->len = seq->len = (int) (info.length * FPS); + strip->us= 1; + + strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + + BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name); + + seq->sound_handle = sound_new_handle(scene, sound, seq_load->start_frame, seq_load->start_frame + strip->len, 0); + + calc_sequence_disp(seq); + + /* last active name */ + strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR-1); + + seq_load_apply(scene, seq, seq_load); + + return seq; +} + +Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) +{ + Scene *scene= CTX_data_scene(C); /* only for sound */ + + Sequence *seq, *soundseq; /* generic strip vars */ + Strip *strip; + StripElem *se; + + struct anim *an; + + an = openanim(seq_load->path, IB_rect); + + if(an==NULL) + return NULL; + + seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); + + seq->type= SEQ_MOVIE; + seq->anim= an; + seq->anim_preseek = IMB_anim_get_preseek(an); + BLI_strncpy(seq->name+2, "Movie", SEQ_NAME_MAXSTR-2); + seqUniqueName(seqbasep, seq); + + /* basic defaults */ + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strip->len = seq->len = IMB_anim_get_duration( an ); + strip->us= 1; + + strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + + BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name); + + calc_sequence_disp(seq); + + + if(seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { + int start_frame_back= seq_load->start_frame; + seq_load->channel++; + + soundseq = sequencer_add_sound_strip(C, seqbasep, seq_load); + + seq_load->start_frame= start_frame_back; + seq_load->channel--; + } + + /* can be NULL */ + seq_load_apply(scene, seq, seq_load); + + return seq; +} -- cgit v1.2.3 From 61da7bb8660228708b1f540e9012446276d6a5e6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 Dec 2009 15:48:57 +0000 Subject: more sequence -> sequencer rename, also made sequencer swap strip update effects strips --- source/blender/blenkernel/intern/scene.c | 2 +- source/blender/blenkernel/intern/sequencer.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 43017a75835..4312f23bd9b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -860,7 +860,7 @@ void scene_update_for_newframe(Scene *sce, unsigned int lay) void scene_add_render_layer(Scene *sce) { SceneRenderLayer *srl; - int tot= 1 + BLI_countlist(&sce->r.layers); +// int tot= 1 + BLI_countlist(&sce->r.layers); srl= MEM_callocN(sizeof(SceneRenderLayer), "new render layer"); sprintf(srl->name, "RenderLayer"); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index c5ca24bec45..7450e810b89 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -472,6 +472,8 @@ void calc_sequence_disp(Sequence *seq) void calc_sequence(Sequence *seq) { + printf(" ddd %s\n", seq->name); + Sequence *seqm; int min, max; -- cgit v1.2.3 From ca16488e813ee58491ccca79532a48d098aaacd5 Mon Sep 17 00:00:00 2001 From: Andrea Weikert Date: Sun, 13 Dec 2009 17:46:30 +0000 Subject: MSVC 9 compile fixes and cleanups * added renamed files in revision 25337 * renamed BLI_util.h -> BLI_path_util.h for consistency * cleanup of #includes: removed BLI_blenlib.h in favour of direct includes of the needed headerfiles in a few places. * removed debug print in sequencer.c * added missing include in blenkernel/blender.c -> bad dependency, needs to be fixed still --- source/blender/blenkernel/intern/blender.c | 2 ++ source/blender/blenkernel/intern/sequencer.c | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index afb1335b86b..6181712f1be 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -94,6 +94,8 @@ #include "BKE_utildefines.h" // O_BINARY FALSE +#include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie + Global G; UserDef U; ListBase WMlist= {NULL, NULL}; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 7450e810b89..2faaa2fb5f5 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -49,14 +49,17 @@ #include "RNA_access.h" #include "RE_pipeline.h" -#include "BLI_blenlib.h" -#include "BLI_util.h" +#include "BLI_fileops.h" +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_threads.h" +#include #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "BLI_threads.h" -#include + #include "BKE_context.h" #include "BKE_sound.h" @@ -472,8 +475,6 @@ void calc_sequence_disp(Sequence *seq) void calc_sequence(Sequence *seq) { - printf(" ddd %s\n", seq->name); - Sequence *seqm; int min, max; -- cgit v1.2.3 From d31d6e71e27db28dde976d0b2e574dced5a464d2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 Dec 2009 19:25:05 +0000 Subject: added include path for bad level call --- source/blender/blenkernel/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 7bd6314097b..b1cbd16512e 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -34,6 +34,7 @@ SET(INC ../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern ../../../intern/bsp/extern ../blenfont ../../../intern/audaspace/intern + ../../../source/blender/windowmanager # XXX - BAD LEVEL CALL WM_api.h ${ZLIB_INC} ) -- cgit v1.2.3 From c8fe0daa918799738d409f2cd331bb39208e86e1 Mon Sep 17 00:00:00 2001 From: Andrea Weikert Date: Sun, 13 Dec 2009 19:45:23 +0000 Subject: fixing scons and makefile compile. * added include path due to added bad level #include "WM_api.h" --- source/blender/blenkernel/SConscript | 3 ++- source/blender/blenkernel/intern/Makefile | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 81b74cc9c42..508ed58165f 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -3,7 +3,8 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include ../blenlib ../blenfont ../makesdna' +incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include' +incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager' incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna' incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes' incs += ' #/intern/iksolver/extern ../blenloader' diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 26b9b9ef0dd..95c82d31890 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -53,6 +53,8 @@ CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../blenloader CPPFLAGS += -I../../python CPPFLAGS += -I../../blenfont +# This is bad level, remove eventually +CPPFLAGS += -I../../windowmanager # also avi is used CPPFLAGS += -I../../avi CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -- cgit v1.2.3 From e01b030817e10163670ce6b03b2a416a668c7555 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 14 Dec 2009 06:25:42 +0000 Subject: Bugfix #20351: - Offset parameter of the path constraint has no effect on the animation - Path animation was being repeated multiple times even though it was not supposed to --- source/blender/blenkernel/intern/constraint.c | 22 +++++++++++----------- source/blender/blenkernel/intern/object.c | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index aff3bf058fd..797fe8f7324 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1191,17 +1191,17 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr if ((data->followflag & FOLLOWPATH_STATIC) == 0) { /* animated position along curve depending on time */ if (cob->scene) - curvetime= bsystem_time(cob->scene, ct->tar, ctime, 0.0) - data->offset; + curvetime= bsystem_time(cob->scene, ct->tar, cu->ctime, 0.0) - data->offset; else - curvetime= ctime - data->offset; + curvetime= cu->ctime - data->offset; /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated, * but this will only work if it actually is animated... * - * we firstly calculate the modulus of cu->ctime/cu->pathlen to clamp ctime within the 0.0 to 1.0 times pathlen - * range, then divide this (the modulus) by pathlen to get a value between 0.0 and 1.0 + * we divide the curvetime calculated in the previous step by the length of the path, to get a time + * factor, which then gets clamped to lie within 0.0 - 1.0 range */ - curvetime= fmod(cu->ctime, cu->pathlen) / cu->pathlen; + curvetime /= cu->pathlen; CLAMP(curvetime, 0.0, 1.0); } else { @@ -1211,7 +1211,7 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr if ( where_on_path(ct->tar, curvetime, vec, dir, NULL, &radius) ) { if (data->followflag & FOLLOWPATH_FOLLOW) { - vec_to_quat( quat,dir, (short) data->trackflag, (short) data->upflag); + vec_to_quat(quat, dir, (short)data->trackflag, (short)data->upflag); normalize_v3(dir); q[0]= (float)cos(0.5*vec[3]); @@ -1221,7 +1221,7 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr q[3]= -x1*dir[2]; mul_qt_qtqt(quat, q, quat); - quat_to_mat4( totmat,quat); + quat_to_mat4(totmat, quat); } if (data->followflag & FOLLOWPATH_RADIUS) { @@ -1251,12 +1251,12 @@ static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase float size[3]; bFollowPathConstraint *data= con->data; - /* get Object local transform (loc/rot/size) to determine transformation from path */ - //object_to_mat4(ob, obmat); - copy_m4_m4(obmat, cob->matrix); // FIXME!!! + /* get Object transform (loc/rot/size) to determine transformation from path */ + // TODO: this used to be local at one point, but is probably more useful as-is + copy_m4_m4(obmat, cob->matrix); /* get scaling of object before applying constraint */ - mat4_to_size( size,cob->matrix); + mat4_to_size(size, cob->matrix); /* apply targetmat - containing location on path, and rotation */ mul_serie_m4(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 47830453c2e..6b86c6c2908 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1664,10 +1664,10 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated, * but this will only work if it actually is animated... * - * we firstly calculate the modulus of cu->ctime/cu->pathlen to clamp ctime within the 0.0 to 1.0 times pathlen - * range, then divide this (the modulus) by pathlen to get a value between 0.0 and 1.0 + * we divide the curvetime calculated in the previous step by the length of the path, to get a time + * factor, which then gets clamped to lie within 0.0 - 1.0 range */ - ctime= fmod(cu->ctime, cu->pathlen) / cu->pathlen; + ctime= cu->ctime / cu->pathlen; CLAMP(ctime, 0.0, 1.0); } else { -- cgit v1.2.3 From be6bf5faf65801d917ef515b7394cac53cbe0715 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 14 Dec 2009 13:45:45 +0000 Subject: Fix #20380: Duplicating mesh with Particle Instance Mod, Pole Axis not copied. --- source/blender/blenkernel/intern/modifier.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9390c7d67c4..e75203c6cde 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6570,6 +6570,7 @@ static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *ta tpimd->ob = pimd->ob; tpimd->psys = pimd->psys; tpimd->flag = pimd->flag; + tpimd->axis = pimd->axis; tpimd->position = pimd->position; tpimd->random_position = pimd->random_position; } -- cgit v1.2.3 From 6760dbf2adc1fa749dc0107d95745cbe9a6611d5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 14 Dec 2009 15:40:47 +0000 Subject: Bugfix: converting multires with 0 levels would crash. --- source/blender/blenkernel/intern/multires.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index e1f2b22c9f0..66f8da03d24 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -796,7 +796,8 @@ void multires_load_old_250(Mesh *me) if(mdisps) { for(a=0; atotface; a++) - old_mdisps_convert(&me->mface[a], &mdisps[a]); + if(mdisps[a].totdisp) + old_mdisps_convert(&me->mface[a], &mdisps[a]); } } -- cgit v1.2.3 From 9a7f6e937bc80b9e72b503d0b0fb07ea840a3e38 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 14 Dec 2009 17:08:02 +0000 Subject: Fix #20345: weight paint crashes with armature modifier without object. Also fixes: * Weight paint subsurf drawing. * Missing pointer endian conversion in paint brushes. * Use of unitialized variable in screen version patch. * Multires modifier without mdisps layer crash. --- source/blender/blenkernel/intern/cdderivedmesh.c | 1 - source/blender/blenkernel/intern/multires.c | 7 +++ source/blender/blenkernel/intern/subsurf_ccg.c | 77 +++++++++++++++++------- 3 files changed, 63 insertions(+), 22 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 77ad9fb7a7b..66c39c6571a 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -761,7 +761,6 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us float *nors= dm->getFaceDataArray(dm, CD_NORMAL); int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); - mc = DM_get_face_data_layer(dm, CD_ID_MCOL); if(!mc) mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 66f8da03d24..139a8d3267f 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -450,6 +450,13 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int int *gridOffset; int i, numGrids, gridSize, dGridSize, dSkip; + if(!mdisps) { + if(invert) + mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); + else + return; + } + numGrids = dm->getNumGrids(dm); gridSize = dm->getGridSize(dm); gridData = dm->getGridData(dm); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index f6abedda2b6..793ea26a602 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1548,12 +1548,15 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; - MCol *mcol = DM_get_face_data_layer(dm, CD_MCOL); + MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); char *faceFlags = ccgdm->faceFlags; int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; + if(!mcol) + mcol = dm->getFaceDataArray(dm, CD_MCOL); + totface = ccgSubSurf_getNumFaces(ss); for(i = 0; i < totface; i++) { CCGFace *f = ccgdm->faceMap[i].face; @@ -1719,21 +1722,35 @@ static void ccgDM_drawUVEdges(DerivedMesh *dm) static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; - CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); + MCol *mcol= NULL; int i, gridSize = ccgSubSurf_getGridSize(ss); char *faceFlags = ccgdm->faceFlags; + int gridFaces = gridSize - 1, totface; - for (i=0; !ccgFaceIterator_isStopped(fi); i++,ccgFaceIterator_next(fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(fi); + if(useColors) { + mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); + if(!mcol) + mcol = dm->getFaceDataArray(dm, CD_MCOL); + } + + totface = ccgSubSurf_getNumFaces(ss); + for(i = 0; i < totface; i++) { + CCGFace *f = ccgdm->faceMap[i].face; int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f); int origIndex; + unsigned char *cp= NULL; origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); if(faceFlags) drawSmooth = (faceFlags[origIndex*2] & ME_SMOOTH); else drawSmooth = 1; - + + if(mcol) { + cp= (unsigned char*)mcol; + mcol += gridFaces*gridFaces*numVerts*4; + } + if (index!=-1) { int draw; draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, index, &drawSmooth); @@ -1748,41 +1765,61 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); if (drawSmooth) { glShadeModel(GL_SMOOTH); - for (y=0; yno); glVertex3fv(a->co); + if(cp) glColor3ub(cp[7], cp[6], cp[5]); glNormal3fv(b->no); glVertex3fv(b->co); + + if(x != gridFaces-1) { + if(cp) cp += 16; + } } + + a = &faceGridData[(y+0)*gridSize + x]; + b = &faceGridData[(y+1)*gridSize + x]; + + if(cp) glColor3ub(cp[15], cp[14], cp[13]); + glNormal3fv(a->no); + glVertex3fv(a->co); + if(cp) glColor3ub(cp[11], cp[10], cp[9]); + glNormal3fv(b->no); + glVertex3fv(b->co); + + if(cp) cp += 16; + glEnd(); } } else { glShadeModel(GL_FLAT); glBegin(GL_QUADS); - for (y=0; y Date: Mon, 14 Dec 2009 20:01:52 +0000 Subject: Fix #20233: crash when entering - characters in text object, with short textbox width. I can't tell if this is working correct, the code is very cryptic, with gotos even, but seems there is not enough space allocated to permit splitting each character to it's own line. --- source/blender/blenkernel/intern/font.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index e2dccf02b40..1a63f97e310 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -705,10 +705,10 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) /* We assume the worst case: 1 character per line (is freed at end anyway) */ - linedata= MEM_mallocN(sizeof(float)*(slen+2),"buildtext2"); - linedata2= MEM_mallocN(sizeof(float)*(slen+2),"buildtext3"); - linedata3= MEM_callocN(sizeof(float)*(slen+2),"buildtext4"); - linedata4= MEM_callocN(sizeof(float)*(slen+2),"buildtext5"); + linedata= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext2"); + linedata2= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext3"); + linedata3= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext4"); + linedata4= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext5"); linedist= cu->linedist; -- cgit v1.2.3 From 639dd6d25ec07535c8b856d527ffcc75c9a7b6d2 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 14 Dec 2009 20:47:02 +0000 Subject: Fix #20362: multires conversion from 2.5alpha0 not working. It's still not entirely the same, the tangets are a bit different at face edges/corners. --- source/blender/blenkernel/intern/multires.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 139a8d3267f..88c6788b723 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -784,6 +784,11 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp) for(x = 0; x < newside; ++x, ++out) { old_mdisps_rotate(S, newside, oldside, x, y, &u, &v); old_mdisps_bilinear(*out, mdisp->disps, oldside, u, v); + + 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]; }; } } } -- cgit v1.2.3 From 03e1afe7ac4d507bf8a41e42049d618313599ab6 Mon Sep 17 00:00:00 2001 From: Andrea Weikert Date: Mon, 14 Dec 2009 22:59:41 +0000 Subject: Sequencer: * fix crash due to missing preview region * had to bump up subversion to catch all files saved without preview region in sequencer. --- 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 08503a3d00c..8a7f4da8cbf 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ struct bContext; struct ReportList; #define BLENDER_VERSION 250 -#define BLENDER_SUBVERSION 9 +#define BLENDER_SUBVERSION 10 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 -- cgit v1.2.3 From 20748a38ac5fea178c852699b4e14f539e84fe96 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 15 Dec 2009 00:10:03 +0000 Subject: Bugfix #20384: target data path of driving not correct when loading old rig from 2.49b --- source/blender/blenkernel/intern/fcurve.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 04fcd43b883..b5f3d0a4be0 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -828,6 +828,10 @@ float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar) /* get property to read from, and get value as appropriate */ if (RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) { + /* for now, if there is no valid index, fall back to the array-index specified separately */ + if (index == -1) + index= dtar->array_index; + switch (RNA_property_type(prop)) { case PROP_BOOLEAN: if (RNA_property_array_length(&ptr, prop)) @@ -927,19 +931,19 @@ static float evaluate_driver (ChannelDriver *driver, float evaltime) /* more than one target, so average the values of the targets */ int tot = 0; float value = 0.0f; - + /* loop through targets, adding (hopefully we don't get any overflow!) */ for (dtar= driver->targets.first; dtar; dtar=dtar->next) { value += driver_get_target_value(driver, dtar); tot++; } - + /* return the average of these */ - if(driver->type == DRIVER_TYPE_AVERAGE) + if (driver->type == DRIVER_TYPE_AVERAGE) return (value / (float)tot); else return value; - + } } break; -- cgit v1.2.3 From 8aa8efb3274daa5bb62c3a20f0ed940cad0ea287 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Dec 2009 11:27:46 +0000 Subject: * rna attributes for sequence strips - seq.start_frame_final & seq.end_frame_final these expose the final start and end after offsets are applied. when set this is like grabbing the handle and moving it. * made swapping strips shuffle effects and check for overlap. --- source/blender/blenkernel/BKE_sequencer.h | 4 ++-- source/blender/blenkernel/intern/sequencer.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 5b146cd5ecd..95fe8fb5eb9 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -178,8 +178,8 @@ void seq_tx_set_final_left(struct Sequence *seq, int val); void seq_tx_set_final_right(struct Sequence *seq, int val); void seq_tx_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag); int seq_tx_test(struct Sequence * seq); -int check_single_seq(struct Sequence *seq); -void fix_single_seq(struct Sequence *seq); +int seq_single_check(struct Sequence *seq); +void seq_single_fix(struct Sequence *seq); int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test); void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 2faaa2fb5f5..4d6033e4f4a 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3259,7 +3259,7 @@ void seq_tx_set_final_right(Sequence *seq, int val) /* used so we can do a quick check for single image seq since they work a bit differently to normal image seq's (during transform) */ -int check_single_seq(Sequence *seq) +int seq_single_check(Sequence *seq) { if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR)) return 1; @@ -3276,7 +3276,7 @@ void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) seq_tx_set_final_left(seq, seq_tx_get_final_right(seq, 0)-1); } - if (check_single_seq(seq)==0) { + if (seq_single_check(seq)==0) { if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_end(seq)) { seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1); } @@ -3298,7 +3298,7 @@ void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) seq_tx_set_final_right(seq, seq_tx_get_final_left(seq, 0)+1); } - if (check_single_seq(seq)==0) { + if (seq_single_check(seq)==0) { if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_start(seq)) { seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1); } @@ -3312,10 +3312,10 @@ void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) } } -void fix_single_seq(Sequence *seq) +void seq_single_fix(Sequence *seq) { int left, start, offset; - if (!check_single_seq(seq)) + if (!seq_single_check(seq)) return; /* make sure the image is always at the start since there is only one, -- cgit v1.2.3 From fedea2eb5c4b5d414349cc460bedc4485af90d53 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 15 Dec 2009 18:00:22 +0000 Subject: Fix #20393: subsurfed objects only allow a single material. --- source/blender/blenkernel/intern/subsurf_ccg.c | 7 +++---- 1 file changed, 3 insertions(+), 4 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 793ea26a602..072a665e0e9 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -931,8 +931,8 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) for(index = 0; index < totface; index++) { CCGFace *f = ccgdm->faceMap[index].face; int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); - int mat_nr = 0; - int flag = ME_SMOOTH; /* assume face is smooth by default */ + int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH; + int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0; for(S = 0; S < numVerts; S++) { for(y = 0; y < gridSize - 1; y++) { @@ -947,8 +947,7 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edgeSize, gridSize); mf->mat_nr = mat_nr; - if(faceFlags) mf->flag = faceFlags[index*2]; - else mf->flag = flag; + mf->flag = flag; i++; } -- cgit v1.2.3 From b6d2d9f63a188aa49e24b4c30c48947b62c6a19c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Dec 2009 16:35:31 +0000 Subject: have sequence strip rna not depend on the current editing sequencer context (TODO- rename) --- source/blender/blenkernel/BKE_sequencer.h | 9 +++++---- source/blender/blenkernel/intern/sequencer.c | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 95fe8fb5eb9..a50b03861d7 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -60,17 +60,17 @@ void seq_next(SeqIterator *iter); void seq_end(SeqIterator *iter); void seq_array(struct Editing *ed, struct Sequence ***seqarray, int *tot, int use_pointer); -#define SEQP_BEGIN(ed, seq) \ +#define SEQP_BEGIN(ed, _seq) \ { \ SeqIterator iter;\ for(seq_begin(ed, &iter, 1); iter.valid; seq_next(&iter)) { \ - seq= iter.seq; + _seq= iter.seq; -#define SEQ_BEGIN(ed, seq) \ +#define SEQ_BEGIN(ed, _seq) \ { \ SeqIterator iter;\ for(seq_begin(ed, &iter, 0); iter.valid; seq_next(&iter)) { \ - seq= iter.seq; + _seq= iter.seq; #define SEQ_END \ } \ @@ -181,6 +181,7 @@ int seq_tx_test(struct Sequence * seq); int seq_single_check(struct Sequence *seq); void seq_single_fix(struct Sequence *seq); int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test); +struct ListBase *seq_seqbase(struct ListBase *seqbase, struct Sequence *seq); void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test); int shuffle_seq_time(ListBase * seqbasep); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 4d6033e4f4a..a7b9cf7f74c 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3532,6 +3532,23 @@ void seq_update_muting(Editing *ed) } } +/* in cases where we done know the sequence's listbase */ +ListBase *seq_seqbase(ListBase *seqbase, Sequence *seq) +{ + Sequence *iseq; + ListBase *lb= NULL; + + for(iseq= seqbase->first; iseq; iseq= iseq->next) { + if(seq==iseq) { + return seqbase; + } + else if(iseq->seqbase.first && (lb= seq_seqbase(&iseq->seqbase, seq))) { + return lb; + } + } + + return NULL; +} /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) -- cgit v1.2.3 From c3401eb5cb0833dc76eff1e90e573b487181ec81 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Dec 2009 19:49:33 +0000 Subject: camera switching via markers Currently access by selecting a marking and binding with the active camera from the view menu. Note: after long discussion we decieded there is no nice way to do this.. animate pointers? animate multiple camera visibility?, use sequencer? use NLA?.... have a kind of event system (like framechange scriptlinks)... etc so this is ifdef'd with DURIAN_CAMERA_SWITCH --- source/blender/blenkernel/BKE_scene.h | 1 + source/blender/blenkernel/intern/object.c | 11 +++++++++ source/blender/blenkernel/intern/scene.c | 41 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index ecff62a7952..c372004bd19 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -66,6 +66,7 @@ void unlink_scene(struct Main *bmain, struct Scene *sce, struct Scene *newsce); int next_object(struct Scene *scene, int val, struct Base **base, struct Object **ob); struct Object *scene_find_camera(struct Scene *sc); +struct Object *scene_find_camera_switch(struct Scene *scene); // DURIAN_CAMERA_SWITCH struct Base *scene_add_base(struct Scene *sce, struct Object *ob); void scene_deselect_all(struct Scene *sce); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6b86c6c2908..9a7a3501031 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -554,6 +554,17 @@ void unlink_object(Scene *scene, Object *ob) if(sce->id.lib==NULL) { if(sce->camera==ob) sce->camera= NULL; if(sce->toolsettings->skgen_template==ob) sce->toolsettings->skgen_template = NULL; + +#ifdef DURIAN_CAMERA_SWITCH + { + TimeMarker *m; + + for (m= sce->markers.first; m; m= m->next) { + if(m->camera==ob) + m->camera= NULL; + } + } +#endif } sce= sce->id.next; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 4312f23bd9b..7bfeac037ce 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -698,6 +698,47 @@ Object *scene_find_camera(Scene *sc) return NULL; } +#ifdef DURIAN_CAMERA_SWITCH +Object *scene_find_camera_switch(Scene *scene) +{ + TimeMarker *m; + int cfra = scene->r.cfra; + int frame = -(MAXFRAME + 1); + Object *camera= NULL; + + for (m= scene->markers.first; m; m= m->next) { + if(m->camera && (m->frame <= cfra) && (m->frame > frame)) { + camera= m->camera; + frame= m->frame; + + if(frame == cfra) + break; + + } + } + return camera; +} +#endif + +static char *get_cfra_marker_name(Scene *scene) +{ + ListBase *markers= &scene->markers; + TimeMarker *m1, *m2; + + /* search through markers for match */ + for (m1=markers->first, m2=markers->last; m1 && m2; m1=m1->next, m2=m2->prev) { + if (m1->frame==CFRA) + return m1->name; + + if (m1 == m2) + break; + + if (m2->frame==CFRA) + return m2->name; + } + + return NULL; +} Base *scene_add_base(Scene *sce, Object *ob) { -- cgit v1.2.3 From fac65a3f4d1645fb59ed0b023247535b4b1d6d77 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Thu, 17 Dec 2009 04:55:15 +0000 Subject: Durian request: Extend the 'only selected' property in the graph editor to only show curves from selected sequence strips and nodes as well. --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/BKE_sequencer.h | 2 ++ source/blender/blenkernel/intern/node.c | 11 +++++++++++ source/blender/blenkernel/intern/sequencer.c | 15 +++++++++++++++ 4 files changed, 29 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index f9130e24a08..3ed9ab8778e 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -175,6 +175,7 @@ struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int inte struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); +struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name); int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex); struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index a50b03861d7..e6b468e0dc0 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -192,6 +192,8 @@ void seq_update_muting(struct Editing *ed); void clear_scene_in_allseqs(struct Scene *sce); +struct Sequence *get_seq_by_name(struct Scene *scene, const char *name); + struct Sequence *active_seq_get(struct Scene *scene); void active_seq_set(struct Scene *scene, struct Sequence *seq); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index a27c3b6494b..84ef4fb6d1c 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -767,6 +767,17 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup) } } +/* finds a node based on its name */ +bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name) +{ + bNode *node=NULL; + + for(node= ntree->nodes.first; node; node= node->next) { + if (strcmp(name, node->name) == 0) + break; + } + return node; +} /* finds a node based on given socket */ int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index a7b9cf7f74c..e36e8dc49c4 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3575,6 +3575,21 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) } +Sequence *get_seq_by_name(Scene *scene, const char *name) +{ + Sequence *seq=NULL; + Editing *ed= seq_give_editing(scene, FALSE); + + if(ed==NULL) return NULL; + + for (seq=ed->seqbase.first; seq; seq=seq->next) { + if (strcmp(name, seq->name+2) == 0) + break; + } + return seq; +} + + Sequence *active_seq_get(Scene *scene) { Editing *ed= seq_give_editing(scene, FALSE); -- cgit v1.2.3 From 88d72e796a388afe79d4dc8d4aed243a49ed1875 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 Dec 2009 11:16:28 +0000 Subject: remove warnings. Sequencer selection for fcurve view didnt work in metastrips. - added RNA_property_string_set to the RNA_access.h - include BKE_animsys.h in pipeline.c for sequencer update, hope these are ok. --- source/blender/blenkernel/BKE_sequencer.h | 2 +- source/blender/blenkernel/intern/scene.c | 2 +- source/blender/blenkernel/intern/sequencer.c | 22 ++++++++++++---------- 3 files changed, 14 insertions(+), 12 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index e6b468e0dc0..34d4b15b437 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -192,7 +192,7 @@ void seq_update_muting(struct Editing *ed); void clear_scene_in_allseqs(struct Scene *sce); -struct Sequence *get_seq_by_name(struct Scene *scene, const char *name); +struct Sequence *get_seq_by_name(struct ListBase *seqbase, const char *name, int recursive); struct Sequence *active_seq_get(struct Scene *scene); void active_seq_set(struct Scene *scene, struct Sequence *seq); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 7bfeac037ce..0a2edf82cb0 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -350,7 +350,7 @@ Scene *add_scene(char *name) sce->r.bake_normal_space= R_BAKE_SPACE_TANGENT; sce->r.scemode= R_DOCOMP|R_DOSEQ|R_EXTENSION; - sce->r.stamp= R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_SCENE|R_STAMP_CAMERA; + sce->r.stamp= R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_SCENE|R_STAMP_CAMERA|R_STAMP_RENDERTIME; sce->r.threads= 1; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index e36e8dc49c4..5165e570504 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3575,18 +3575,20 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) } -Sequence *get_seq_by_name(Scene *scene, const char *name) +Sequence *get_seq_by_name(ListBase *seqbase, const char *name, int recursive) { - Sequence *seq=NULL; - Editing *ed= seq_give_editing(scene, FALSE); - - if(ed==NULL) return NULL; - - for (seq=ed->seqbase.first; seq; seq=seq->next) { - if (strcmp(name, seq->name+2) == 0) - break; + Sequence *iseq=NULL; + Sequence *rseq=NULL; + + for (iseq=seqbase->first; iseq; iseq=iseq->next) { + if (strcmp(name, iseq->name+2) == 0) + return iseq; + else if(recursive && (iseq->seqbase.first) && (rseq=get_seq_by_name(&iseq->seqbase, name, 1))) { + return rseq; + } } - return seq; + + return NULL; } -- cgit v1.2.3 From 51fdfa0de97bd3825161e245338c76711578f4cf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 Dec 2009 14:45:47 +0000 Subject: sequencer clipboard note: for inter-scene copying this uses a hack because Colin needs it because half his scene was scrambled by blender. --- source/blender/blenkernel/BKE_sequencer.h | 1 + source/blender/blenkernel/intern/sequencer.c | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 34d4b15b437..a101a096fe8 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -141,6 +141,7 @@ void printf_strip(struct Sequence *seq); void seq_free_sequence(struct Scene *scene, struct Sequence *seq); void seq_free_strip(struct Strip *strip); void seq_free_editing(struct Scene *scene); +void seq_free_clipboard(struct Scene *scene); struct Editing *seq_give_editing(struct Scene *scene, int alloc); char *give_seqname(struct Sequence *seq); struct ImBuf *give_ibuf_seq(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 5165e570504..41e51885bfc 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -232,11 +232,23 @@ Editing *seq_give_editing(Scene *scene, int alloc) return scene->ed; } +void seq_free_clipboard(Scene *scene) +{ + Editing *ed = scene->ed; + Sequence *seq, *nseq; + + for(seq= ed->seqbase_clipboard.first; seq; seq= nseq) { + nseq= seq->next; + seq_free_sequence(scene, seq); + } + ed->seqbase_clipboard.first= ed->seqbase_clipboard.last= NULL; +} + void seq_free_editing(Scene *scene) { Editing *ed = scene->ed; MetaStack *ms; - Sequence *seq; + Sequence *seq, *nseq; if(ed==NULL) return; @@ -246,6 +258,8 @@ void seq_free_editing(Scene *scene) } SEQ_END + seq_free_clipboard(scene); + while((ms= ed->metastack.first)) { BLI_remlink(&ed->metastack, ms); MEM_freeN(ms); -- cgit v1.2.3 From 4271a40ee7a53029f04389234278b7f64d834a11 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 Dec 2009 16:28:45 +0000 Subject: - sequencer clipboard now stored globally (not in the scene, makes pasting into other scenes nicer) - multiple pastes after copying - clear the sound handle when copying (was crashing) - allow seq freeing without a scene (assumes seq strip isnt active and sound handle isnt set) - free clipboard sequences on exit - paste sequence strips using the relative playhead location from when they were copied. TODO - check scene pointers on paste - detect overlaps after paste --- source/blender/blenkernel/BKE_sequencer.h | 5 ++++- source/blender/blenkernel/intern/sequencer.c | 30 +++++++++++++++------------- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index a101a096fe8..22f9278aa38 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -141,7 +141,7 @@ void printf_strip(struct Sequence *seq); void seq_free_sequence(struct Scene *scene, struct Sequence *seq); void seq_free_strip(struct Strip *strip); void seq_free_editing(struct Scene *scene); -void seq_free_clipboard(struct Scene *scene); +void seq_free_clipboard(void); struct Editing *seq_give_editing(struct Scene *scene, int alloc); char *give_seqname(struct Sequence *seq); struct ImBuf *give_ibuf_seq(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); @@ -230,3 +230,6 @@ struct Sequence *sequencer_add_image_strip(struct bContext *C, ListBase *seqbase struct Sequence *sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); struct Sequence *sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); +/* copy/paste */ +extern ListBase seqbase_clipboard; +extern int seqbase_clipboard_frame; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 41e51885bfc..8b59c2982e6 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -77,6 +77,8 @@ static int seqrecty= 0; /* **** XXX ******** */ +ListBase seqbase_clipboard; +int seqbase_clipboard_frame; void printf_strip(Sequence *seq) { @@ -200,23 +202,26 @@ void seq_free_strip(Strip *strip) void seq_free_sequence(Scene *scene, Sequence *seq) { - Editing *ed = scene->ed; - if(seq->strip) seq_free_strip(seq->strip); if(seq->anim) IMB_free_anim(seq->anim); - if(seq->sound_handle) - sound_delete_handle(scene, seq->sound_handle); - if (seq->type & SEQ_EFFECT) { struct SeqEffectHandle sh = get_sequence_effect(seq); sh.free(seq); } - if (ed->act_seq==seq) - ed->act_seq= NULL; + /* clipboard has no scene and will never have a sound handle or be active */ + if(scene) { + Editing *ed = scene->ed; + + if (ed->act_seq==seq) + ed->act_seq= NULL; + + if(seq->sound_handle) + sound_delete_handle(scene, seq->sound_handle); + } MEM_freeN(seq); } @@ -232,16 +237,15 @@ Editing *seq_give_editing(Scene *scene, int alloc) return scene->ed; } -void seq_free_clipboard(Scene *scene) +void seq_free_clipboard(void) { - Editing *ed = scene->ed; Sequence *seq, *nseq; - for(seq= ed->seqbase_clipboard.first; seq; seq= nseq) { + for(seq= seqbase_clipboard.first; seq; seq= nseq) { nseq= seq->next; - seq_free_sequence(scene, seq); + seq_free_sequence(NULL, seq); } - ed->seqbase_clipboard.first= ed->seqbase_clipboard.last= NULL; + seqbase_clipboard.first= seqbase_clipboard.last= NULL; } void seq_free_editing(Scene *scene) @@ -258,8 +262,6 @@ void seq_free_editing(Scene *scene) } SEQ_END - seq_free_clipboard(scene); - while((ms= ed->metastack.first)) { BLI_remlink(&ed->metastack, ms); MEM_freeN(ms); -- cgit v1.2.3 From 8505c5bcf357b30919907d11279b232034305a9e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 Dec 2009 23:29:11 +0000 Subject: sequencer copy clipboard wasnt checking if all related strips were selected --- source/blender/blenkernel/BKE_sequencer.h | 1 + source/blender/blenkernel/intern/sequencer.c | 42 ++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 22f9278aa38..7c74dd5b3d3 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -186,6 +186,7 @@ struct ListBase *seq_seqbase(struct ListBase *seqbase, struct Sequence *seq); void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test); int shuffle_seq_time(ListBase * seqbasep); +int seqbase_isolated_sel_check(struct ListBase *seqbase); void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage); void seq_update_sound(struct Sequence *seq); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 8b59c2982e6..c92640e295e 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -76,7 +76,7 @@ static int seqrecty= 0; //static int blender_test_break() {return 0;} /* **** XXX ******** */ - +#define SELECT 1 ListBase seqbase_clipboard; int seqbase_clipboard_frame; @@ -3283,6 +3283,42 @@ int seq_single_check(Sequence *seq) return 0; } +/* check if the selected seq's reference unselected seq's */ +int seqbase_isolated_sel_check(ListBase *seqbase) +{ + Sequence *seq; + /* is there more than 1 select */ + int ok= FALSE; + + for(seq= seqbase->first; seq; seq= seq->next) { + if(seq->flag & SELECT) { + ok= TRUE; + break; + } + } + + if(ok == FALSE) + return FALSE; + + /* test relationships */ + for(seq= seqbase->first; seq; seq= seq->next) { + if(seq->flag & SELECT) { + if(seq->type & SEQ_EFFECT) { + if(seq->seq1 && (seq->seq1->flag & SELECT)==0) return FALSE; + if(seq->seq2 && (seq->seq2->flag & SELECT)==0) return FALSE; + if(seq->seq3 && (seq->seq3->flag & SELECT)==0) return FALSE; + } + } + else if(seq->type & SEQ_EFFECT) { + if(seq->seq1 && (seq->seq1->flag & SELECT)) return FALSE; + if(seq->seq2 && (seq->seq2->flag & SELECT)) return FALSE; + if(seq->seq3 && (seq->seq3->flag & SELECT)) return FALSE; + } + } + + return TRUE; +} + /* use to impose limits when dragging/extending - so impossible situations dont happen * Cant use the SEQ_LEFTSEL and SEQ_LEFTSEL directly because the strip may be in a metastrip */ void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) @@ -3636,7 +3672,7 @@ void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) } if(seq_load->flag & SEQ_LOAD_REPLACE_SEL) { - seq_load->flag |= 1; /* SELECT */ + seq_load->flag |= SELECT; active_seq_set(scene, seq); } @@ -3662,7 +3698,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine) *( (short *)seq->name )= ID_SEQ; seq->name[2]= 0; - seq->flag= 1; /* SELECT */ + seq->flag= SELECT; seq->start= cfra; seq->machine= machine; seq->mul= 1.0; -- cgit v1.2.3 From 4f3af9980f61e8203016714a2314ca51e1902362 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 18 Dec 2009 11:55:18 +0000 Subject: Keyframing Bugfix: This commit attempts to fix some of the bugs which were causing grief with some Durian animation tests. In one of those files, the order in which F-Curves were stored was seriously messed up; causing problems with some F-Curves still existing but unable to be edited (i.e. still showing up in the Object/Action summaries but nowhere else) since the standard assumptions for the way the data was stored had been violated. I've recoded the code that ensures that when F-Curves get added to Action Groups (and the Action that contains these) it ends up in the right places, since it was very likely that all the F-Curves would only ever get added near the end of the list. Hopefully this is enough to prevent these problems reoccurring, though I have a feeling there may still be one or two buggy tools which caused the problems in the first place. --- source/blender/blenkernel/intern/action.c | 117 +++++++++++------------------- 1 file changed, 42 insertions(+), 75 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index ace1292f813..303cd208b7c 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -254,101 +254,68 @@ void set_active_action_group (bAction *act, bActionGroup *agrp, short select) * - always adds at the end of the group */ void action_groups_add_channel (bAction *act, bActionGroup *agrp, FCurve *fcurve) -{ - FCurve *fcu; - short done=0; - +{ /* sanity checks */ if (ELEM3(NULL, act, agrp, fcurve)) return; - /* if no channels, just add to two lists at the same time */ + /* if no channels anywhere, just add to two lists at the same time */ if (act->curves.first == NULL) { fcurve->next = fcurve->prev = NULL; agrp->channels.first = agrp->channels.last = fcurve; act->curves.first = act->curves.last = fcurve; - - fcurve->grp= agrp; - return; } - /* try to find a channel to slot this in before/after */ - for (fcu= act->curves.first; fcu; fcu= fcu->next) { - /* if channel has no group, then we have ungrouped channels, which should always occur after groups */ - if (fcu->grp == NULL) { - BLI_insertlinkbefore(&act->curves, fcu, fcurve); - - if (agrp->channels.first == NULL) - agrp->channels.first= fcurve; - agrp->channels.last= fcurve; + /* if the group already has channels, the F-Curve can simply be added to the list + * (i.e. as the last channel in the group) + */ + else if (agrp->channels.first) { + /* if the group's last F-Curve is the action's last F-Curve too, + * then set the F-Curve as the last for the action first so that + * the lists will be in sync after linking + */ + if (agrp->channels.last == act->curves.last) + act->curves.last= fcurve; - done= 1; - break; - } + /* link in the given F-Curve after the last F-Curve in the group, + * which means that it should be able to fit in with the rest of the + * list seamlessly + */ + BLI_insertlinkafter(&agrp->channels, agrp->channels.last, fcurve); + } + + /* otherwise, need to find the nearest F-Curve in group before/after current to link with */ + else { + bActionGroup *grp; - /* if channel has group after current, we can now insert (otherwise we have gone too far) */ - else if (fcu->grp == agrp->next) { - BLI_insertlinkbefore(&act->curves, fcu, fcurve); - - if (agrp->channels.first == NULL) - agrp->channels.first= fcurve; - agrp->channels.last= fcurve; - - done= 1; - break; - } + /* firstly, link this F-Curve to the group */ + agrp->channels.first = agrp->channels.last = fcurve; - /* if channel has group we're targeting, check whether it is the last one of these */ - else if (fcu->grp == agrp) { - if ((fcu->next) && (fcu->next->grp != agrp)) { - BLI_insertlinkafter(&act->curves, fcu, fcurve); - agrp->channels.last= fcurve; - done= 1; - break; - } - else if (fcu->next == NULL) { - BLI_addtail(&act->curves, fcurve); - agrp->channels.last= fcurve; - done= 1; + /* step through the groups preceeding this one, finding the F-Curve there to attach this one after */ + for (grp= agrp->prev; grp; grp= grp->prev) { + /* if this group has F-Curves, we want weave the given one in right after the last channel there, + * but via the Action's list not this group's list + * - this is so that the F-Curve is in the right place in the Action, + * but won't be included in the previous group + */ + if (grp->channels.last) { + /* once we've added, break here since we don't need to search any further... */ + BLI_insertlinkafter(&act->curves, grp->channels.last, fcurve); break; } } - /* if channel has group before target, check whether the next one is something after target */ - else if (fcu->grp == agrp->prev) { - if (fcu->next) { - if ((fcu->next->grp != fcu->grp) && (fcu->next->grp != agrp)) { - BLI_insertlinkafter(&act->curves, fcu, fcurve); - - agrp->channels.first= fcurve; - agrp->channels.last= fcurve; - - done= 1; - break; - } - } - else { - BLI_insertlinkafter(&act->curves, fcu, fcurve); - - agrp->channels.first= fcurve; - agrp->channels.last= fcurve; - - done= 1; - break; - } - } + /* if grp is NULL, that means we fell through, and this F-Curve should be added as the new first + * since group is (effectively) the first group. Thus, the existing first F-Curve becomes the + * second in the chain, etc. etc. + */ + if (grp == NULL) + BLI_insertlinkbefore(&act->curves, act->curves.first, fcurve); } - /* only if added, set channel as belonging to this group */ - if (done) { - //printf("FCurve added to group \n"); - fcurve->grp= agrp; - } - else { - printf("Error: FCurve '%s' couldn't be added to Group '%s' \n", fcurve->rna_path, agrp->name); - BLI_addtail(&act->curves, fcurve); - } + /* set the F-Curve's new group */ + fcurve->grp= agrp; } /* Remove the given channel from all groups */ -- cgit v1.2.3 From 50544ea6457fb1a05eedd184251e33956deab03f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 18 Dec 2009 13:28:03 +0000 Subject: - sequence strips without scenes would crash on display - appending scenes would not append the sound and scene ID's for sequence strips - reload button in sequence header now reloads sounds as well. - redrawing the sequence image view didnt work while plaing (unless play was activated from that region) - generic functions for running a callback on sequence strips recursively. seqbase_recursive_apply() and seq_recursive_apply() - bind marker with camera was set to home key, use Ctrl+B instead. --- source/blender/blenkernel/BKE_sequencer.h | 4 ++ source/blender/blenkernel/intern/sequencer.c | 74 +++++++++++++++++++--------- 2 files changed, 56 insertions(+), 22 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 7c74dd5b3d3..c078b92af2d 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -137,6 +137,10 @@ struct SeqEffectHandle { /* sequence.c */ void printf_strip(struct Sequence *seq); +/* apply functions recursively */ +void seqbase_recursive_apply(struct ListBase *seqbase, int (*apply_func)(struct Sequence *seq, void *), void *arg); +void seq_recursive_apply(struct Sequence *seq, int (*apply_func)(struct Sequence *, void *), void *arg); + // extern void seq_free_sequence(struct Scene *scene, struct Sequence *seq); void seq_free_strip(struct Strip *strip); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index c92640e295e..84458b0e921 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -87,6 +87,20 @@ void printf_strip(Sequence *seq) fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0), seq_tx_get_final_right(seq, 0)); } +void seqbase_recursive_apply(ListBase *seqbase, int (*apply_func)(Sequence *seq, void *), void *arg) +{ + Sequence *iseq; + for(iseq= seqbase->first; iseq; iseq= iseq->next) { + seq_recursive_apply(iseq, apply_func, arg); + } +} + +void seq_recursive_apply(Sequence *seq, int (*apply_func)(Sequence *, void *), void *arg) +{ + if(apply_func(seq, arg) && seq->seqbase.first) + seqbase_recursive_apply(&seq->seqbase, apply_func, arg); +} + /* ********************************************************************** alloc / free functions ********************************************************************** */ @@ -252,7 +266,7 @@ void seq_free_editing(Scene *scene) { Editing *ed = scene->ed; MetaStack *ms; - Sequence *seq, *nseq; + Sequence *seq; if(ed==NULL) return; @@ -689,28 +703,22 @@ void sort_seq(Scene *scene) } -void clear_scene_in_allseqs(Scene *sce) +static int clear_scene_in_allseqs_cb(Sequence *seq, void *arg_pt) { - Scene *sce1; - Editing *ed; - Sequence *seq; - - /* when a scene is deleted: test all seqs */ - - sce1= G.main->scene.first; - while(sce1) { - if(sce1!=sce && sce1->ed) { - ed= sce1->ed; - - SEQ_BEGIN(ed, seq) { + if(seq->scene==(Scene *)arg_pt) + seq->scene= NULL; + return 1; +} - if(seq->scene==sce) seq->scene= 0; +void clear_scene_in_allseqs(Scene *scene) +{ + Scene *scene_iter; - } - SEQ_END + /* when a scene is deleted: test all seqs */ + for(scene_iter= G.main->scene.first; scene_iter; scene_iter= scene_iter->id.next) { + if(scene_iter != scene && scene_iter->ed) { + seqbase_recursive_apply(&scene_iter->ed->seqbase, clear_scene_in_allseqs_cb, scene); } - - sce1= sce1->id.next; } } @@ -2033,9 +2041,14 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int Render *re; RenderResult rres; char scenename[64]; - int have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first; - int sce_valid =sce && (sce->camera || have_seq); - + int have_seq= FALSE; + int sce_valid= FALSE; + + if(sce) { + have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first; + sce_valid= (sce->camera || have_seq); + } + if (se->ibuf == NULL && sce_valid && !build_proxy_run) { se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); if (se->ibuf) { @@ -3217,6 +3230,23 @@ static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) } #endif +static int seq_sound_reload_cb(Sequence *seq, void *arg_pt) +{ + if (seq->type==SEQ_SOUND && seq->sound) { + Scene *scene= (Scene *)arg_pt; + if(seq->sound_handle) + sound_delete_handle(scene, seq->sound_handle); + + seq->sound_handle = sound_new_handle(scene, seq->sound, seq->start, seq->start + seq->strip->len, 0); + return 0; + } + return 1; /* recurse meta's */ +} +void seqbase_sound_reload(Scene *scene, ListBase *seqbase) +{ + seqbase_recursive_apply(seqbase, seq_sound_reload_cb, (void *)scene); +} + /* seq funcs's for transforming internally notice the difference between start/end and left/right. -- cgit v1.2.3 From 3e23f002b42dc1892665e1705f9f107c4e047b8a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 19 Dec 2009 10:27:23 +0000 Subject: fix for non Euler-XYZ rotations... - Camera to 3D view didnt check for rotation order. - Fly mode didnt check for rotation order. added util functions. - object_apply_mat4(ob, mat4); applies a 4x4 matrix to an objects loc,scale,rot (accounting for rotation modes) - object_mat3_to_rot(ob, mat3, use_compat); apply a 3x3 matrix to the objects rotation, option to use a euler compatible with the existing euler. --- source/blender/blenkernel/BKE_object.h | 2 ++ source/blender/blenkernel/intern/object.c | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index aeb33cd3628..3e239e91453 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -93,8 +93,10 @@ void disable_speed_curve(int val); float bsystem_time(struct Scene *scene, struct Object *ob, float cfra, float ofs); void object_scale_to_mat3(struct Object *ob, float mat[][3]); void object_rot_to_mat3(struct Object *ob, float mat[][3]); +void object_mat3_to_rot(struct Object *ob, float mat[][3], int use_compat); void object_to_mat3(struct Object *ob, float mat[][3]); void object_to_mat4(struct Object *ob, float mat[][4]); +void object_apply_mat4(struct Object *ob, float mat[][4]); void set_no_parent_ipo(int val); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 9a7a3501031..676ab081533 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1618,6 +1618,32 @@ void object_rot_to_mat3(Object *ob, float mat[][3]) mul_m3_m3m3(mat, dmat, rmat); } +void object_mat3_to_rot(Object *ob, float mat[][3], int use_compat) +{ + if (ob->rotmode == ROT_MODE_QUAT) + mat3_to_quat(ob->quat, mat); + else if (ob->rotmode == ROT_MODE_AXISANGLE) + mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat); + else { + if(use_compat) { + float eul[3]; + VECCOPY(eul, ob->rot); + mat3_to_compatible_eulO(ob->rot, eul, ob->rotmode, mat); + } + else + mat3_to_eulO(ob->rot, ob->rotmode, mat); + } +} + +void object_apply_mat4(Object *ob, float mat[][4]) +{ + float mat3[3][3]; + VECCOPY(ob->loc, mat[3]); + mat4_to_size(ob->size, mat); + copy_m3_m4(mat3, mat); + object_mat3_to_rot(ob, mat3, 0); +} + void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ { float smat[3][3]; -- cgit v1.2.3 From be323efa3525031bc7b2f255543f4d57e2b5f9cc Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sat, 19 Dec 2009 22:40:45 +0000 Subject: Fix preview do_version bug (causing region type missing errors) The missing region was added to the wrong region base. Bump the subversion, new code to fix wrong region layouts saved in previous subversion and correct all old files correctly. --- 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 8a7f4da8cbf..8e7e698a986 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ struct bContext; struct ReportList; #define BLENDER_VERSION 250 -#define BLENDER_SUBVERSION 10 +#define BLENDER_SUBVERSION 11 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 -- cgit v1.2.3 From 54c9557b8595cfd830d1491875a70f85e3f6658d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 Dec 2009 01:02:08 +0000 Subject: Solidify modifier for Durian (allow cloth sim on single layer and make solid after) Mostly the same as the recently added editmode tool with some extras. * Options to disable filling in the rim between inner and outer surface, since its faster not to detect this in cases where its not needed. * Option to disable high quality normal calculation, mostly noticable when operating on building walls, not needed for cloth or more organic shapes. * Option to disable 'even thickness', again, not needed in some cases. Also options for creasing inner/outer and rim edges, need this for makign Sintels cloths solid since zero crease looks far too soft. note: * UVs and VCols etc are copied to the new skin however rim faces dont get the UVs or vcols set from the faces they are created from yet. * Normals are assumed to be pointing outwards * used patch from Uncle Entity as a template since it added the DNA and RNA entries but the actual modifier from the patch wasnt used. --- source/blender/blenkernel/intern/modifier.c | 436 ++++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e75203c6cde..732ba2a651e 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5807,6 +5807,432 @@ static int softbodyModifier_dependsOnTime(ModifierData *md) return 1; } +/* Solidify */ + + +typedef struct EdgeFaceRef { + int f1; /* init as -1 */ + int f2; +} EdgeFaceRef; + +static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3]) +{ + int i, numVerts, numEdges, numFaces; + MFace *mface, *mf; + MVert *mvert, *mv; + + float (*face_nors)[3]; + float *f_no; + int calc_face_nors= 0; + + numVerts = dm->getNumVerts(dm); + numEdges = dm->getNumEdges(dm); + numFaces = dm->getNumFaces(dm); + mface = dm->getFaceArray(dm); + mvert = dm->getVertArray(dm); + + /* we don't want to overwrite any referenced layers */ + + /* + Dosnt work here! + mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); + cddm->mvert = mv; + */ + + face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); + if(!face_nors) { + calc_face_nors = 1; + face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, numFaces); + } + + mv = mvert; + mf = mface; + + { + EdgeHash *edge_hash = BLI_edgehash_new(); + EdgeHashIterator *edge_iter; + int edge_ref_count = 0; + int ed_v1, ed_v2; /* use when getting the key */ + EdgeFaceRef *edge_ref_array = MEM_callocN(numEdges * sizeof(EdgeFaceRef), "Edge Connectivity"); + EdgeFaceRef *edge_ref; + float edge_normal[3]; + + /* This function adds an edge hash if its not there, and adds the face index */ +#define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \ + edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \ + if (!edge_ref) { \ + edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \ + edge_ref->f1=i; \ + edge_ref->f2=-1; \ + BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \ + } else { \ + edge_ref->f2=i; \ + } + + for(i = 0; i < numFaces; i++, mf++) { + f_no = face_nors[i]; + + if(mf->v4) { + if(calc_face_nors) + normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); + + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v4); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v4, mf->v1); + } else { + if(calc_face_nors) + normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); + + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3); + NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v1); + } + } + + for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) { + /* Get the edge vert indicies, and edge value (the face indicies that use it)*/ + BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2); + edge_ref = BLI_edgehashIterator_getValue(edge_iter); + + if (edge_ref->f2 != -1) { + /* We have 2 faces using this edge, calculate the edges normal + * using the angle between the 2 faces as a weighting */ + add_v3_v3v3(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]); + normalize_v3(edge_normal); + mul_v3_fl(edge_normal, angle_normalized_v3v3(face_nors[edge_ref->f1], face_nors[edge_ref->f2])); + } else { + /* only one face attached to that edge */ + /* an edge without another attached- the weight on this is + * undefined, M_PI/2 is 90d in radians and that seems good enough */ + VECCOPY(edge_normal, face_nors[edge_ref->f1]) + mul_v3_fl(edge_normal, M_PI/2); + } + add_v3_v3(temp_nors[ed_v1], edge_normal); + add_v3_v3(temp_nors[ed_v2], edge_normal); + } + BLI_edgehashIterator_free(edge_iter); + BLI_edgehash_free(edge_hash, NULL); + MEM_freeN(edge_ref_array); + } + + /* normalize vertex normals and assign */ + for(i = 0; i < numVerts; i++, mv++) { + if(normalize_v3(temp_nors[i]) == 0.0f) { + normal_short_to_float_v3(temp_nors[i], mv->no); + } + } +} + +static void solidifyModifier_initData(ModifierData *md) +{ + SolidifyModifierData *smd = (SolidifyModifierData*) md; + smd->offset = 0.01f; + smd->flag = MOD_SOLIDIFY_EVEN | MOD_SOLIDIFY_RIM | MOD_SOLIDIFY_NORMAL_CALC; +} + +static void solidifyModifier_copyData(ModifierData *md, ModifierData *target) +{ + SolidifyModifierData *smd = (SolidifyModifierData*) md; + SolidifyModifierData *tsmd = (SolidifyModifierData*) target; + tsmd->offset = smd->offset; + tsmd->crease_inner = smd->crease_inner; + tsmd->crease_outer = smd->crease_outer; + tsmd->crease_rim = smd->crease_rim; + strcpy(tsmd->vgroup, smd->vgroup); +} + +static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, + Object *ob, + DerivedMesh *dm, + int useRenderParams, + int isFinalCalc) +{ + int i; + DerivedMesh *result; + SolidifyModifierData *smd = (SolidifyModifierData*) md; + + MFace *mf, *mface, *orig_mface; + MEdge *ed, *medge, *orig_medge; + MVert *mv, *mvert, *orig_mvert; + + int numVerts = dm->getNumVerts(dm); + int numEdges = dm->getNumEdges(dm); + int numFaces = dm->getNumFaces(dm); + + /* use for edges */ + int *new_vert_arr= NULL; + int newFaces = 0; + + int *new_edge_arr= NULL; + int newEdges = 0; + + float (*vert_nors)[3]= NULL; + + orig_mface = dm->getFaceArray(dm); + orig_medge = dm->getEdgeArray(dm); + orig_mvert = dm->getVertArray(dm); + + if(smd->flag & MOD_SOLIDIFY_RIM) { + EdgeHash *edgehash = BLI_edgehash_new(); + EdgeHashIterator *ehi; + int v1, v2; + int *edge_users; + + for(i=0, mv=orig_mvert; iflag &= ~ME_VERT_TMP_TAG; + } + + for(i=0, ed=orig_medge; iv1, ed->v2, (void *)i); + } + + edge_users= MEM_callocN(sizeof(int) * numEdges, "solid_mod edges"); + +/* will be incorrect if an edge happens to have this many face users (very unlikely) */ +#define LARGE_NUM 1000000 + + for(i=0, mf=orig_mface; iv4) { + edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v1, mf->v2)] += mf->v1 < mf->v2 ? 1:LARGE_NUM; + edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v2, mf->v3)] += mf->v2 < mf->v3 ? 1:LARGE_NUM; + edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v3, mf->v4)] += mf->v3 < mf->v4 ? 1:LARGE_NUM; + edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v4, mf->v1)] += mf->v4 < mf->v1 ? 1:LARGE_NUM; + } + else { + edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v1, mf->v2)] += mf->v1 < mf->v2 ? 1:LARGE_NUM; + edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v2, mf->v3)] += mf->v2 < mf->v3 ? 1:LARGE_NUM; + edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v3, mf->v1)] += mf->v3 < mf->v1 ? 1:LARGE_NUM; + } + } + + new_edge_arr= MEM_callocN(sizeof(int) * numEdges, "solid_mod arr"); + + ehi= BLI_edgehashIterator_new(edgehash); + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + int eidx= (int)BLI_edgehashIterator_getValue(ehi); + if(edge_users[eidx] == 1 || edge_users[eidx] == LARGE_NUM) { + BLI_edgehashIterator_getKey(ehi, &v1, &v2); + + /* we need to order the edge */ + if(edge_users[eidx] == LARGE_NUM) { + eidx= -(eidx + 1); + } + + orig_mvert[v1].flag |= ME_VERT_TMP_TAG; + orig_mvert[v2].flag |= ME_VERT_TMP_TAG; + new_edge_arr[newFaces]= eidx; + newFaces++; + } + } + BLI_edgehashIterator_free(ehi); + MEM_freeN(edge_users); + +#undef LARGE_NUM + + new_vert_arr= MEM_callocN(sizeof(int) * numVerts, "solid_mod new_varr"); + for(i=0, mv=orig_mvert; iflag & ME_VERT_TMP_TAG) { + new_vert_arr[newEdges] = i; + newEdges++; + + mv->flag &= ~ME_VERT_TMP_TAG; + } + } + + BLI_edgehash_free(edgehash, NULL); + } + + if(smd->flag & MOD_SOLIDIFY_NORMAL_CALC) { + vert_nors= MEM_callocN(sizeof(float) * numVerts * 3, "mod_solid_vno_hq"); + dm_calc_normal(dm, vert_nors); + } + + result = CDDM_from_template(dm, numVerts * 2, (numEdges * 2) + newEdges, (numFaces * 2) + newFaces); + + mface = result->getFaceArray(result); + medge = result->getEdgeArray(result); + mvert = result->getVertArray(result); + + DM_copy_face_data(dm, result, 0, 0, numFaces); + DM_copy_face_data(dm, result, 0, numFaces, numFaces); + + DM_copy_edge_data(dm, result, 0, 0, numEdges); + DM_copy_edge_data(dm, result, 0, numEdges, numEdges); + + DM_copy_vert_data(dm, result, 0, 0, numVerts); + DM_copy_vert_data(dm, result, 0, numVerts, numVerts); + + { + static int corner_indices[4] = {2, 1, 0, 3}; + int is_quad; + + for(i=0, mf=mface+numFaces; iv1 += numVerts; + mf->v2 += numVerts; + mf->v3 += numVerts; + if(mf->v4) + mf->v4 += numVerts; + + /* Flip face normal */ + { + is_quad = mf->v4; + SWAP(int, mf->v1, mf->v3); + DM_swap_face_data(result, i+numFaces, corner_indices); + test_index_face(mf, &result->faceData, numFaces, is_quad ? 4:3); + } + } + } + + for(i=0, ed=medge+numEdges; iv1 += numVerts; + ed->v2 += numVerts; + } + + if((smd->flag & MOD_SOLIDIFY_EVEN) == 0) { + /* no even thickness, very simple */ + float scalar_short = smd->offset / 32767.0f; + + if(smd->offset < 0.0f) mv= mvert+numVerts; + else mv= mvert; + + for(i=0; ico[0] += mv->no[0] * scalar_short; + mv->co[1] += mv->no[1] * scalar_short; + mv->co[2] += mv->no[2] * scalar_short; + } + } + else { + /* make a face normal layer if not present */ + float (*face_nors)[3]; + int face_nors_calc= 0; + + /* same as EM_solidify() in editmesh_lib.c */ + float *vert_angles= MEM_callocN(sizeof(float) * numVerts * 2, "mod_solid_pair"); /* 2 in 1 */ + float *vert_accum= vert_angles + numVerts; + float face_angles[4]; + int i, j, vidx; + + face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); + if(!face_nors) { + face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, dm->numFaceData); + face_nors_calc= 1; + } + + if(vert_nors==NULL) { + vert_nors= MEM_mallocN(sizeof(float) * numVerts * 3, "mod_solid_vno"); + for(i=0, mv=mvert; ino); + } + } + + for(i=0, mf=mface; iv4) + normal_quad_v3(face_nors[i], mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); + else + normal_tri_v3(face_nors[i] , mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co); + } + + if(mf->v4) { + angle_quad_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); + j= 3; + } + else { + angle_tri_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co); + j= 2; + } + + for(; j>=0; j--) { + vidx = *(&mf->v1 + j); + vert_accum[vidx] += face_angles[j]; + vert_angles[vidx]+= shell_angle_to_dist(angle_normalized_v3v3(vert_nors[vidx], face_nors[i])) * face_angles[j]; + } + } + + if(smd->offset < 0.0f) mv= mvert+numVerts; + else mv= mvert; + + for(i=0; ico, vert_nors[i], smd->offset * (vert_angles[i] / vert_accum[i])); + } + } + + MEM_freeN(vert_angles); + } + + if(vert_nors) + MEM_freeN(vert_nors); + + if(smd->flag & MOD_SOLIDIFY_RIM) { + /* add faces & edges */ + ed= medge + (numEdges * 2); + for(i=0; iv1= new_vert_arr[i]; + ed->v2= new_vert_arr[i] + numVerts; + ed->flag |= ME_EDGEDRAW; + + if(smd->crease_rim) + ed->crease= smd->crease_rim * 255.0f; + } + + /* faces */ + mf= mface + (numFaces * 2); + for(i=0; iv1= ed->v1; + mf->v2= ed->v2; + mf->v3= ed->v2 + numVerts; + mf->v4= ed->v1 + numVerts; + } + else { + mf->v1= ed->v2; + mf->v2= ed->v1; + mf->v3= ed->v1 + numVerts; + mf->v4= ed->v2 + numVerts; + } + + if(smd->crease_outer > 0.0f) + ed->crease= smd->crease_outer * 255.0f; + + if(smd->crease_inner > 0.0f) { + ed= medge + (numEdges + eidx); + ed->crease= smd->crease_inner * 255.0f; + } + } + + MEM_freeN(new_vert_arr); + MEM_freeN(new_edge_arr); + } + + return result; +} + +static DerivedMesh *solidifyModifier_applyModifierEM(ModifierData *md, + Object *ob, + EditMesh *editData, + DerivedMesh *derivedData) +{ + return solidifyModifier_applyModifier(md, ob, derivedData, 0, 1); +} + /* Smoke */ static void smokeModifier_initData(ModifierData *md) @@ -8788,6 +9214,16 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->deformVertsEM = shapekeyModifier_deformVertsEM; mti->deformMatricesEM = shapekeyModifier_deformMatricesEM; + mti = INIT_TYPE(Solidify); + mti->type = eModifierTypeType_Constructive; + mti->flags = eModifierTypeFlag_AcceptsMesh + //| eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; + mti->initData = solidifyModifier_initData; + mti->copyData = solidifyModifier_copyData; + mti->applyModifier = solidifyModifier_applyModifier; + mti->applyModifierEM = solidifyModifier_applyModifierEM; typeArrInit = 0; #undef INIT_TYPE } -- cgit v1.2.3 From 824b76332202c33da0a9ec6fe803e4eb752618d5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 Dec 2009 08:37:30 +0000 Subject: solidify modifier - rim faces now copy values from the faces they extrude from (material, face flags but not uvs or vcols yet) this doesnt work in editmode yet. --- source/blender/blenkernel/intern/modifier.c | 63 ++++++++++++++++++----------- 1 file changed, 40 insertions(+), 23 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 732ba2a651e..e4728602d65 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5967,6 +5967,8 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, int *new_edge_arr= NULL; int newEdges = 0; + int *edge_users= NULL; + float (*vert_nors)[3]= NULL; orig_mface = dm->getFaceArray(dm); @@ -5977,7 +5979,7 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, EdgeHash *edgehash = BLI_edgehash_new(); EdgeHashIterator *ehi; int v1, v2; - int *edge_users; + int edu, eidx; for(i=0, mv=orig_mvert; iflag &= ~ME_VERT_TMP_TAG; @@ -5987,38 +5989,47 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, BLI_edgehash_insert(edgehash, ed->v1, ed->v2, (void *)i); } - edge_users= MEM_callocN(sizeof(int) * numEdges, "solid_mod edges"); +#define INVALID_UNUSED -1 +#define INVALID_PAIR -2 + +#define ADD_EDGE_USER(_v1, _v2) \ + eidx= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, _v1, _v2)); \ + if(edge_users[eidx] == INVALID_UNUSED) { \ + edge_users[eidx]= (_v1 < _v2) ? i:(i+numFaces); \ + } else { \ + edge_users[eidx]= INVALID_PAIR; \ + } \ -/* will be incorrect if an edge happens to have this many face users (very unlikely) */ -#define LARGE_NUM 1000000 + + edge_users= MEM_mallocN(sizeof(int) * numEdges, "solid_mod edges"); + memset(edge_users, INVALID_UNUSED, sizeof(int) * numEdges); for(i=0, mf=orig_mface; iv4) { - edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v1, mf->v2)] += mf->v1 < mf->v2 ? 1:LARGE_NUM; - edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v2, mf->v3)] += mf->v2 < mf->v3 ? 1:LARGE_NUM; - edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v3, mf->v4)] += mf->v3 < mf->v4 ? 1:LARGE_NUM; - edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v4, mf->v1)] += mf->v4 < mf->v1 ? 1:LARGE_NUM; + ADD_EDGE_USER(mf->v1, mf->v2); + ADD_EDGE_USER(mf->v2, mf->v3); + ADD_EDGE_USER(mf->v3, mf->v4); + ADD_EDGE_USER(mf->v4, mf->v1); } else { - edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v1, mf->v2)] += mf->v1 < mf->v2 ? 1:LARGE_NUM; - edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v2, mf->v3)] += mf->v2 < mf->v3 ? 1:LARGE_NUM; - edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v3, mf->v1)] += mf->v3 < mf->v1 ? 1:LARGE_NUM; + ADD_EDGE_USER(mf->v1, mf->v2); + ADD_EDGE_USER(mf->v2, mf->v3); + ADD_EDGE_USER(mf->v3, mf->v1); } } +#undef ADD_EDGE_USER +#undef INVALID_UNUSED +#undef INVALID_PAIR + + new_edge_arr= MEM_callocN(sizeof(int) * numEdges, "solid_mod arr"); ehi= BLI_edgehashIterator_new(edgehash); for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - int eidx= (int)BLI_edgehashIterator_getValue(ehi); - if(edge_users[eidx] == 1 || edge_users[eidx] == LARGE_NUM) { + int eidx= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + if(edge_users[eidx] >= 0) { BLI_edgehashIterator_getKey(ehi, &v1, &v2); - - /* we need to order the edge */ - if(edge_users[eidx] == LARGE_NUM) { - eidx= -(eidx + 1); - } - orig_mvert[v1].flag |= ME_VERT_TMP_TAG; orig_mvert[v2].flag |= ME_VERT_TMP_TAG; new_edge_arr[newFaces]= eidx; @@ -6026,9 +6037,8 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, } } BLI_edgehashIterator_free(ehi); - MEM_freeN(edge_users); -#undef LARGE_NUM + new_vert_arr= MEM_callocN(sizeof(int) * numVerts, "solid_mod new_varr"); for(i=0, mv=orig_mvert; i= numFaces) { + fidx -= numFaces; flip= 1; } else { @@ -6196,6 +6207,9 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, ed= medge + eidx; + /* copy most of the face settings */ + *mf= mface[fidx]; + if(flip) { mf->v1= ed->v1; mf->v2= ed->v2; @@ -6207,6 +6221,8 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, mf->v2= ed->v1; mf->v3= ed->v1 + numVerts; mf->v4= ed->v2 + numVerts; + + } if(smd->crease_outer > 0.0f) @@ -6220,6 +6236,7 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, MEM_freeN(new_vert_arr); MEM_freeN(new_edge_arr); + MEM_freeN(edge_users); } return result; -- cgit v1.2.3 From f7f06d96f3c13623448d899e1fe2577ed6cbf996 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 Dec 2009 10:16:04 +0000 Subject: Solidify rim faces now get face data from the faces they extrude from, (UV and VCol support) --- source/blender/blenkernel/intern/modifier.c | 38 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e4728602d65..e0640a76f43 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5968,6 +5968,7 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, int newEdges = 0; int *edge_users= NULL; + char *edge_order= NULL; float (*vert_nors)[3]= NULL; @@ -5979,42 +5980,44 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, EdgeHash *edgehash = BLI_edgehash_new(); EdgeHashIterator *ehi; int v1, v2; - int edu, eidx; + int eidx; for(i=0, mv=orig_mvert; iflag &= ~ME_VERT_TMP_TAG; } for(i=0, ed=orig_medge; iv1, ed->v2, (void *)i); + BLI_edgehash_insert(edgehash, ed->v1, ed->v2, SET_INT_IN_POINTER(i)); } #define INVALID_UNUSED -1 #define INVALID_PAIR -2 -#define ADD_EDGE_USER(_v1, _v2) \ +#define ADD_EDGE_USER(_v1, _v2, edge_ord) \ eidx= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, _v1, _v2)); \ if(edge_users[eidx] == INVALID_UNUSED) { \ edge_users[eidx]= (_v1 < _v2) ? i:(i+numFaces); \ + edge_order[eidx]= edge_ord; \ } else { \ edge_users[eidx]= INVALID_PAIR; \ } \ edge_users= MEM_mallocN(sizeof(int) * numEdges, "solid_mod edges"); + edge_order= MEM_mallocN(sizeof(char) * numEdges, "solid_mod eorder"); memset(edge_users, INVALID_UNUSED, sizeof(int) * numEdges); for(i=0, mf=orig_mface; iv4) { - ADD_EDGE_USER(mf->v1, mf->v2); - ADD_EDGE_USER(mf->v2, mf->v3); - ADD_EDGE_USER(mf->v3, mf->v4); - ADD_EDGE_USER(mf->v4, mf->v1); + ADD_EDGE_USER(mf->v1, mf->v2, 0); + ADD_EDGE_USER(mf->v2, mf->v3, 1); + ADD_EDGE_USER(mf->v3, mf->v4, 2); + ADD_EDGE_USER(mf->v4, mf->v1, 3); } else { - ADD_EDGE_USER(mf->v1, mf->v2); - ADD_EDGE_USER(mf->v2, mf->v3); - ADD_EDGE_USER(mf->v3, mf->v1); + ADD_EDGE_USER(mf->v1, mf->v2, 0); + ADD_EDGE_USER(mf->v2, mf->v3, 1); + ADD_EDGE_USER(mf->v3, mf->v1, 2); } } @@ -6178,6 +6181,13 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, MEM_freeN(vert_nors); if(smd->flag & MOD_SOLIDIFY_RIM) { + + static int edge_indices[4][4] = { + {1, 0, 0, 1}, + {2, 1, 1, 2}, + {3, 2, 2, 3}, + {0, 3, 3, 0}}; + /* add faces & edges */ ed= medge + (numEdges * 2); for(i=0; iv1= ed->v1; mf->v2= ed->v2; mf->v3= ed->v2 + numVerts; mf->v4= ed->v1 + numVerts; } else { + DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]); + mf->v1= ed->v2; mf->v2= ed->v1; mf->v3= ed->v1 + numVerts; @@ -6237,6 +6250,7 @@ static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md, MEM_freeN(new_vert_arr); MEM_freeN(new_edge_arr); MEM_freeN(edge_users); + MEM_freeN(edge_order); } return result; -- cgit v1.2.3 From 5832f2fb7bd396e45690b1765103d4136694845a Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Mon, 21 Dec 2009 11:19:07 +0000 Subject: =?UTF-8?q?*=20Rest=20length=20parameter=20for=20harmonic=20force?= =?UTF-8?q?=20springs.=20Implementation=20is=20a=20slightly=20modified=20v?= =?UTF-8?q?ersion=20of=20the=20patch=20provided=20by=20Ra=C3=BAl=20Fern?= =?UTF-8?q?=C3=A1ndez=20Hern=C3=A1ndez=20(Farsthary).=20*=20Also=20added?= =?UTF-8?q?=20a=20"multiple=20springs"=20option=20to=20use=20every=20effec?= =?UTF-8?q?tor=20point=20as=20a=20harmonic=20spring=20instead=20of=20just?= =?UTF-8?q?=20one.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/blender/blenkernel/intern/effect.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 6d63553396d..83f63c9ffb2 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -128,7 +128,6 @@ PartDeflect *object_add_collision_fields(int type) pd->seed = ((unsigned int)(ceil(PIL_check_seconds_timer()))+1) % 128; pd->f_strength = 1.0f; pd->f_damp = 1.0f; - pd->f_size = 1.0f; /* set sensible defaults based on type */ switch(type) { @@ -139,6 +138,9 @@ PartDeflect *object_add_collision_fields(int type) pd->shape = PFIELD_SHAPE_PLANE; pd->f_flow = 1.0f; /* realistic wind behavior */ break; + case PFIELD_TEXTURE: + pd->f_size = 1.0f; + break; } pd->flag = PFIELD_DO_LOCATION|PFIELD_DO_ROTATION; @@ -693,6 +695,10 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin sub_v3_v3v3(efd->vec_to_point, point->loc, efd->loc); efd->distance = len_v3(efd->vec_to_point); + /* rest length for harmonic effector, will have to see later if this could be extended to other effectors */ + if(eff->pd->forcefield == PFIELD_HARMONIC && eff->pd->f_size) + mul_v3_fl(efd->vec_to_point, (efd->distance-eff->pd->f_size)/efd->distance); + if(eff->flag & PE_USE_NORMAL_DATA) { VECCOPY(efd->vec_to_point2, efd->vec_to_point); VECCOPY(efd->nor2, efd->nor); @@ -735,7 +741,7 @@ static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoin */ efd->charge = eff->pd->f_strength; } - else if(eff->pd->forcefield == PFIELD_HARMONIC) { + else if(eff->pd->forcefield == PFIELD_HARMONIC && (eff->pd->flag & PFIELD_MULTIPLE_SPRINGS)==0) { /* every particle is mapped to only one harmonic effector particle */ *p= point->index % eff->psys->totpart; *tot= *p + 1; -- cgit v1.2.3 From 29ea21e6bd6d6813a6b8fd58d7085e9efce9b494 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 21 Dec 2009 15:55:10 +0000 Subject: Multires: added back Reshape function, to copy vertex locations from another mesh. --- source/blender/blenkernel/intern/multires.c | 75 +++++++++++++---------------- 1 file changed, 34 insertions(+), 41 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 88c6788b723..f5414567da8 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -63,6 +63,7 @@ static const int multires_max_levels = 13; static const int multires_grid_tot[] = {0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; static const int multires_side_tot[] = {0, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; +static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert); static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl); MultiresModifierData *find_multires_modifier(Object *ob) @@ -106,6 +107,27 @@ static void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lv CLAMP(mmd->renderlvl, 0, mmd->totlvl); } +static void multires_dm_mark_as_modified(DerivedMesh *dm) +{ + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; + ccgdm->multires.modified = 1; +} + +void multires_mark_as_modified(Object *ob) +{ + if(ob && ob->derivedFinal) + multires_dm_mark_as_modified(ob->derivedFinal); +} + +void multires_force_update(Object *ob) +{ + if(ob && ob->derivedFinal) { + ob->derivedFinal->needsFree =1; + ob->derivedFinal->release(ob->derivedFinal); + ob->derivedFinal = NULL; + } +} + /* XXX */ #if 0 void multiresModifier_join(Object *ob) @@ -168,30 +190,22 @@ void multiresModifier_join(Object *ob) } #endif -/* Returns 0 on success, 1 if the src's totvert doesn't match */ +/* Returns 1 on success, 0 if the src's totvert doesn't match */ int multiresModifier_reshape(MultiresModifierData *mmd, Object *dst, Object *src) { - /* XXX */ -#if 0 - Mesh *src_me = get_mesh(src); + DerivedMesh *srcdm = src->derivedFinal; DerivedMesh *mrdm = dst->derivedFinal; - if(mrdm && mrdm->getNumVerts(mrdm) == src_me->totvert) { - MVert *mvert = CDDM_get_verts(mrdm); - int i; + if(mrdm && srcdm && mrdm->getNumVerts(mrdm) == srcdm->getNumVerts(srcdm)) { + multires_mvert_to_ss(mrdm, srcdm->getVertArray(srcdm)); - for(i = 0; i < src_me->totvert; ++i) - copy_v3_v3(mvert[i].co, src_me->mvert[i].co); - mrdm->needsFree = 1; - MultiresDM_mark_as_modified(mrdm); - mrdm->release(mrdm); - dst->derivedFinal = NULL; + multires_dm_mark_as_modified(mrdm); + multires_force_update(dst); - return 0; + return 1; } -#endif - return 1; + return 0; } static void column_vectors_to_mat3(float mat[][3], float v1[3], float v2[3], float v3[3]) @@ -242,7 +256,7 @@ static void multires_copy_dm_grid(DMGridData *gridA, DMGridData *gridB, int size } /* direction=1 for delete higher, direction=0 for lower (not implemented yet) */ -void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object *ob, int direction) +void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction) { Mesh *me = get_mesh(ob); int lvl = multires_get_level(ob, mmd, 0); @@ -621,27 +635,6 @@ static void multiresModifier_update(DerivedMesh *dm) } } -static void multires_dm_mark_as_modified(struct DerivedMesh *dm) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; - ccgdm->multires.modified = 1; -} - -void multires_mark_as_modified(struct Object *ob) -{ - if(ob && ob->derivedFinal) - multires_dm_mark_as_modified(ob->derivedFinal); -} - -void multires_force_update(Object *ob) -{ - if(ob && ob->derivedFinal) { - ob->derivedFinal->needsFree =1; - ob->derivedFinal->release(ob->derivedFinal); - ob->derivedFinal = NULL; - } -} - void multires_stitch_grids(Object *ob) { /* utility for smooth brush */ @@ -661,7 +654,7 @@ void multires_stitch_grids(Object *ob) } } -struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob, +DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob, int useRenderParams, int isFinalCalc) { Mesh *me= ob->data; @@ -973,7 +966,7 @@ static void multires_load_old_faces(ListBase **fmap, ListBase **emap, MultiresLe } } -static void multires_old_mvert_to_ss(DerivedMesh *dm, MVert *mvert) +static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; @@ -1197,7 +1190,7 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) MEM_freeN(vvmap); - multires_old_mvert_to_ss(dm, vdst); + multires_mvert_to_ss(dm, vdst); } -- cgit v1.2.3 From 1f8cd19d4bc76b294841f3495132ecbdf9964228 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 Dec 2009 16:57:39 +0000 Subject: removing sequence strip overlap didnt adjust the animation key time single images were not having their animation data transformed correctly made sequence strip opacity 0-1 rather then 0-100 in RNA --- source/blender/blenkernel/BKE_sequencer.h | 4 ++-- source/blender/blenkernel/intern/sequencer.c | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index c078b92af2d..070d98ce25f 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -188,8 +188,8 @@ void seq_single_fix(struct Sequence *seq); int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test); struct ListBase *seq_seqbase(struct ListBase *seqbase, struct Sequence *seq); void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); -int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test); -int shuffle_seq_time(ListBase * seqbasep); +int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test, struct Scene *evil_scene); +int shuffle_seq_time(ListBase * seqbasep, struct Scene *evil_scene); int seqbase_isolated_sel_check(struct ListBase *seqbase); void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 84458b0e921..aa81cea79f5 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3442,13 +3442,15 @@ int seq_test_overlap(ListBase * seqbasep, Sequence *test) } -static void seq_translate(Sequence *seq, int delta) +static void seq_translate(Scene *evil_scene, Sequence *seq, int delta) { + seq_offset_animdata(evil_scene, seq, delta); seq->start += delta; + if(seq->type==SEQ_META) { Sequence *seq_child; for(seq_child= seq->seqbase.first; seq_child; seq_child= seq_child->next) { - seq_translate(seq_child, delta); + seq_translate(evil_scene, seq_child, delta); } } @@ -3456,7 +3458,7 @@ static void seq_translate(Sequence *seq, int delta) } /* return 0 if there werent enough space */ -int shuffle_seq(ListBase * seqbasep, Sequence *test) +int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene) { int orig_machine= test->machine; test->machine++; @@ -3484,7 +3486,7 @@ int shuffle_seq(ListBase * seqbasep, Sequence *test) test->machine= orig_machine; new_frame = new_frame + (test->start-test->startdisp); /* adjust by the startdisp */ - seq_translate(test, new_frame - test->start); + seq_translate(evil_scene, test, new_frame - test->start); calc_sequence(test); return 0; @@ -3540,7 +3542,7 @@ static int shuffle_seq_time_offset(ListBase * seqbasep, char dir) return tot_ofs; } -int shuffle_seq_time(ListBase * seqbasep) +int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene) { /* note: seq->tmp is used to tag strips to move */ @@ -3553,7 +3555,7 @@ int shuffle_seq_time(ListBase * seqbasep) if(offset) { for(seq= seqbasep->first; seq; seq= seq->next) { if(seq->tmp) { - seq_translate(seq, offset); + seq_translate(evil_scene, seq, offset); seq->flag &= ~SEQ_OVERLAP; } } -- cgit v1.2.3 From e207d045322db4656f42f68ae9fa092ac1478635 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 22 Dec 2009 10:04:15 +0000 Subject: quite a few python panels (10 or so) had names longer then the PanelType allowed, for panels it would fail silently but for menu's it meant further references would give errors. increase the registered class name from 32 to 64 and raise an error if the limit reached. --- source/blender/blenkernel/BKE_screen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index bf01ef0ec60..c9d1caa1cfe 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -55,7 +55,7 @@ struct uiMenuItem; ED_spacetypes_init() in editors/area/spacetypes.c */ /* an editor in Blender is a combined ScrArea + SpaceType + SpaceData */ -#define BKE_ST_MAXNAME 32 +#define BKE_ST_MAXNAME 64 typedef struct SpaceType { struct SpaceType *next, *prev; -- cgit v1.2.3 From 5a3ac3ceeb0d3550c14987f5cfd607e1ad126e64 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 22 Dec 2009 10:14:13 +0000 Subject: Assorted F-Curve/Keyframe API stuff (for use with some Sequencer editing): * Added function for F-Curves to find the F-Curves in a given list which affect some named data, such as bones, nodes, or sequence strips. * Added a BezTriple offsetting callback to be used with the F-Curve+Keyframe loopers in use for many of the keyframe editing tools. --- source/blender/blenkernel/BKE_fcurve.h | 7 ++- source/blender/blenkernel/intern/fcurve.c | 85 ++++++++++++++++++++++--------- 2 files changed, 67 insertions(+), 25 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 5888c6d7530..fa6b8969edb 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -158,7 +158,12 @@ void copy_fcurves(ListBase *dst, ListBase *src); struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index); /* high level function to get an fcurve from C without having the rna */ -struct FCurve *id_data_find_fcurve(ID* id, void *data, struct StructRNA *type, char *prop_name, int index); +struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, char *prop_name, int index); + +/* Get list of LinkData's containing pointers to the F-Curves which control the types of data indicated + * e.g. numMatches = list_find_data_fcurves(matches, &act->curves, "pose.bones[", "MyFancyBone"); + */ +int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName); /* Binary search algorithm for finding where to 'insert' BezTriple with given frame number. * Returns the index to insert at (data already at that index will be offset if replace is 0) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index b5f3d0a4be0..d5e033652a8 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -167,53 +167,42 @@ void copy_fcurves (ListBase *dst, ListBase *src) } } -/* ---------------------- Relink --------------------------- */ - -#if 0 -/* uses id->newid to match pointers with other copied data - * - called after single-user or other such - */ - if (icu->driver) - ID_NEW(icu->driver->ob); -#endif - /* --------------------- Finding -------------------------- */ +/* high level function to get an fcurve from C without having the rna */ FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, char *prop_name, int index) { /* anim vars */ - AnimData *adt; + AnimData *adt= BKE_animdata_from_id(id); FCurve *fcu= NULL; /* rna vars */ PointerRNA ptr; PropertyRNA *prop; char *path; - - adt= BKE_animdata_from_id(id); - + /* only use the current action ??? */ - if(adt==NULL || adt->action==NULL) + if (ELEM(NULL, adt, adt->action)) return NULL; - + RNA_pointer_create(id, type, data, &ptr); prop = RNA_struct_find_property(&ptr, prop_name); - - if(prop) { + + if (prop) { path= RNA_path_from_ID_to_property(&ptr, prop); - - if(path) { + + if (path) { /* animation takes priority over drivers */ - if(adt->action && adt->action->curves.first) + if ((adt->action) && (adt->action->curves.first)) fcu= list_find_fcurve(&adt->action->curves, path, index); - + /* if not animated, check if driven */ #if 0 - if(!fcu && (adt->drivers.first)) { + if ((fcu == NULL) && (adt->drivers.first)) { fcu= list_find_fcurve(&adt->drivers, path, but->rnaindex); } #endif - + MEM_freeN(path); } } @@ -245,6 +234,54 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array return NULL; } +/* Get list of LinkData's containing pointers to the F-Curves which control the types of data indicated + * Lists... + * - dst: list of LinkData's matching the criteria returned. + * List must be freed after use, and is assumed to be empty when passed. + * - src: list of F-Curves to search through + * Filters... + * - dataPrefix: i.e. 'pose.bones[' or 'nodes[' + * - dataName: name of entity within "" immediately following the prefix + */ +int list_find_data_fcurves (ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName) +{ + FCurve *fcu; + int matches = 0; + + /* sanity checks */ + if (ELEM4(NULL, dst, src, dataPrefix, dataName)) + return 0; + else if ((dataPrefix[0] == 0) || (dataName[0] == 0)) + return 0; + + /* search each F-Curve one by one */ + for (fcu= src->first; fcu; fcu= fcu->next) { + /* check if quoted string matches the path */ + if ((fcu->rna_path) && strstr(fcu->rna_path, dataPrefix)) { + char *quotedName= BLI_getQuotedStr(fcu->rna_path, dataPrefix); + + if (quotedName) { + /* check if the quoted name matches the required name */ + if (strcmp(quotedName, dataName) == 0) { + LinkData *ld= MEM_callocN(sizeof(LinkData), "list_find_data_fcurves"); + + ld->data= fcu; + BLI_addtail(dst, ld); + + matches++; + } + + /* always free the quoted string, since it needs freeing */ + MEM_freeN(quotedName); + } + } + } + + /* return the number of matches */ + return matches; +} + + /* threshold for binary-searching keyframes - threshold here should be good enough for now, but should become userpref */ #define BEZT_BINARYSEARCH_THRESH 0.00001f -- cgit v1.2.3 From 3221dea46eeb6c5441c4617d704ffb3e8caeeca3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 22 Dec 2009 10:48:13 +0000 Subject: clone and stencil layer access added, renamed mask to stencil layer internally --- source/blender/blenkernel/BKE_customdata.h | 8 ++++---- source/blender/blenkernel/intern/customdata.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 5f13e702343..65c02d1abb9 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -198,11 +198,11 @@ int CustomData_get_named_layer_index(const struct CustomData *data, int type, ch int CustomData_get_active_layer_index(const struct CustomData *data, int type); int CustomData_get_render_layer_index(const struct CustomData *data, int type); int CustomData_get_clone_layer_index(const struct CustomData *data, int type); -int CustomData_get_mask_layer_index(const struct CustomData *data, int type); +int CustomData_get_stencil_layer_index(const struct CustomData *data, int type); int CustomData_get_active_layer(const struct CustomData *data, int type); int CustomData_get_render_layer(const struct CustomData *data, int type); int CustomData_get_clone_layer(const struct CustomData *data, int type); -int CustomData_get_mask_layer(const struct CustomData *data, int type); +int CustomData_get_stencil_layer(const struct CustomData *data, int type); /* copies the data from source to the data element at index in the first * layer of type @@ -231,13 +231,13 @@ void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, voi void CustomData_set_layer_active(struct CustomData *data, int type, int n); void CustomData_set_layer_render(struct CustomData *data, int type, int n); void CustomData_set_layer_clone(struct CustomData *data, int type, int n); -void CustomData_set_layer_mask(struct CustomData *data, int type, int n); +void CustomData_set_layer_stencil(struct CustomData *data, int type, int n); /* same as above but works with an index from CustomData_get_layer_index */ void CustomData_set_layer_active_index(struct CustomData *data, int type, int n); void CustomData_set_layer_render_index(struct CustomData *data, int type, int n); void CustomData_set_layer_clone_index(struct CustomData *data, int type, int n); -void CustomData_set_layer_mask_index(struct CustomData *data, int type, int n); +void CustomData_set_layer_stencil_index(struct CustomData *data, int type, int n); /* adds flag to the layer flags */ void CustomData_set_layer_flag(struct CustomData *data, int type, int flag); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index d9e85d5d412..78e673b9e79 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1006,7 +1006,7 @@ int CustomData_get_clone_layer_index(const CustomData *data, int type) return -1; } -int CustomData_get_mask_layer_index(const CustomData *data, int type) +int CustomData_get_stencil_layer_index(const CustomData *data, int type) { int i; @@ -1050,7 +1050,7 @@ int CustomData_get_clone_layer(const CustomData *data, int type) return -1; } -int CustomData_get_mask_layer(const CustomData *data, int type) +int CustomData_get_stencil_layer(const CustomData *data, int type) { int i; @@ -1088,7 +1088,7 @@ void CustomData_set_layer_clone(CustomData *data, int type, int n) data->layers[i].active_clone = n; } -void CustomData_set_layer_mask(CustomData *data, int type, int n) +void CustomData_set_layer_stencil(CustomData *data, int type, int n) { int i; @@ -1125,7 +1125,7 @@ void CustomData_set_layer_clone_index(CustomData *data, int type, int n) data->layers[i].active_clone = n-i; } -void CustomData_set_layer_mask_index(CustomData *data, int type, int n) +void CustomData_set_layer_stencil_index(CustomData *data, int type, int n) { int i; -- cgit v1.2.3 From d6531927510ad3885176158afa643fee6ec30882 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 22 Dec 2009 12:01:32 +0000 Subject: Reports: writing movies now uses the reports mechanism to throw errors. Also fixes bug #19463: screencast to xvid ffmpeg crash. --- source/blender/blenkernel/BKE_writeavi.h | 12 ++- source/blender/blenkernel/BKE_writeffmpeg.h | 5 +- source/blender/blenkernel/BKE_writeframeserver.h | 7 +- source/blender/blenkernel/intern/writeavi.c | 19 ++-- source/blender/blenkernel/intern/writeffmpeg.c | 120 +++++++++++---------- .../blender/blenkernel/intern/writeframeserver.c | 48 ++++----- 6 files changed, 110 insertions(+), 101 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index 4ef63b069c2..a8d38dda103 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -37,17 +37,19 @@ extern "C" { /* generic blender movie support, could move to own module */ struct RenderData; +struct ReportList; struct Scene; -void start_avi(struct Scene *scene, struct RenderData *rd, int rectx, int recty); + +int start_avi(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); void end_avi(void); -void append_avi(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); +int append_avi(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); void makeavistring (struct RenderData *rd, char *string); typedef struct bMovieHandle { - void (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty); - void (*append_movie)(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); + int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); + int (*append_movie)(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); void (*end_movie)(void); - int (*get_next_frame)(struct RenderData *rd); /* optional */ + int (*get_next_frame)(struct RenderData *rd, struct ReportList *reports); /* optional */ } bMovieHandle; bMovieHandle *BKE_get_movie_handle(int imtype); diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 07e0e01ef7e..6ec8320f026 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -57,11 +57,12 @@ extern "C" { struct IDProperty; struct RenderData; +struct ReportList; struct Scene; -extern void start_ffmpeg(struct Scene *scene, struct RenderData *rd, int rectx, int recty); +extern int start_ffmpeg(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); extern void end_ffmpeg(void); -extern void append_ffmpeg(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); +extern int append_ffmpeg(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); extern void ffmpeg_set_preset(struct RenderData *rd, int preset); extern void ffmpeg_verify_image_type(struct RenderData *rd); diff --git a/source/blender/blenkernel/BKE_writeframeserver.h b/source/blender/blenkernel/BKE_writeframeserver.h index 6a38abe977f..50b905cfd75 100644 --- a/source/blender/blenkernel/BKE_writeframeserver.h +++ b/source/blender/blenkernel/BKE_writeframeserver.h @@ -33,12 +33,13 @@ extern "C" { #endif struct RenderData; +struct ReportList; struct Scene; -extern void start_frameserver(struct Scene *scene, struct RenderData *rd, int rectx, int recty); +extern int start_frameserver(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); extern void end_frameserver(void); -extern void append_frameserver(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); -extern int frameserver_loop(struct RenderData *rd); +extern int append_frameserver(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); +extern int frameserver_loop(struct RenderData *rd, struct ReportList *reports); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index 7c58a4f9499..ec3d1185179 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -40,6 +40,7 @@ #include "BLI_blenlib.h" #include "BKE_global.h" +#include "BKE_report.h" #include "BKE_utildefines.h" #include "BKE_writeavi.h" #include "AVI_avi.h" @@ -127,7 +128,7 @@ void makeavistring (RenderData *rd, char *string) } } -void start_avi(struct Scene *scene, RenderData *rd, int rectx, int recty) +int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) { int x, y; char name[256]; @@ -153,10 +154,10 @@ void start_avi(struct Scene *scene, RenderData *rd, int rectx, int recty) else format = AVI_FORMAT_MJPEG; if (AVI_open_compress (name, avi, 1, format) != AVI_ERROR_NONE) { - printf("cannot open or start AVI movie file"); + BKE_report(reports, RPT_ERROR, "Cannot open or start AVI movie file."); MEM_freeN (avi); avi = NULL; - return; + return 0; } AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x); @@ -170,18 +171,17 @@ void start_avi(struct Scene *scene, RenderData *rd, int rectx, int recty) /* avi->odd_fields= (rd->mode & R_ODDFIELD)?1:0; */ printf("Created avi: %s\n", name); + return 1; } -void append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty) +int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { unsigned int *rt1, *rt2, *rectot; int x, y; char *cp, rt; - if (avi == NULL) { - G.afbreek = 1; - return; - } + if (avi == NULL) + return 0; /* note that libavi free's the buffer... stupid interface - zr */ rectot= MEM_mallocN(rectx*recty*sizeof(int), "rectot"); @@ -205,6 +205,8 @@ void append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty) AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32, rectot, rectx*recty*4); // printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe); + + return 1; } void end_avi(void) @@ -215,3 +217,4 @@ void end_avi(void) MEM_freeN (avi); avi= NULL; } + diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 1953058fddf..417679417e4 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -52,23 +52,24 @@ #define snprintf _snprintf #endif -#include "BKE_writeffmpeg.h" - #include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" + #include "BLI_blenlib.h" +#include "AUD_C-API.h" /* must be before BKE_sound.h for define */ + #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_main.h" +#include "BKE_report.h" +#include "BKE_sound.h" +#include "BKE_writeffmpeg.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -#include "DNA_scene_types.h" - -#include "AUD_C-API.h" -#include "BKE_sound.h" -#include "BKE_main.h" - #ifdef HAVE_CONFIG_H #include #endif @@ -239,10 +240,10 @@ static const char** get_file_extensions(int format) } /* Write a frame to the output file */ -static void write_video_frame(RenderData *rd, AVFrame* frame) +static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports) { int outsize = 0; - int ret; + int ret, success= 1; AVCodecContext* c = get_codec_from_stream(video_stream); #ifdef FFMPEG_CODEC_TIME_BASE frame->pts = rd->cfra - rd->sfra; @@ -276,14 +277,17 @@ static void write_video_frame(RenderData *rd, AVFrame* frame) packet.size = outsize; ret = av_interleaved_write_frame(outfile, &packet); } else ret = 0; + if (ret != 0) { - G.afbreek = 1; - //XXX error("Error writing frame"); + success= 0; + BKE_report(reports, RPT_ERROR, "Error writing frame."); } + + return success; } /* read and encode a frame of audio from the buffer */ -static AVFrame* generate_video_frame(uint8_t* pixels) +static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports) { uint8_t* rendered_frame; @@ -295,8 +299,7 @@ static AVFrame* generate_video_frame(uint8_t* pixels) if (c->pix_fmt != PIX_FMT_BGR32) { rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height); if (!rgb_frame) { - G.afbreek=1; - //XXX error("Couldn't allocate temporary frame"); + BKE_report(reports, RPT_ERROR, "Couldn't allocate temporary frame."); return NULL; } } else { @@ -613,7 +616,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex } /* essential functions -- start, append, end */ -static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) +static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports) { /* Handle to the output file */ AVFormatContext* of; @@ -648,22 +651,19 @@ static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) exts = get_file_extensions(ffmpeg_type); if (!exts) { - G.afbreek = 1; /* Abort render */ - //XXX error("No valid formats found"); - return; + BKE_report(reports, RPT_ERROR, "No valid formats found."); + return 0; } fmt = guess_format(NULL, exts[0], NULL); if (!fmt) { - G.afbreek = 1; /* Abort render */ - //XXX error("No valid formats found"); - return; + BKE_report(reports, RPT_ERROR, "No valid formats found."); + return 0; } of = av_alloc_format_context(); if (!of) { - G.afbreek = 1; - //XXX error("Error opening output file"); - return; + BKE_report(reports, RPT_ERROR, "Error opening output file"); + return 0; } of->oformat = fmt; @@ -711,22 +711,16 @@ static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) } if (fmt->video_codec == CODEC_ID_DVVIDEO) { if (rectx != 720) { - G.afbreek = 1; - //XXX error("Render width has to be 720 pixels for DV!"); - return; + BKE_report(reports, RPT_ERROR, "Render width has to be 720 pixels for DV!"); + return 0; } if (rd->frs_sec != 25 && recty != 480) { - G.afbreek = 1; - //XXX error("Render height has to be 480 pixels " - // "for DV-NTSC!"); - return; - + BKE_report(reports, RPT_ERROR, "Render height has to be 480 pixels for DV-NTSC!"); + return 0; } if (rd->frs_sec == 25 && recty != 576) { - G.afbreek = 1; - //XXX error("Render height has to be 576 pixels " - // "for DV-PAL!"); - return; + BKE_report(reports, RPT_ERROR, "Render height has to be 576 pixels for DV-PAL!"); + return 0; } } @@ -735,46 +729,42 @@ static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) if (ffmpeg_type == FFMPEG_DV) { fmt->audio_codec = CODEC_ID_PCM_S16LE; if (ffmpeg_multiplex_audio && rd->ffcodecdata.audio_mixrate != 48000) { - G.afbreek = 1; - //XXX error("FFMPEG only supports 48khz / stereo " - // "audio for DV!"); - return; + BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!"); + return 0; } } video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty); + printf("alloc video stream %p\n", video_stream); if (!video_stream) { - G.afbreek = 1; - //XXX error("Error initializing video stream"); - return; + BKE_report(reports, RPT_ERROR, "Error initializing video stream."); + return 0; } if (ffmpeg_multiplex_audio) { audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); if (!audio_stream) { - G.afbreek = 1; - //XXX error("Error initializing audio stream"); - return; + BKE_report(reports, RPT_ERROR, "Error initializing audio stream."); + return 0; } //XXX audiostream_play(SFRA, 0, 1); } if (av_set_parameters(of, NULL) < 0) { - G.afbreek = 1; - //XXX error("Error setting output parameters"); - return; + BKE_report(reports, RPT_ERROR, "Error setting output parameters."); + return 0; } if (!(fmt->flags & AVFMT_NOFILE)) { if (url_fopen(&of->pb, name, URL_WRONLY) < 0) { - G.afbreek = 1; - // - //XXX error("Could not open file for writing"); - return; + BKE_report(reports, RPT_ERROR, "Could not open file for writing."); + return 0; } } av_write_header(of); outfile = of; dump_format(of, 0, name, 1); + + return 1; } /* ********************************************************************** @@ -831,11 +821,13 @@ static void makeffmpegstring(RenderData* rd, char* string) { } } -void start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty) +int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) { + int success; + ffmpeg_autosplit_count = 0; - start_ffmpeg_impl(rd, rectx, recty); + success = start_ffmpeg_impl(rd, rectx, recty, reports); if(ffmpeg_multiplex_audio && audio_stream) { @@ -846,6 +838,8 @@ void start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty) specs.rate = rd->ffcodecdata.audio_mixrate; audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->efra, rd->ffcodecdata.audio_volume); } + + return success; } void end_ffmpeg(void); @@ -870,22 +864,29 @@ static void write_audio_frames() } } -void append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty) +int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { + AVFrame* avframe; + int success; + fprintf(stderr, "Writing frame %i, " "render width=%d, render height=%d\n", frame, rectx, recty); write_audio_frames(); - write_video_frame(rd, generate_video_frame((unsigned char*) pixels)); + + avframe= generate_video_frame((unsigned char*) pixels, reports); + success= (avframe && write_video_frame(rd, avframe, reports)); if (ffmpeg_autosplit) { if (url_ftell(OUTFILE_PB) > FFMPEG_AUTOSPLIT_SIZE) { end_ffmpeg(); ffmpeg_autosplit_count++; - start_ffmpeg_impl(rd, rectx, recty); + success &= start_ffmpeg_impl(rd, rectx, recty, reports); } } + + return success; } @@ -914,6 +915,7 @@ 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); } diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index 0780cd0dc48..20d858fffeb 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -48,6 +48,7 @@ #include "DNA_userdef_types.h" #include "BKE_global.h" +#include "BKE_report.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -101,48 +102,45 @@ static int closesocket(int fd) } #endif -void start_frameserver(struct Scene *scene, RenderData *rd, int rectx, int recty) +int start_frameserver(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) { - struct sockaddr_in addr; + struct sockaddr_in addr; int arg = 1; if (!startup_socket_system()) { - G.afbreek = 1; - //XXX error("Can't startup socket system"); - return; + BKE_report(reports, RPT_ERROR, "Can't startup socket system"); + return 0; } if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { shutdown_socket_system(); - G.afbreek = 1; /* Abort render */ - //XXX error("Can't open socket"); - return; - } + BKE_report(reports, RPT_ERROR, "Can't open socket"); + return 0; + } - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (char*) &arg, sizeof(arg)); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &arg, sizeof(arg)); addr.sin_family = AF_INET; - addr.sin_port = htons(U.frameserverport); - addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(U.frameserverport); + addr.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { shutdown_socket_system(); - G.afbreek = 1; /* Abort render */ - //XXX error("Can't bind to socket"); - return; - } + BKE_report(reports, RPT_ERROR, "Can't bind to socket"); + return 0; + } - if (listen(sock, SOMAXCONN) < 0) { + if (listen(sock, SOMAXCONN) < 0) { shutdown_socket_system(); - G.afbreek = 1; /* Abort render */ - //XXX error("Can't establish listen backlog"); - return; - } + BKE_report(reports, RPT_ERROR, "Can't establish listen backlog"); + return 0; + } connsock = -1; render_width = rectx; render_height = recty; + + return 1; } static char index_page[] @@ -249,7 +247,7 @@ static int handle_request(RenderData *rd, char * req) return -1; } -int frameserver_loop(RenderData *rd) +int frameserver_loop(RenderData *rd, ReportList *reports) { fd_set readfds; struct timeval tv; @@ -355,7 +353,7 @@ static void serve_ppm(int *pixels, int rectx, int recty) connsock = -1; } -void append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int recty) +int append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { fprintf(stderr, "Serving frame: %d\n", frame); if (write_ppm) { @@ -365,6 +363,8 @@ void append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int r closesocket(connsock); connsock = -1; } + + return 0; } void end_frameserver() -- cgit v1.2.3 From a2b0020e11e27c6d7ecdacf747a4543ab733867b Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Thu, 24 Dec 2009 14:01:22 +0000 Subject: Reverted the addition of the f-curve sound modifier (was added in revision 24759) due to unusability and performance issues. The ability to use a sound as animation source will be added as an import operator later that renders a sound to an f-curve which brings the advantage that you can edit the generated curve later and the disadvantage it is not automatically updated when the sound changes. --- source/blender/blenkernel/intern/fmodifier.c | 93 ---------------------------- 1 file changed, 93 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 877c6d6b62e..5daa2ed1924 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -53,8 +53,6 @@ #include "RNA_access.h" #include "RNA_types.h" -#include "AUD_C-API.h" - #ifndef DISABLE_PYTHON #include "BPY_extern.h" /* for BPY_pydriver_eval() */ #endif @@ -873,96 +871,6 @@ static FModifierTypeInfo FMI_LIMITS = { fcm_limits_evaluate /* evaluate */ }; -/* Sound F-Curve Modifier --------------------------- */ - -static void fcm_sound_new_data (void *mdata) -{ - FMod_Sound *data= (FMod_Sound *)mdata; - - /* defaults */ - data->strength= 1.0f; - data->delay = 0.0f; - data->modification = FCM_SOUND_MODIF_REPLACE; - data->sound = NULL; -} - -static void fcm_sound_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) -{ - FMod_Sound *data= (FMod_Sound *)fcm->data; - float amplitude; - - AUD_Device *device; - AUD_Sound *limiter; - AUD_SoundInfo info; - - // XXX fixme - need to get in terms of time instead of frames to be really useful -// evaltime = FRA2TIME(evaltime); - evaltime -= data->delay; - - /* sound-system cannot cope with negative times/frames */ - if (evaltime < 0.0f) - return; - /* must have a sound with a cache so that this can be used */ - if (ELEM(NULL, data->sound, data->sound->cache)) - return; - - /* examine this snippet of the wave, and extract the amplitude from it */ - info = AUD_getInfo(data->sound->cache); - info.specs.channels = 1; - info.specs.format = AUD_FORMAT_FLOAT32; - device = AUD_openReadDevice(info.specs); - limiter = AUD_limitSound(data->sound->cache, evaltime, evaltime + 1); - AUD_playDevice(device, limiter); - AUD_unload(limiter); - AUD_readDevice(device, (sample_t*)&litude, 1); - AUD_closeReadDevice(device); - - /* combine the amplitude with existing motion data */ - switch (data->modification) { - case FCM_SOUND_MODIF_ADD: - *cvalue= *cvalue + amplitude * data->strength; - break; - case FCM_SOUND_MODIF_SUBTRACT: - *cvalue= *cvalue - amplitude * data->strength; - break; - case FCM_SOUND_MODIF_MULTIPLY: - *cvalue= *cvalue * amplitude * data->strength; - break; - case FCM_SOUND_MODIF_REPLACE: - default: - *cvalue= *cvalue + amplitude * data->strength; - break; - } -} - -static float fcm_sound_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) -{ - FMod_Sound *data= (FMod_Sound *)fcm->data; - - /* check for the time delay */ -// evaltime = FRA2TIME(evaltime); - if(evaltime < data->delay) - return data->delay; - - /* modifier doesn't change time */ - return evaltime; -} - -static FModifierTypeInfo FMI_SOUND = { - FMODIFIER_TYPE_SOUND, /* type */ - sizeof(FMod_Sound), /* size */ - FMI_TYPE_REPLACE_VALUES, /* action type */ - 0, /* requirements */ - "Sound", /* name */ - "FMod_Sound", /* struct name */ - NULL, /* free data */ - NULL, /* copy data */ - fcm_sound_new_data, /* new data */ - NULL, /* verify */ - fcm_sound_time, /* evaluate time */ - fcm_sound_evaluate /* evaluate */ -}; - /* F-Curve Modifier API --------------------------- */ /* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out * and operations that involve F-Curve modifier specific code. @@ -984,7 +892,6 @@ static void fmods_init_typeinfo () fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */ - fmodifiersTypeInfo[9]= &FMI_SOUND; /* Sound F-Curve Modifier */ } /* This function should be used for getting the appropriate type-info when only -- cgit v1.2.3 From 4dd3e6c36070e64d8b1d784a34d9881ae2c3eed8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Dec 2009 16:10:26 +0000 Subject: support for registering operators using the same internal rna api as panels, menus, headers & render engines since there was a fair bit of duplicate functionality. will remove the old system and update scripts next. --- source/blender/blenkernel/BKE_sequencer.h | 2 +- source/blender/blenkernel/intern/brush.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 070d98ce25f..dc7b6d3ad9b 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -195,7 +195,7 @@ void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_m void seq_update_sound(struct Sequence *seq); void seq_update_muting(struct Editing *ed); - +void seqbase_sound_reload(Scene *scene, ListBase *seqbase); void clear_scene_in_allseqs(struct Scene *sce); struct Sequence *get_seq_by_name(struct ListBase *seqbase, const char *name, int recursive); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 09d73f20b9a..667b0d50ee9 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -40,6 +40,8 @@ #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" +#include "WM_types.h" + #include "RNA_access.h" #include "BLI_math.h" @@ -56,6 +58,8 @@ #include "BKE_texture.h" #include "BKE_utildefines.h" + + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -- cgit v1.2.3 From b0b3e27471fb84f139d4aa3033aa093ac708f467 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Fri, 25 Dec 2009 22:58:11 +0000 Subject: Particles bug fix: using virtual parents for child particles crashed in some cases. --- source/blender/blenkernel/intern/particle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 1968673e568..b19b0f9fa20 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2444,7 +2444,7 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle mul_m4_v3(ob->obmat,cpa_1st); } - pa = psys->particles + cpa->parent; + pa = psys->particles + cpa->pa[0]; psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); -- cgit v1.2.3 From 99e3423a500d59e3493c4e8db8665c97aa02e110 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 25 Dec 2009 23:50:35 +0000 Subject: fix for accessing invalid memory when loading a new file. --- source/blender/blenkernel/intern/scene.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 0a2edf82cb0..eadeac585b2 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -249,7 +249,12 @@ void free_scene(Scene *sce) /* do not free objects! */ if(sce->gpd) { +#if 0 // removed since this can be invalid memory when freeing everything + // since the grease pencil data is free'd before the scene. + // since grease pencil data is not (yet?), shared between objects + // its probably safe not to do this, some save and reload will free this. sce->gpd->id.us--; +#endif sce->gpd= NULL; } -- cgit v1.2.3 From fc066a6a5d01718981c9dcae23c5f4f47f3d7b1e Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Fri, 25 Dec 2009 23:51:29 +0000 Subject: Fix for [#20458] Segmentation fault when trying to enable Hair dynamics * The hair mesh vertex index was stored as a short, but vertex counts can easily go higher than what fits in a short so changed this to an int. * Also removed particle life looping, which didn't work correctly anyways. Similar functionality will become available when I get to recoding reactor particles into a better system. --- source/blender/blenkernel/intern/particle.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 46 ++++++---------------- 2 files changed, 14 insertions(+), 34 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index b19b0f9fa20..992f63520ab 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -4069,7 +4069,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta else{ if(cpa){ ParticleKey *key1; - float t = (cfra - pa->time + pa->loop * pa->lifetime) / pa->lifetime; + float t = (cfra - pa->time) / pa->lifetime; key1=&pa->state; offset_child(cpa, key1, state, part->childflat, part->childrad); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index ce595bb280d..9882bfea137 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -389,7 +389,7 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) pa->fuv[1]=min[1]+(float)j*d; pa->fuv[2]=min[2]+(float)k*d; pa->flag |= PARS_UNEXIST; - pa->loop=0; /* abused in volume calculation */ + pa->hair_index=0; /* abused in volume calculation */ } } } @@ -451,7 +451,7 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) if(from==PART_FROM_FACE) (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; else /* store number of intersections */ - (pa+(int)(lambda*size[a])*a0mul)->loop++; + (pa+(int)(lambda*size[a])*a0mul)->hair_index++; } if(mface->v4){ @@ -461,20 +461,20 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) if(from==PART_FROM_FACE) (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; else - (pa+(int)(lambda*size[a])*a0mul)->loop++; + (pa+(int)(lambda*size[a])*a0mul)->hair_index++; } } } if(from==PART_FROM_VOLUME){ - int in=pa->loop%2; - if(in) pa->loop++; + int in=pa->hair_index%2; + if(in) pa->hair_index++; for(i=0; iloop%2) + if(in || (pa+i*a0mul)->hair_index%2) (pa+i*a0mul)->flag &= ~PARS_UNEXIST; /* odd intersections == in->out / out->in */ /* even intersections -> in stays same */ - in=(in + (pa+i*a0mul)->loop) % 2; + in=(in + (pa+i*a0mul)->hair_index) % 2; } } } @@ -1584,7 +1584,7 @@ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p) pa->flag &= ~PARS_UNEXIST; } - pa->loop=0; + pa->hair_index=0; /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */ /* usage other than straight after distribute has to handle this index by itself - jahka*/ //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we dont have a derived mesh face */ @@ -3215,14 +3215,6 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); reset_particle(sim, pa, dtime, cfra); - - if(cfra > pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){ - pa->loop = (short)((cfra-pa->time)/pa->lifetime); - pa->alive = PARS_UNBORN; - } - else{ - pa->loop = 0; - } } if(vg_size) @@ -3276,7 +3268,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) //if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) // react_to_events(psys,p); - birthtime = pa->time + pa->loop * pa->lifetime; + birthtime = pa->time; dietime = birthtime + pa->lifetime; pa_dfra = dfra; @@ -3335,15 +3327,8 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) if(pa->alive == PARS_DYING){ //push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); - if(part->flag & PART_LOOP && part->type!=PART_HAIR){ - pa->loop++; - reset_particle(sim, pa, 0.0, cfra); - pa->alive=PARS_ALIVE; - } - else{ - pa->alive=PARS_DEAD; - pa->state.time=pa->dietime; - } + pa->alive=PARS_DEAD; + pa->state.time=pa->dietime; } else pa->state.time=cfra; @@ -3394,13 +3379,8 @@ static void cached_step(ParticleSimulationData *sim, float cfra) psys->lattice= psys_get_lattice(sim); - if(part->flag & PART_LOOP && part->type!=PART_HAIR) - pa->loop = (short)((cfra - pa->time) / pa->lifetime); - else - pa->loop = 0; - - birthtime = pa->time + pa->loop * pa->lifetime; - dietime = birthtime + (1 + pa->loop) * (pa->dietime - pa->time); + birthtime = pa->time; + dietime = pa->dietime; /* update alive status and push events */ if(pa->time > cfra) { -- cgit v1.2.3 From 7a19832a78bea88d0a9c64809ef6e6576e870456 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 26 Dec 2009 00:17:54 +0000 Subject: Fix for [#20294] Switching to particle mode after changing number of hair particles causes blender to crash. * Particle edit mode wasn't freed when the particle amount was changed. --- source/blender/blenkernel/intern/particle_system.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 9882bfea137..d3dacadca53 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -170,6 +170,12 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) PARTICLE_P; int totpart, totsaved = 0; + if(psys->edit && psys->free_edit) { + psys->free_edit(psys->edit); + psys->edit = NULL; + psys->free_edit = NULL; + } + if(new_totpart<0) { if(part->distr==PART_DISTR_GRID && part->from != PART_FROM_VERT) { totpart= part->grid_res; -- cgit v1.2.3