diff options
46 files changed, 1300 insertions, 722 deletions
diff --git a/release/scripts/lightwave_import.py b/release/scripts/lightwave_import.py index 24e072f018a..2049fbd2380 100644 --- a/release/scripts/lightwave_import.py +++ b/release/scripts/lightwave_import.py @@ -656,7 +656,12 @@ def read_clip(lwochunk, dir_part): # ima, IMAG, g_IMAG refers to clip dictionary 'ID' entries: refer to blok and surf clip_dict = {} data = cStringIO.StringIO(lwochunk.read()) - image_index, = struct.unpack(">L", data.read(4)) + data_str = data.read(4) + if len(data_str) < 4: # can be zero also??? :/ + # Should not happen but lw can import so we should too + return + + image_index, = struct.unpack(">L", data_str) clip_dict['ID'] = image_index i = 4 while(i < lwochunk.chunksize): @@ -1634,11 +1639,11 @@ def main(): return Blender.Window.FileSelector(read, "Import LWO", '*.lwo') - if __name__=='__main__': main() + # Cams debugging lwo loader """ TIME= Blender.sys.time() diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index af5713b565d..3358cfbfd2b 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -215,7 +215,7 @@ void free_keyed_keys(struct ParticleSystem *psys); void psys_free(struct Object * ob, struct ParticleSystem * psys); void psys_free_children(struct ParticleSystem *psys); -void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy); +void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset); void psys_render_restore(struct Object *ob, struct ParticleSystem *psys); int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot); int psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index d08f42375ac..fc22f6787b1 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -112,6 +112,7 @@ #define VECADD(v1,v2,v3) {*(v1)= *(v2) + *(v3); *(v1+1)= *(v2+1) + *(v3+1); *(v1+2)= *(v2+2) + *(v3+2);} #define VECSUB(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1); *(v1+2)= *(v2+2) - *(v3+2);} #define VECADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac);} +#define QUATADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac); *(v1+3)= *(v2+3) + *(v3+3)*(fac);} #define INPR(v1, v2) ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] ) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 7d7180da271..38f25b54fd8 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2382,6 +2382,118 @@ static bConstraintTypeInfo CTI_LOCKTRACK = { locktrack_evaluate /* evaluate */ }; +/* ---------- Limit Distance Constraint ----------- */ + +static void distlimit_new_data (void *cdata) +{ + bDistLimitConstraint *data= (bDistLimitConstraint *)cdata; + + data->dist= 0.0; +} + +static void distlimit_get_tars (bConstraint *con, ListBase *list) +{ + if (con && list) { + bDistLimitConstraint *data= con->data; + bConstraintTarget *ct; + + /* standard target-getting macro for single-target constraints */ + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) + } +} + +static void distlimit_flush_tars (bConstraint *con, ListBase *list, short nocopy) +{ + if (con && list) { + bDistLimitConstraint *data= con->data; + bConstraintTarget *ct= list->first; + + /* the following macro is used for all standard single-target constraints */ + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) + } +} + +static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) +{ + bDistLimitConstraint *data= con->data; + bConstraintTarget *ct= targets->first; + + /* only evaluate if there is a target */ + if (VALID_CONS_TARGET(ct)) { + float dvec[3], dist=0.0f, sfac=1.0f; + short clamp_surf= 0; + + /* calculate our current distance from the target */ + dist= VecLenf(cob->matrix[3], ct->matrix[3]); + + /* set distance (flag is only set when user demands it) */ + if (data->dist == 0) + data->dist= dist; + + /* check if we're which way to clamp from, and calculate interpolation factor (if needed) */ + if (data->mode == LIMITDIST_OUTSIDE) { + /* if inside, then move to surface */ + if (dist <= data->dist) { + clamp_surf= 1; + sfac= data->dist / dist; + } + /* if soft-distance is enabled, start fading once owner is dist+softdist from the target */ + else if (data->flag & LIMITDIST_USESOFT) { + if (dist <= (data->dist + data->soft)) { + + } + } + } + else if (data->mode == LIMITDIST_INSIDE) { + /* if outside, then move to surface */ + if (dist >= data->dist) { + clamp_surf= 1; + sfac= data->dist / dist; + } + /* if soft-distance is enabled, start fading once owner is dist-soft from the target */ + else if (data->flag & LIMITDIST_USESOFT) { + // FIXME: there's a problem with "jumping" when this kicks in + if (dist >= (data->dist - data->soft)) { + sfac = data->soft*(1.0 - exp(-(dist - data->dist)/data->soft)) + data->dist; + sfac /= dist; + + clamp_surf= 1; + } + } + } + else { + if (IS_EQ(dist, data->dist)==0) { + clamp_surf= 1; + sfac= data->dist / dist; + } + } + + /* clamp to 'surface' (i.e. move owner so that dist == data->dist) */ + if (clamp_surf) { + /* simply interpolate along line formed by target -> owner */ + VecLerpf(dvec, ct->matrix[3], cob->matrix[3], sfac); + + /* copy new vector onto owner */ + VECCOPY(cob->matrix[3], dvec); + } + } +} + +static bConstraintTypeInfo CTI_DISTLIMIT = { + CONSTRAINT_TYPE_DISTLIMIT, /* type */ + sizeof(bDistLimitConstraint), /* size */ + "Limit Distance", /* name */ + "bDistLimitConstraint", /* struct name */ + NULL, /* free data */ + NULL, /* relink data */ + NULL, /* copy data */ + distlimit_new_data, /* new data */ + distlimit_get_tars, /* get constraint targets */ + distlimit_flush_tars, /* flush constraint targets */ + default_get_tarmat, /* get a target matrix */ + distlimit_evaluate /* evaluate */ +}; + /* ---------- Stretch To ------------ */ static void stretchto_new_data (void *cdata) @@ -3067,12 +3179,12 @@ static void constraints_init_typeinfo () { constraintsTypeInfo[11]= &CTI_PYTHON; /* Python/Script Constraint */ constraintsTypeInfo[12]= &CTI_ACTION; /* Action Constraint */ constraintsTypeInfo[13]= &CTI_LOCKTRACK; /* Locked-Track Constraint */ - constraintsTypeInfo[14]= NULL; /* 'Distance Limit' Constraint */ + constraintsTypeInfo[14]= &CTI_DISTLIMIT; /* Limit Distance Constraint */ constraintsTypeInfo[15]= &CTI_STRETCHTO; /* StretchTo Constaint */ constraintsTypeInfo[16]= &CTI_MINMAX; /* Floor Constraint */ constraintsTypeInfo[17]= &CTI_RIGIDBODYJOINT; /* RigidBody Constraint */ constraintsTypeInfo[18]= &CTI_CLAMPTO; /* ClampTo Constraint */ - constraintsTypeInfo[19]= &CTI_TRANSFORM; /* Transformation Constraint */ + constraintsTypeInfo[19]= &CTI_TRANSFORM; /* Transformation Constraint */ } /* This function should be used for getting the appropriate type-info when only diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 5b92eb12d4f..e09d6a7f06c 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -394,6 +394,7 @@ typedef struct ParticleRenderData { int winx, winy; int dosimplify; + int timeoffset; ParticleRenderElem *elems; int *origindex; } ParticleRenderData; @@ -455,13 +456,15 @@ static float psys_render_projected_area(ParticleSystem *psys, float *center, flo return area; } -void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy) +void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset) { ParticleRenderData*data; ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); if(!G.rendering) return; + if(psys->renderdata) + return; data= MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData"); @@ -489,6 +492,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float data->winx= winx; data->winy= winy; + data->timeoffset= timeoffset; + psys->renderdata= data; } @@ -554,7 +559,13 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) if(part->draw_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) return tot; - if(!ctx->psys->renderdata || !(part->simplify_flag & PART_SIMPLIFY_ENABLE)) + if(!ctx->psys->renderdata) + return tot; + + data= ctx->psys->renderdata; + if(data->timeoffset) + return 0; + if(!(part->simplify_flag & PART_SIMPLIFY_ENABLE)) return tot; mvert= dm->getVertArray(dm); @@ -571,7 +582,6 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) facetotvert= MEM_callocN(sizeof(int)*totorigface, "SimplifyFaceArea"); elems= MEM_callocN(sizeof(ParticleRenderElem)*totorigface, "SimplifyFaceElem"); - data= ctx->psys->renderdata; if(data->elems) MEM_freeN(data->elems); @@ -2076,7 +2086,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, rough_t = t; if(part->rough1 != 0.0 && pa_rough1 != 0.0) - do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state); + do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state); if(part->rough2 != 0.0 && pa_rough2 != 0.0) do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state); @@ -2262,6 +2272,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda float sel_col[3]; float nosel_col[3]; float length, vec[3]; + float *vg_effector= NULL, effector=0.0f; /* we don't have anything valid to create paths from so let's quit here */ if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) @@ -2310,6 +2321,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda ma= give_current_material(ob, psys->part->omat); if(ma && (psys->part->draw & PART_DRAW_MAT_COL)) VECCOPY(col, &ma->r) + + if(psys->part->from!=PART_FROM_PARTICLE) + vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR); /*---first main loop: create all actual particles' paths---*/ for(i=0,pa=psys->particles; i<totpart; i++, pa++){ @@ -2446,6 +2460,10 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda VecSubf(vec,(cache[i]+1)->co,cache[i]->co); length = VecLength(vec); + effector= 1.0f; + if(vg_effector) + effector*= psys_interpolate_value_from_verts(psmd->dm,psys->part->from,pa->num,pa->fuv,vg_effector); + for(k=0, ca=cache[i]; k<=steps; k++, ca++) { /* apply effectors */ if(edit==0 && k) { @@ -2458,7 +2476,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda do_effectors(i, pa, &eff_key, ob, psys, force, vel, dfra, cfra); - VecMulf(force, pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps); + VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps); VecAddf(force, force, vec); @@ -2571,6 +2589,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda end_latt_deform(); psys->lattice=0; } + + if(vg_effector) + MEM_freeN(vg_effector); } /************************************************/ /* Particle Key handling */ @@ -3517,7 +3538,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle part->kink_amp, part->kink, part->kink_axis, ob->obmat); if(part->rough1 != 0.0) - do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state); + do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state); if(part->rough2 != 0.0) do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index e71c4f90d48..3db42f091d4 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2724,7 +2724,8 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti force[0]=force[1]=force[2]=0.0; tvel[0]=tvel[1]=tvel[2]=0.0; /* add effectors */ - do_effectors(pa_no,pa,states+i,ob,psys,force,tvel,dfra,fra); + if(part->type != PART_HAIR) + do_effectors(pa_no,pa,states+i,ob,psys,force,tvel,dfra,fra); /* calculate air-particle interaction */ if(part->dragfac!=0.0f){ diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index c6011bb6fd9..5902b7dd68a 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -50,7 +50,9 @@ #include <time.h> #include <sys/stat.h> -#if !defined(linux) && (defined(__sgi) || defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__)) +#if defined (__sun__) || defined (__sun) +#include <sys/statvfs.h> /* Other modern unix os's should probably use this also */ +#elif !defined(linux) && (defined(__sgi) || defined(__sparc) || defined(__sparc__)) #include <sys/statfs.h> #endif @@ -179,7 +181,12 @@ double BLI_diskfree(char *dir) return (double) (freec*bytesps*sectorspc); #else + +#if defined (__sun__) || defined (__sun) + struct statvfs disk; +#else struct statfs disk; +#endif char name[FILE_MAXDIR],*slash; int len = strlen(dir); @@ -199,12 +206,12 @@ double BLI_diskfree(char *dir) #ifdef __BeOS return -1; #endif -#if !defined(linux) && (defined (__sgi) || defined (__sun__) || defined (__sun) || defined(__sparc) || defined(__sparc__)) - if (statfs(name, &disk, sizeof(struct statfs), 0)){ - /* printf("diskfree: Couldn't get information about %s.\n",dir); */ - return(-1); - } +#if defined (__sun__) || defined (__sun) + if (statvfs(name, &disk)) return(-1); +#elif !defined(linux) && (defined (__sgi) || defined(__sparc) || defined(__sparc__)) + /* WARNING - This may not be supported by geeneric unix os's - Campbell */ + if (statfs(name, &disk, sizeof(struct statfs), 0)) return(-1); #endif return ( ((double) disk.f_bsize) * ((double) disk.f_bfree)); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c725b3d63ac..a9d2e7d05a1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1754,6 +1754,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist) data->tar = newlibadr(fd, id->lib, data->tar); } break; + case CONSTRAINT_TYPE_DISTLIMIT: + { + bDistLimitConstraint *data; + data= ((bDistLimitConstraint*)con->data); + data->tar = newlibadr(fd, id->lib, data->tar); + } + break; case CONSTRAINT_TYPE_NULL: break; } @@ -1767,6 +1774,7 @@ static void direct_link_constraints(FileData *fd, ListBase *lb) link_list(fd, lb); for (cons=lb->first; cons; cons=cons->next) { cons->data = newdataadr(fd, cons->data); + if (cons->type == CONSTRAINT_TYPE_PYTHON) { bPythonConstraint *data= cons->data; link_list(fd, &data->targets); @@ -7844,6 +7852,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb) expand_doit(fd, mainvar, data->tar); } break; + case CONSTRAINT_TYPE_DISTLIMIT: + { + bDistLimitConstraint *data = (bDistLimitConstraint*)curcon->data; + expand_doit(fd, mainvar, data->tar); + } + break; default: break; } diff --git a/source/blender/include/BDR_sculptmode.h b/source/blender/include/BDR_sculptmode.h index 8b0b65be4de..e36b8674612 100644 --- a/source/blender/include/BDR_sculptmode.h +++ b/source/blender/include/BDR_sculptmode.h @@ -35,8 +35,8 @@ #include "BKE_sculpt.h" struct uiBlock; +struct BrushAction; struct BrushData; -struct EditData; struct IndexNode; struct KeyBlock; struct Mesh; @@ -65,7 +65,7 @@ void sculpt_stroke_draw(); void sculpt_radialcontrol_start(int mode); struct BrushData *sculptmode_brush(void); -void do_symmetrical_brush_actions(struct EditData *e, short *, short *); +void do_symmetrical_brush_actions(struct BrushAction *a, short *, short *); void sculptmode_update_tex(void); char sculpt_modifiers_active(struct Object *ob); @@ -76,8 +76,8 @@ void set_sculptmode(void); void sculpt_stroke_new(const int max); void sculpt_stroke_free(); void sculpt_stroke_add_point(const short x, const short y); -void sculpt_stroke_apply(struct EditData *); -void sculpt_stroke_apply_all(struct EditData *e); +void sculpt_stroke_apply(struct BrushAction *); +void sculpt_stroke_apply_all(struct BrushAction *); void sculpt_stroke_draw(); diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index c8e2a4832ab..a0f991f2631 100644 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -68,10 +68,10 @@ #define CTX_NO_PET 4 #define CTX_TWEAK 8 #define CTX_NO_MIRROR 16 +#define CTX_AUTOCONFIRM 32 void initTransform(int mode, int context); void Transform(void); -void Mirror(short mode); /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index a7759f799ba..28a58f7f9e4 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -700,7 +700,7 @@ enum { B_CONSTRAINT_ADD_ACTION, B_CONSTRAINT_ADD_LOCKTRACK, B_CONSTRAINT_ADD_FOLLOWPATH, - B_CONSTRAINT_ADD_DISTANCELIMIT, + B_CONSTRAINT_ADD_DISTLIMIT, B_CONSTRAINT_ADD_STRETCHTO, B_CONSTRAINT_ADD_LOCLIMIT, B_CONSTRAINT_ADD_ROTLIMIT, diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 30b9bbf3f51..48e840a7128 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -363,6 +363,9 @@ int TimeScale(TransInfo *t, short mval[2]); void initBakeTime(TransInfo *t); int BakeTime(TransInfo *t, short mval[2]); +void initMirror(TransInfo *t); +int Mirror(TransInfo *t, short mval[2]); + /*********************** transform_conversions.c ********** */ struct ListBase; void flushTransIpoData(TransInfo *t); diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 4ae8d6b39e6..2bcf2412588 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -307,6 +307,19 @@ typedef struct bSizeLimitConstraint { short flag2; } bSizeLimitConstraint; +/* Limit Distance Constraint */ +typedef struct bDistLimitConstraint { + Object *tar; + char subtarget[32]; + + float dist; /* distance (radius of clamping sphere) from target */ + float soft; /* distance from clamping-sphere to start applying 'fade' */ + + short flag; /* settings */ + short mode; /* how to limit in relation to clamping sphere */ + int pad; +} bDistLimitConstraint; + /* ------------------------------------------ */ /* bConstraint->type @@ -328,13 +341,14 @@ typedef enum B_CONSTAINT_TYPES { CONSTRAINT_TYPE_PYTHON, /* Unimplemented no longer :) - Aligorith. Scripts */ CONSTRAINT_TYPE_ACTION, CONSTRAINT_TYPE_LOCKTRACK, /* New Tracking constraint that locks an axis in place - theeth */ - CONSTRAINT_TYPE_DISTANCELIMIT, /* was never properly coded - removed! */ + CONSTRAINT_TYPE_DISTLIMIT, /* limit distance */ CONSTRAINT_TYPE_STRETCHTO, /* claiming this to be mine :) is in tuhopuu bjornmose */ CONSTRAINT_TYPE_MINMAX, /* floor constraint */ CONSTRAINT_TYPE_RIGIDBODYJOINT, /* rigidbody constraint */ CONSTRAINT_TYPE_CLAMPTO, /* clampto constraint */ CONSTRAINT_TYPE_TRANSFORM, /* transformation (loc/rot/size -> loc/rot/size) constraint */ + /* NOTE: everytime a new constraint is added, update this */ NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_TRANSFORM } B_CONSTRAINT_TYPES; @@ -478,6 +492,15 @@ typedef enum B_CONSTRAINTCHANNEL_FLAG { #define LIMIT_NOPARENT 0x01 /* for all Limit constraints - allow to be used during transform? */ #define LIMIT_TRANSFORM 0x02 + +/* distance limit constraint */ + /* bDistLimitConstraint->flag */ +#define LIMITDIST_USESOFT (1<<0) + + /* bDistLimitConstraint->mode */ +#define LIMITDIST_INSIDE 0 +#define LIMITDIST_OUTSIDE 1 +#define LIMITDIST_ONSURFACE 2 /* python constraint -> flag */ #define PYCON_USETARGETS 0x01 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index d39fbbbc679..6fcedcd934a 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -415,7 +415,7 @@ typedef struct ParticleSystem{ #define PARS_ALIVE 3 /* psys->vg */ -#define PSYS_TOT_VG 11 +#define PSYS_TOT_VG 12 #define PSYS_VG_DENSITY 0 #define PSYS_VG_VEL 1 @@ -428,6 +428,7 @@ typedef struct ParticleSystem{ #define PSYS_VG_SIZE 8 #define PSYS_VG_TAN 9 #define PSYS_VG_ROT 10 +#define PSYS_VG_EFFECTOR 11 /* part->boidrules */ #define BOID_TOT_RULES 8 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b342bc5afe8..8bdea93b1f4 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -120,7 +120,11 @@ typedef struct SceneRenderLayer { struct Group *light_override; unsigned int lay; /* scene->lay itself has priority over this */ + unsigned int lay_zmask; /* has to be after lay, this is for Z-masking */ int layflag; + + int pad; + int passflag; /* pass_xor has to be after passflag */ int pass_xor; } SceneRenderLayer; @@ -137,6 +141,7 @@ typedef struct SceneRenderLayer { #define SCE_LAY_ALL_Z 0x8000 #define SCE_LAY_XOR 0x10000 #define SCE_LAY_DISABLE 0x20000 +#define SCE_LAY_ZMASK 0x40000 /* srl->passflag */ #define SCE_PASS_COMBINED 1 diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py index 7ab3d7b90a9..ddcc5a239af 100644 --- a/source/blender/python/api2_2x/doc/Render.py +++ b/source/blender/python/api2_2x/doc/Render.py @@ -432,6 +432,15 @@ class RenderData: sequences. """ + def getFrameFilename( frame ): + """ + Get the filename used for the remdered image. + @type frame: int + @param path: the frame to use in the filename, if no argument given, use the current frame. + @rtype: string + @return: Returns the filename that blender would render to, taking into account output path, extension and frame number. + """ + def setBackbufPath(path): """ Set the path to a background image and load it. diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index ec160ddf4ce..f5861995073 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -2201,6 +2201,19 @@ static int RenderData_setRenderPath( BPy_RenderData * self, PyObject * value ) return 0; } +static PyObject *RenderData_getFrameFilename( BPy_RenderData * self, PyObject *args ) +{ + char name[FILE_MAX]; + int frame = self->renderContext->cfra; + + if( !PyArg_ParseTuple( args, "|i", &( frame ) ) ) + return ( EXPP_ReturnPyObjError( PyExc_AttributeError, + "expected int argument or nothing" ) ); + + BKE_makepicstring(name, self->renderContext->pic, frame, self->renderContext->imtype); + return PyString_FromString( name ); +} + PyObject *RenderData_getBackbufPath( BPy_RenderData * self ) { return PyString_FromString( self->renderContext->backbuf ); @@ -2726,6 +2739,9 @@ static PyMethodDef BPy_RenderData_methods[] = { {"getRenderPath", ( PyCFunction ) RenderData_getRenderPath, METH_NOARGS, "() - get the path to directory where rendered images will go"}, + {"getFrameFilename", ( PyCFunction ) RenderData_getFrameFilename, + METH_VARARGS, + "() - get the filename of the frame this will be rendered, taking into account extension and frame range"}, {"setBackbufPath", ( PyCFunction ) RenderData_SetBackbufPath, METH_VARARGS, "(string) - get/set the path to a background image and load it"}, diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 846b0867a76..de12f75300e 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -73,7 +73,7 @@ typedef struct RenderLayer { /* copy of RenderData */ char name[RE_MAXNAME]; - unsigned int lay; + unsigned int lay, lay_zmask; int layflag, passflag, pass_xor; struct Material *mat_override; diff --git a/source/blender/render/intern/include/occlusion.h b/source/blender/render/intern/include/occlusion.h index 3f10d50ab2e..646ad30b318 100644 --- a/source/blender/render/intern/include/occlusion.h +++ b/source/blender/render/intern/include/occlusion.h @@ -45,7 +45,5 @@ void sample_occ(struct Render *re, struct ShadeInput *shi); void cache_occ_samples(struct Render *re, struct RenderPart *pa, struct ShadeSample *ssamp); void free_occ_samples(struct Render *re, struct RenderPart *pa); -void *cache_occ_mesh(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4]); - #endif diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 46b5face22a..16c46ec550f 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -161,7 +161,7 @@ struct Render /* occlusion tree */ void *occlusiontree; - ListBase occlusionmesh; + ListBase strandsurface; /* use this instead of R.r.cfra */ float cfra; @@ -337,6 +337,18 @@ typedef struct StrandVert { float strandco; } StrandVert; +typedef struct StrandSurface { + struct StrandSurface *next, *prev; + ObjectRen obr; + int (*face)[4]; + float (*co)[3]; + /* for occlusion caching */ + float (*col)[3]; /* for occlusion */ + /* for speedvectors */ + float (*prevco)[3], (*nextco)[3]; + int totvert, totface; +} StrandSurface; + typedef struct StrandBuffer { struct StrandBuffer *next, *prev; struct StrandVert *vert; @@ -344,7 +356,7 @@ typedef struct StrandBuffer { struct ObjectRen *obr; struct Material *ma; - void *occlusionmesh; + struct StrandSurface *surface; unsigned int lay; int overrideuv; int flag, maxdepth; diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h index f1c0b6d1e3a..8e34fa27342 100644 --- a/source/blender/render/intern/include/strand.h +++ b/source/blender/render/intern/include/strand.h @@ -44,6 +44,9 @@ struct RenderBuckets; struct RenderPrimitiveIterator; struct ZSpan; struct ObjectInstanceRen; +struct StrandSurface; +struct DerivedMesh; +struct ObjectRen; typedef struct StrandPoint { /* position within segment */ @@ -89,6 +92,9 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint); void render_strand_segment(struct Render *re, float winmat[][4], struct StrandPart *spart, struct ZSpan *zspan, int totzspan, StrandSegment *sseg); void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets); +struct StrandSurface *cache_strand_surface(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4], int timeoffset); +void free_strand_surface(struct Render *re); + struct RenderBuckets *init_buckets(struct Render *re); void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim); void free_buckets(struct RenderBuckets *buckets); diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h index 1d202fa45fa..8feb18a7ab8 100644 --- a/source/blender/render/intern/include/zbuf.h +++ b/source/blender/render/intern/include/zbuf.h @@ -48,7 +48,7 @@ void projectverto(float *v1, float winmat[][4], float *adr); int testclip(float *v); void zbuffer_shadow(struct Render *re, float winmat[][4], struct LampRen *lar, int *rectz, int size, float jitx, float jity); -void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag, void (*fillfunc)(struct RenderPart*, struct ZSpan*, int, void*), void *data); +void zbuffer_solid(struct RenderPart *pa, struct RenderLayer *rl, void (*fillfunc)(struct RenderPart*, struct ZSpan*, int, void*), void *data); unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass, struct ListBase *psmlist); unsigned short *zbuffer_strands_shade(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, float *pass); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 69ae280dc4c..7a8d151c738 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -108,6 +108,7 @@ #include "radio.h" #include "shadbuf.h" #include "shading.h" +#include "strand.h" #include "texture.h" #include "sss.h" #include "zbuf.h" @@ -1465,7 +1466,7 @@ static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mat if(har) har->lay= obr->ob->lay; } } -static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys) +static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset) { Object *ob= obr->ob; Object *tob=0, *bb_ob=re->scene->camera; @@ -1487,7 +1488,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2]; - int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0, doapproxao = 0; + int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0, dosurfacecache = 0; int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num; char **uv_name=0; @@ -1647,9 +1648,11 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem svert= strandbuf->vert; - if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) + if(re->r.mode & R_SPEED) + dosurfacecache= 1; + else if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) if(ma->amb != 0.0f) - doapproxao= 1; + dosurfacecache= 1; } } } @@ -1827,7 +1830,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem VECCOPY(snor, surfnor); } - if(doapproxao && num >= 0) { + if(dosurfacecache && num >= 0) { int *facenum= RE_strandren_get_face(obr, strand, 1); *facenum= num; } @@ -1931,8 +1934,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem break; } - if(doapproxao) - strandbuf->occlusionmesh= cache_occ_mesh(re, obr, psmd->dm, mat); + if(dosurfacecache) + strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset); /* 4. clean up */ if(ma) do_mat_ipo(ma); @@ -2543,7 +2546,7 @@ static void init_render_surf(Render *re, ObjectRen *obr) freedisplist(&displist); } -static void init_render_curve(Render *re, ObjectRen *obr, int only_verts) +static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; Curve *cu; @@ -2621,7 +2624,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int only_verts) } } - if(only_verts==0) { + if(timeoffset==0) { startvlak= obr->totvlak; index= dl->index; for(a=0; a<dl->parts; a++, index+=3) { @@ -2674,7 +2677,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int only_verts) } } - if(dl->bevelSplitFlag || only_verts==0) { + if(dl->bevelSplitFlag || timeoffset==0) { startvlak= obr->totvlak; for(a=0; a<dl->parts; a++) { @@ -2890,7 +2893,7 @@ static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, } } -static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) +static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; Mesh *me; @@ -2949,12 +2952,12 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) /* check autosmooth and displacement, we then have to skip only-verts optimize */ do_autosmooth |= (me->flag & ME_AUTOSMOOTH); if(do_autosmooth) - only_verts= 0; + timeoffset= 0; if(test_for_displace(re, ob ) ) - only_verts= 0; + timeoffset= 0; mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; - if(!only_verts) + if(!timeoffset) if(need_orco) mask |= CD_MASK_ORCO; @@ -3020,7 +3023,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) } } - if(!only_verts) { + if(!timeoffset) { /* store customdata names, because DerivedMesh is freed */ RE_set_customdata_names(obr, &dm->faceData); @@ -3174,7 +3177,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts) } } - if(!only_verts) { + if(!timeoffset) { if (test_for_displace(re, ob ) ) { calc_vertexnormals(re, obr, 0); do_displacement(re, obr); @@ -3834,7 +3837,7 @@ static void check_non_flat_quads(ObjectRen *obr) } } -static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts) +static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; @@ -3845,7 +3848,7 @@ static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts) if(ob->type!=OB_MESH && test_for_displace(re, ob)) do_displacement(re, obr); - if(!only_verts) { + if(!timeoffset) { /* phong normal interpolation can cause error in tracing * (terminator problem) */ ob->smoothresh= 0.0; @@ -3934,7 +3937,7 @@ static ObjectRen *find_dupligroup_dupli(Render *re, Object *ob, int psysindex) return NULL; } -static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) +static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; ParticleSystem *psys; @@ -3952,20 +3955,20 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) for(psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++) psys= psys->next; - render_new_particle_system(re, obr, psys); + render_new_particle_system(re, obr, psys, timeoffset); } else { if ELEM(ob->type, OB_FONT, OB_CURVE) - init_render_curve(re, obr, only_verts); + init_render_curve(re, obr, timeoffset); else if(ob->type==OB_SURF) init_render_surf(re, obr); else if(ob->type==OB_MESH) - init_render_mesh(re, obr, only_verts); + init_render_mesh(re, obr, timeoffset); else if(ob->type==OB_MBALL) init_render_mball(re, obr); } - finalize_render_object(re, obr, only_verts); + finalize_render_object(re, obr, timeoffset); re->totvert += obr->totvert; re->totvlak += obr->totvlak; @@ -3973,7 +3976,7 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) re->totstrand += obr->totstrand; } -static void add_render_object(Render *re, Object *ob, Object *par, int index, int only_verts, int instanceable) +static void add_render_object(Render *re, Object *ob, Object *par, int index, int timeoffset, int instanceable) { ObjectRen *obr; ParticleSystem *psys; @@ -3985,7 +3988,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in show_emitter= 0; for(psys=ob->particlesystem.first; psys; psys=psys->next) { show_emitter += psys->part->draw & PART_DRAW_EMITTER; - psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy); + psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); } /* if no psys has "show emitter" selected don't render emitter */ @@ -4000,7 +4003,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in obr->flag |= R_INSTANCEABLE; Mat4CpyMat4(obr->obmat, ob->obmat); } - init_render_object_data(re, obr, only_verts); + init_render_object_data(re, obr, timeoffset); /* only add instance for objects that have not been used for dupli */ if(!(ob->transflag & OB_RENDER_DUPLI)) @@ -4018,7 +4021,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in obr->flag |= R_INSTANCEABLE; Mat4CpyMat4(obr->obmat, ob->obmat); } - init_render_object_data(re, obr, only_verts); + init_render_object_data(re, obr, timeoffset); psys_render_restore(ob, psys); /* only add instance for objects that have not been used for dupli */ @@ -4032,7 +4035,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in /* par = pointer to duplicator parent, needed for object lookup table */ /* index = when duplicater copies same object (particle), the counter */ -static void init_render_object(Render *re, Object *ob, Object *par, int index, int only_verts, int instanceable) +static void init_render_object(Render *re, Object *ob, Object *par, int index, int timeoffset, int instanceable) { static double lasttime= 0.0; double time; @@ -4041,7 +4044,7 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i if(ob->type==OB_LAMP) add_render_lamp(re, ob); else if(render_object_type(ob->type)) - add_render_object(re, ob, par, index, only_verts, instanceable); + add_render_object(re, ob, par, index, timeoffset, instanceable); else { MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); MTC_Mat4Invert(ob->imat, mat); @@ -4119,6 +4122,7 @@ void RE_Database_Free(Render *re) free_sss(re); free_occ(re); + free_strand_surface(re); re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; re->i.convertdone= 0; @@ -4174,7 +4178,7 @@ static int allow_render_dupli_instance(Render *re, DupliObject *dob, Object *obd !(re->r.mode & R_RADIO)); } -static void dupli_render_particle_set(Render *re, Object *ob, int level, int enable) +static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, int level, int enable) { /* ugly function, but we need to set particle systems to their render * settings before calling object_duplilist, to get render level duplis */ @@ -4190,7 +4194,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int level, int ena for(psys=ob->particlesystem.first; psys; psys=psys->next) { if(ELEM(psys->part->draw_as, PART_DRAW_OB, PART_DRAW_GR)) { if(enable) - psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy); + psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); else psys_render_restore(ob, psys); } @@ -4212,10 +4216,10 @@ static void dupli_render_particle_set(Render *re, Object *ob, int level, int ena group= ob->dup_group; for(go= group->gobject.first; go; go= go->next) - dupli_render_particle_set(re, go->ob, level+1, enable); + dupli_render_particle_set(re, go->ob, timeoffset, level+1, enable); } -static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int only_verts) +static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int timeoffset) { Base *base; Object *ob; @@ -4243,16 +4247,16 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int if(ob->flag & OB_DONE) { if(ob->transflag & OB_RENDER_DUPLI) if(allow_render_object(ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, 0, only_verts, 1); + init_render_object(re, ob, NULL, 0, timeoffset, 1); } else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) { if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) { DupliObject *dob; ListBase *lb; - dupli_render_particle_set(re, ob, 0, 1); + dupli_render_particle_set(re, ob, timeoffset, 0, 1); lb= object_duplilist(sce, ob); - dupli_render_particle_set(re, ob, 0, 0); + dupli_render_particle_set(re, ob, timeoffset, 0, 0); for(dob= lb->first; dob; dob= dob->next) { Object *obd= dob->ob; @@ -4294,7 +4298,7 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int } } else - init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated); + init_render_object(re, obd, ob, dob->index, timeoffset, !dob->animated); psysindex= 1; for(psys=obd->particlesystem.first; psys; psys=psys->next) { @@ -4319,17 +4323,17 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int } } else - init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated); + init_render_object(re, obd, ob, dob->index, timeoffset, !dob->animated); if(re->test_break()) break; } free_object_duplilist(lb); if(allow_render_object(ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, 0, only_verts, 0); + init_render_object(re, ob, NULL, 0, timeoffset, 0); } else if(allow_render_object(ob, nolamps, onlyselected, actob)) - init_render_object(re, ob, NULL, 0, only_verts, 0); + init_render_object(re, ob, NULL, 0, timeoffset, 0); } if(re->test_break()) break; @@ -4513,7 +4517,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset) } /* MAKE RENDER DATA */ - database_init_objects(re, lay, 0, 0, 0, 1); + database_init_objects(re, lay, 0, 0, 0, timeoffset); if(!re->test_break()) project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); @@ -4608,14 +4612,49 @@ static void calculate_speedvector(float *vectors, int step, float winsq, float w } } +static float *calculate_strandsurface_speedvectors(Render *re, ObjectInstanceRen *obi, StrandSurface *mesh) +{ + float winsq= re->winx*re->winy, winroot= sqrt(winsq), (*winspeed)[4]; + float ho[4], prevho[4], nextho[4], winmat[4][4], vec[2]; + int a; + + if(mesh->co && mesh->prevco && mesh->nextco) { + if(obi->flag & R_TRANSFORMED) + Mat4MulMat4(winmat, obi->mat, re->winmat); + else + Mat4CpyMat4(winmat, re->winmat); + + winspeed= MEM_callocN(sizeof(float)*4*mesh->totvert, "StrandSurfWin"); + + for(a=0; a<mesh->totvert; a++) { + projectvert(mesh->co[a], winmat, ho); + + projectvert(mesh->prevco[a], winmat, prevho); + speedvector_project(NULL, vec, mesh->prevco[a], prevho); + calculate_speedvector(vec, 0, winsq, winroot, mesh->co[a], ho, winspeed[a]); + + projectvert(mesh->nextco[a], winmat, nextho); + speedvector_project(NULL, vec, mesh->nextco[a], nextho); + calculate_speedvector(vec, 1, winsq, winroot, mesh->co[a], ho, winspeed[a]); + } + + return (float*)winspeed; + } + + return NULL; +} + static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step) { ObjectRen *obr= obi->obr; VertRen *ver= NULL; StrandRen *strand= NULL; - float *speed, ho[4], winmat[4][4]; + StrandBuffer *strandbuf; + StrandSurface *mesh= NULL; + float *speed, (*winspeed)[4]=NULL, ho[4], winmat[4][4]; + float *co1, *co2, *co3, *co4, w[4]; float winsq= re->winx*re->winy, winroot= sqrt(winsq); - int a; + int a, *face, *index; if(obi->flag & R_TRANSFORMED) Mat4MulMat4(winmat, obi->mat, re->winmat); @@ -4634,13 +4673,42 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve } if(obr->strandnodes) { - for(a=0; a<obr->totstrand; a++, vectors+=2) { - if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; - else strand++; + strandbuf= obr->strandbufs.first; + mesh= (strandbuf)? strandbuf->surface: NULL; + + /* compute speed vectors at surface vertices */ + if(mesh) + winspeed= (float(*)[4])calculate_strandsurface_speedvectors(re, obi, mesh); - speed= RE_strandren_get_winspeed(obi, strand, 1); - projectvert(strand->vert->co, winmat, ho); - calculate_speedvector(vectors, step, winsq, winroot, strand->vert->co, ho, speed); + if(winspeed) { + for(a=0; a<obr->totstrand; a++, vectors+=2) { + if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; + else strand++; + + index= RE_strandren_get_face(obr, strand, 0); + if(index && *index) { + speed= RE_strandren_get_winspeed(obi, strand, 1); + + /* interpolate speed vectors from strand surface */ + face= mesh->face[*index]; + + co1= mesh->co[face[0]]; + co2= mesh->co[face[1]]; + co3= mesh->co[face[2]]; + co4= (face[3])? mesh->co[face[3]]: NULL; + + InterpWeightsQ3Dfl(co1, co2, co3, co4, strand->vert->co, w); + + speed[0]= speed[1]= speed[2]= speed[3]= 0.0f; + QUATADDFAC(speed, speed, winspeed[face[0]], w[0]); + QUATADDFAC(speed, speed, winspeed[face[1]], w[1]); + QUATADDFAC(speed, speed, winspeed[face[2]], w[2]); + if(face[3]) + QUATADDFAC(speed, speed, winspeed[face[3]], w[3]); + } + } + + MEM_freeN(winspeed); } } } @@ -4731,7 +4799,6 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb) ObjectInstanceRen *obi, *obilb; ObjectRen *obr; VertRen *ver= NULL; - StrandRen *strand= NULL; float *vec, ho[4], winmat[4][4]; int a, totvector; @@ -4742,7 +4809,7 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb) memcpy(obilb, obi, sizeof(ObjectInstanceRen)); BLI_addtail(lb, obilb); - obilb->totvector= totvector= obr->totvert + obr->totstrand; + obilb->totvector= totvector= obr->totvert; if(totvector > 0) { vec= obilb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array"); @@ -4759,14 +4826,6 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb) projectvert(ver->co, winmat, ho); speedvector_project(NULL, vec, ver->co, ho); } - - for(a=0; a<obr->totstrand; a++, vec+=2) { - if((a & 255)==0) strand= obr->strandnodes[a>>8].strand; - else strand++; - - projectvert(strand->vert->co, winmat, ho); - speedvector_project(NULL, vec, strand->vert->co, ho); - } } } } @@ -4784,8 +4843,10 @@ static void free_dbase_object_vectors(ListBase *lb) void RE_Database_FromScene_Vectors(Render *re, Scene *sce) { ObjectInstanceRen *obi, *oldobi; + StrandSurface *mesh; ListBase *table; ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL}; + ListBase strandsurface; int step; re->i.infostr= "Calculating previous vectors"; @@ -4800,7 +4861,10 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) copy_dbase_object_vectors(re, &oldtable); /* free dbase and make the future one */ + strandsurface= re->strandsurface; + memset(&re->strandsurface, 0, sizeof(ListBase)); RE_Database_Free(re); + re->strandsurface= strandsurface; if(!re->test_break()) { /* creates entire dbase */ @@ -4812,7 +4876,10 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) copy_dbase_object_vectors(re, &newtable); /* free dbase and make the real one */ + strandsurface= re->strandsurface; + memset(&re->strandsurface, 0, sizeof(ListBase)); RE_Database_Free(re); + re->strandsurface= strandsurface; if(!re->test_break()) RE_Database_FromScene(re, sce, 1); @@ -4829,7 +4896,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) for(obi= re->instancetable.first; obi && oldobi; obi= obi->next, oldobi= oldobi->next) { int ok= 1; - obi->totvector= obi->obr->totvert + obi->obr->totstrand; + obi->totvector= obi->obr->totvert; /* find matching object in old table */ if(oldobi->ob!=obi->ob || oldobi->par!=obi->par || oldobi->index!=obi->index || oldobi->psysindex!=obi->psysindex) { @@ -4867,6 +4934,17 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce) free_dbase_object_vectors(&oldtable); free_dbase_object_vectors(&newtable); + + for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { + if(mesh->prevco) { + MEM_freeN(mesh->prevco); + mesh->prevco= NULL; + } + if(mesh->nextco) { + MEM_freeN(mesh->nextco); + mesh->nextco= NULL; + } + } re->i.infostr= NULL; re->stats_draw(&re->i); diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index 7d7ed5bcdce..e1d491c69d9 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -35,14 +35,12 @@ #include "MEM_guardedalloc.h" #include "DNA_material_types.h" -#include "DNA_meshdata_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_memarena.h" #include "BLI_threads.h" -#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_utildefines.h" @@ -74,15 +72,6 @@ typedef struct OcclusionCache { int x, y, w, h, step; } OcclusionCache; -typedef struct OcclusionCacheMesh { - struct OcclusionCacheMesh *next, *prev; - ObjectRen *obr; - int (*face)[4]; - float (*co)[3]; - float (*col)[3]; - int totvert, totface; -} OcclusionCacheMesh; - typedef struct OccFace { int obi; int facenr; @@ -1418,10 +1407,10 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int return 0; } -static void sample_occ_cache_mesh(ShadeInput *shi) +static void sample_occ_surface(ShadeInput *shi) { StrandRen *strand= shi->strand; - OcclusionCacheMesh *mesh= strand->buffer->occlusionmesh; + StrandSurface *mesh= strand->buffer->surface; int *face, *index = RE_strandren_get_face(shi->obr, strand, 0); float w[4], *co1, *co2, *co3, *co4; @@ -1449,53 +1438,11 @@ static void sample_occ_cache_mesh(ShadeInput *shi) } } -void *cache_occ_mesh(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4]) -{ - OcclusionCacheMesh *mesh; - MFace *mface; - MVert *mvert; - int a, totvert, totface; - - totvert= dm->getNumVerts(dm); - totface= dm->getNumFaces(dm); - - mesh= re->occlusionmesh.last; - if(mesh && mesh->obr->ob == obr->ob && mesh->obr->par == obr->par - && mesh->totvert==totvert && mesh->totface==totface) - return mesh; - - mesh= MEM_callocN(sizeof(OcclusionCacheMesh), "OcclusionCacheMesh"); - mesh->obr= obr; - mesh->totvert= totvert; - mesh->totface= totface; - mesh->co= MEM_callocN(sizeof(float)*3*mesh->totvert, "OcclusionMeshCo"); - mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "OcclusionMeshFaces"); - mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "OcclusionMeshCol"); - - mvert= dm->getVertArray(dm); - for(a=0; a<mesh->totvert; a++, mvert++) { - VECCOPY(mesh->co[a], mvert->co); - Mat4MulVecfl(mat, mesh->co[a]); - } - - mface= dm->getFaceArray(dm); - for(a=0; a<mesh->totface; a++, mface++) { - mesh->face[a][0]= mface->v1; - mesh->face[a][1]= mface->v2; - mesh->face[a][2]= mface->v3; - mesh->face[a][3]= mface->v4; - } - - BLI_addtail(&re->occlusionmesh, mesh); - - return mesh; -} - /* ------------------------- External Functions --------------------------- */ void make_occ_tree(Render *re) { - OcclusionCacheMesh *mesh; + StrandSurface *mesh; float col[3], co[3], n[3], *co1, *co2, *co3, *co4; int a, *face, *count; @@ -1511,7 +1458,7 @@ void make_occ_tree(Render *re) if(re->wrld.ao_approx_passes) occ_compute_passes(re, re->occlusiontree, re->wrld.ao_approx_passes); - for(mesh=re->occlusionmesh.first; mesh; mesh=mesh->next) { + for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount"); for(a=0; a<mesh->totface; a++) { @@ -1558,20 +1505,10 @@ void make_occ_tree(Render *re) void free_occ(Render *re) { - OcclusionCacheMesh *mesh; - if(re->occlusiontree) { occ_free_tree(re->occlusiontree); re->occlusiontree = NULL; } - - for(mesh=re->occlusionmesh.first; mesh; mesh=mesh->next) { - if(mesh->co) MEM_freeN(mesh->co); - if(mesh->col) MEM_freeN(mesh->col); - if(mesh->face) MEM_freeN(mesh->face); - } - - BLI_freelistN(&re->occlusionmesh); } void sample_occ(Render *re, ShadeInput *shi) @@ -1584,7 +1521,7 @@ void sample_occ(Render *re, ShadeInput *shi) if(tree) { if(shi->strand) { - sample_occ_cache_mesh(shi); + sample_occ_surface(shi); } /* try to get result from the cache if possible */ else if(!sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) { diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 43f0a0d13e7..e4aa2326c0c 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -505,6 +505,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int strcpy(rl->name, srl->name); rl->lay= srl->lay; + rl->lay_zmask= srl->lay_zmask; rl->layflag= srl->layflag; rl->passflag= srl->passflag; rl->pass_xor= srl->pass_xor; @@ -2358,6 +2359,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) continue; } if (scene->r.mode & R_TOUCH && !BLI_exist(name)) { + BLI_make_existing_file(name); /* makes the dir if its not there */ BLI_touch(name); } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 50f3142f95a..220c06f1ede 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -897,7 +897,7 @@ void zbufshadeDA_tile(RenderPart *pa) sdata.rl= rl; sdata.psmlist= &psmlist; sdata.edgerect= edgerect; - zbuffer_solid(pa, rl->lay, rl->layflag, make_pixelstructs, &sdata); + zbuffer_solid(pa, rl, make_pixelstructs, &sdata); if(R.test_break()) break; } @@ -1063,7 +1063,7 @@ void zbufshade_tile(RenderPart *pa) shade_sample_initialize(&ssamp, pa, rl); addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); - zbuffer_solid(pa, rl->lay, rl->layflag, NULL, NULL); + zbuffer_solid(pa, rl, NULL, NULL); if(!R.test_break()) { /* NOTE: this if() is not consistant */ @@ -1364,12 +1364,12 @@ void zbufshade_sss_tile(RenderPart *pa) ShadeSample ssamp; ZBufSSSHandle handle; RenderResult *rr= pa->result; - RenderLayer *rl= rr->layers.first; + RenderLayer *rl; VlakRen *vlr; Material *mat= re->sss_mat; - float (*co)[3], (*color)[3], *area, *fcol= rl->rectf; + float (*co)[3], (*color)[3], *area, *fcol; int x, y, seed, quad, totpoint, display = !(re->r.scemode & R_PREVIEWBUTS); - int *ro, *rz, *rp, *rbo, *rbz, *rbp; + int *ro, *rz, *rp, *rbo, *rbz, *rbp, lay; #if 0 PixStr *ps; long *rs; @@ -1394,13 +1394,32 @@ void zbufshade_sss_tile(RenderPart *pa) pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz"); #endif + /* setup shade sample with correct passes */ + memset(&ssamp, 0, sizeof(ssamp)); + shade_sample_initialize(&ssamp, pa, rr->layers.first); + ssamp.tot= 1; + + for(rl=rr->layers.first; rl; rl=rl->next) { + ssamp.shi[0].lay |= rl->lay; + ssamp.shi[0].layflag |= rl->layflag; + ssamp.shi[0].passflag |= rl->passflag; + ssamp.shi[0].combinedflag |= ~rl->pass_xor; + } + + rl= rr->layers.first; + ssamp.shi[0].passflag |= SCE_PASS_RGBA|SCE_PASS_COMBINED; + ssamp.shi[0].combinedflag &= ~(SCE_PASS_SPEC); + lay= ssamp.shi[0].lay; + /* create the pixelstrs to be used later */ - zbuffer_sss(pa, rl->lay, &handle, addps_sss); + zbuffer_sss(pa, lay, &handle, addps_sss); if(handle.totps==0) { zbufshade_sss_free(pa); return; } + + fcol= rl->rectf; co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo"); color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor"); @@ -1412,14 +1431,6 @@ void zbufshade_sss_tile(RenderPart *pa) ISB_create(pa, NULL); #endif - /* setup shade sample with correct passes */ - memset(&ssamp, 0, sizeof(ssamp)); - shade_sample_initialize(&ssamp, pa, rl); - ssamp.shi[0].passflag= SCE_PASS_DIFFUSE|SCE_PASS_AO|SCE_PASS_RADIO; - ssamp.shi[0].passflag |= SCE_PASS_RGBA; - ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC); - ssamp.tot= 1; - if(display) { /* initialize scanline updates for main thread */ rr->renrect.ymin= 0; diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index 09a3b9ef66d..88333265a84 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -860,13 +860,13 @@ static void sss_create_tree_mat(Render *re, Material *mat) setting them back, maybe we need to create our own Render? */ /* do SSS preprocessing render */ - layers= re->r.layers; + rr= re->result; + layers= rr->layers; osa= re->osa; osaflag= re->r.mode & R_OSA; partsdone= re->i.partsdone; - rr= re->result; - re->r.layers.first= re->r.layers.last= NULL; + rr->layers.first= rr->layers.last= NULL; re->osa= 0; re->r.mode &= ~R_OSA; re->sss_points= &points; @@ -881,7 +881,7 @@ static void sss_create_tree_mat(Render *re, Material *mat) re->i.partsdone= partsdone; re->sss_mat= NULL; re->sss_points= NULL; - re->r.layers= layers; + rr->layers= layers; re->osa= osa; if (osaflag) re->r.mode |= R_OSA; diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 3a1d98572ca..bf58c023998 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -35,12 +35,14 @@ #include "DNA_key_types.h" #include "DNA_material_types.h" +#include "DNA_meshdata_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_ghash.h" #include "BLI_memarena.h" +#include "BKE_DerivedMesh.h" #include "BKE_key.h" #include "BKE_utildefines.h" @@ -1313,3 +1315,70 @@ void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], fl #endif } +StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4], int timeoffset) +{ + StrandSurface *mesh; + MFace *mface; + MVert *mvert; + float (*co)[3]; + int a, totvert, totface; + + totvert= dm->getNumVerts(dm); + totface= dm->getNumFaces(dm); + + for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) + if(mesh->obr.ob == obr->ob && mesh->obr.par == obr->par + && mesh->obr.index == obr->index && mesh->totvert==totvert && mesh->totface==totface) + break; + + if(!mesh) { + mesh= MEM_callocN(sizeof(StrandSurface), "StrandSurface"); + mesh->obr= *obr; + mesh->totvert= totvert; + mesh->totface= totface; + mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "StrandSurfFaces"); + mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCol"); + BLI_addtail(&re->strandsurface, mesh); + } + + if(timeoffset == -1 && !mesh->prevco) + mesh->prevco= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); + else if(timeoffset == 0 && !mesh->co) + mesh->co= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); + else if(timeoffset == 1 && !mesh->nextco) + mesh->nextco= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo"); + else + return mesh; + + mvert= dm->getVertArray(dm); + for(a=0; a<mesh->totvert; a++, mvert++) { + VECCOPY(co[a], mvert->co); + Mat4MulVecfl(mat, co[a]); + } + + mface= dm->getFaceArray(dm); + for(a=0; a<mesh->totface; a++, mface++) { + mesh->face[a][0]= mface->v1; + mesh->face[a][1]= mface->v2; + mesh->face[a][2]= mface->v3; + mesh->face[a][3]= mface->v4; + } + + return mesh; +} + +void free_strand_surface(Render *re) +{ + StrandSurface *mesh; + + for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { + if(mesh->co) MEM_freeN(mesh->co); + if(mesh->prevco) MEM_freeN(mesh->prevco); + if(mesh->nextco) MEM_freeN(mesh->nextco); + if(mesh->col) MEM_freeN(mesh->col); + if(mesh->face) MEM_freeN(mesh->face); + } + + BLI_freelistN(&re->strandsurface); +} + diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index a8b6dfec667..6b103d4fce2 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -196,7 +196,6 @@ static void zbuf_add_to_span(ZSpan *zspan, float *v1, float *v2) /* Functions */ /*-----------------------------------------------------------*/ - void fillrect(int *rect, int x, int y, int val) { int len, *drect; @@ -1922,10 +1921,78 @@ void zbufclip4(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3 zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, vez+12); } +/* ************** ZMASK ******************************** */ + +#define EXTEND_PIXEL(a) if(temprectp[a]) {z+= rectz[a]; tot++;} + +/* changes the zbuffer to be ready for z-masking: applies an extend-filter, and then clears */ +static void zmask_rect(int *rectz, int *rectp, int xs, int ys) +{ + int len=0, x, y; + int *temprectp; + int row1, row2, row3, *curp, *curz; + + temprectp= MEM_dupallocN(rectp); + + /* extend: if pixel is not filled in, we check surrounding pixels and average z value */ + + for(y=1; y<=ys; y++) { + /* setup row indices */ + row1= (y-2)*xs; + row2= row1 + xs; + row3= row2 + xs; + if(y==1) + row1= row2; + else if(y==ys) + row3= row2; + + curp= rectp + (y-1)*xs; + curz= rectz + (y-1)*xs; + + for(x=0; x<xs; x++, curp++, curz++) { + if(curp[0]==0) { + int tot= 0; + float z= 0.0f; + + EXTEND_PIXEL(row1); + EXTEND_PIXEL(row2); + EXTEND_PIXEL(row3); + EXTEND_PIXEL(row1 + 1); + EXTEND_PIXEL(row3 + 1); + if(x!=xs-1) { + EXTEND_PIXEL(row1 + 2); + EXTEND_PIXEL(row2 + 2); + EXTEND_PIXEL(row3 + 2); + } + if(tot) { + len++; + curz[0]= (int)(z/(float)tot); + curp[0]= -1; /* env */ + } + } + + if(x!=0) { + row1++; row2++; row3++; + } + } + } + MEM_freeN(temprectp); + + /* clear not filled z values */ + for(len= xs*ys -1; len>=0; len--) { + if(rectp[len]==0) { + rectz[len] = -0x7FFFFFFF; + rectp[len]= -1; /* env code */ + } + } +} + + + /* ***************** ZBUFFER MAIN ROUTINES **************** */ -void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag, void(*fillfunc)(RenderPart*, ZSpan*, int, void*), void *data) +void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*, ZSpan*, int, void*), void *data) { ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; ZSpan zspans[16], *zspan; /* 16 = RE_MAX_OSA */ @@ -1935,9 +2002,11 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag, void(*fillfu ObjectInstanceRen *obi; ObjectRen *obr; float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0}; + unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask; int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0; - short nofill=0, env=0, wire=0, all_z= layflag & SCE_LAY_ALL_Z; - + short nofill=0, env=0, wire=0, zmaskpass=0; + short all_z= rl->layflag & SCE_LAY_ALL_Z; + samples= (R.osa? R.osa: 1); samples= MIN2(4, samples-pa->sample); @@ -1988,98 +2057,123 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag, void(*fillfu zspan->zbuflinefunc= zbufline; } - for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { - obr= obi->obr; + /* in case zmask we fill Z for objects in lay_zmask first, then clear Z, and then do normal zbuffering */ + if(rl->layflag & SCE_LAY_ZMASK) + zmaskpass= 1; + + for(; zmaskpass >=0; zmaskpass--) { + /* regular zbuffering loop, does all sample buffers */ + for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { + obr= obi->obr; - if(obi->flag & R_TRANSFORMED) - zbuf_make_winmat(&R, obi->mat, winmat); - else - zbuf_make_winmat(&R, NULL, winmat); + /* continue happens in 2 different ways... zmaskpass only does lay_zmask stuff */ + if(zmaskpass) { + if((obr->lay & lay_zmask)==0) + continue; + } + else { + if(!all_z && !(obr->lay & lay)) + continue; + } + + if(obi->flag & R_TRANSFORMED) + zbuf_make_winmat(&R, obi->mat, winmat); + else + zbuf_make_winmat(&R, NULL, winmat); - zbuf_project_cache_clear(cache, obr->totvert); + zbuf_project_cache_clear(cache, obr->totvert); - for(v=0; v<obr->totvlak; v++) { - if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; - else vlr++; + for(v=0; v<obr->totvlak; v++) { + if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; + else vlr++; - /* three cases, visible for render, only z values and nothing */ - if(obr->lay & lay) { - if(vlr->mat!=ma) { - ma= vlr->mat; - nofill= ma->mode & (MA_ZTRA|MA_ONLYCAST); - env= (ma->mode & MA_ENV); - wire= (ma->mode & MA_WIRE); - - for(zsample=0; zsample<samples; zsample++) { - if(ma->mode & MA_ZINV) zspans[zsample].zbuffunc= zbuffillGLinv4; - else zspans[zsample].zbuffunc= zbuffillGL4; + /* the cases: visible for render, only z values, zmask, nothing */ + if(obr->lay & lay) { + if(vlr->mat!=ma) { + ma= vlr->mat; + nofill= ma->mode & (MA_ZTRA|MA_ONLYCAST); + env= (ma->mode & MA_ENV); + wire= (ma->mode & MA_WIRE); + + for(zsample=0; zsample<samples; zsample++) { + if(ma->mode & MA_ZINV) zspans[zsample].zbuffunc= zbuffillGLinv4; + else zspans[zsample].zbuffunc= zbuffillGL4; + } } } - } - else if(all_z) { - env= 1; - nofill= 0; - ma= NULL; - } - else { - nofill= 1; - ma= NULL; /* otherwise nofill can hang */ - } - - if(!(vlr->flag & R_HIDDEN) && nofill==0) { - unsigned short partclip; - - v1= vlr->v1; - v2= vlr->v2; - v3= vlr->v3; - v4= vlr->v4; - - c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1); - c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2); - c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3); - - /* partclipping doesn't need viewplane clipping */ - partclip= c1 & c2 & c3; - if(v4) { - c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4); - partclip &= c4; + else if(all_z || (obr->lay & lay_zmask)) { + env= 1; + nofill= 0; + ma= NULL; + } + else { + nofill= 1; + ma= NULL; /* otherwise nofill can hang */ } - if(partclip==0) { + if(!(vlr->flag & R_HIDDEN) && nofill==0) { + unsigned short partclip; - if(env) zvlnr= -1; - else zvlnr= v+1; - - c1= testclip(ho1); - c2= testclip(ho2); - c3= testclip(ho3); - if(v4) - c4= testclip(ho4); - - for(zsample=0; zsample<samples; zsample++) { - zspan= &zspans[zsample]; - - if(wire) { - if(v4) - zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); - else - zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0); - } - else { - /* strands allow to be filled in as quad */ - if(v4 && (vlr->flag & R_STRAND)) { - zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + v1= vlr->v1; + v2= vlr->v2; + v3= vlr->v3; + v4= vlr->v4; + + c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1); + c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2); + c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3); + + /* partclipping doesn't need viewplane clipping */ + partclip= c1 & c2 & c3; + if(v4) { + c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4); + partclip &= c4; + } + + if(partclip==0) { + + if(env) zvlnr= -1; + else zvlnr= v+1; + + c1= testclip(ho1); + c2= testclip(ho2); + c3= testclip(ho3); + if(v4) + c4= testclip(ho4); + + for(zsample=0; zsample<samples; zsample++) { + zspan= &zspans[zsample]; + + if(wire) { + if(v4) + zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + else + zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0); } else { - zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); - if(v4) - zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); + /* strands allow to be filled in as quad */ + if(v4 && (vlr->flag & R_STRAND)) { + zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4); + } + else { + zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3); + if(v4) + zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4); + } } } } } } } + + /* clear all z to close value, so it works as mask for next passes (ztra+strand) */ + if(zmaskpass) { + for(zsample=0; zsample<samples; zsample++) { + zspan= &zspans[zsample]; + zmask_rect(zspan->rectz, zspan->rectp, pa->rectx, pa->recty); + } + } } for(zsample=0; zsample<samples; zsample++) { @@ -2272,6 +2366,8 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int if(obr->ob==re->excludeob) continue; + else if(!(obr->lay & lay)) + continue; if(obi->flag & R_TRANSFORMED) Mat4MulMat4(obwinmat, obi->mat, winmat); @@ -2495,6 +2591,9 @@ void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(vo for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { obr= obi->obr; + if(!(obr->lay & lay)) + continue; + if(obi->flag & R_TRANSFORMED) zbuf_make_winmat(&R, obi->mat, winmat); else @@ -3196,6 +3295,9 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) { obr= obi->obr; + if(!(obr->lay & lay)) + continue; + if(obi->flag & R_TRANSFORMED) zbuf_make_winmat(&R, obi->mat, winmat); else diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 7b87dd2108c..eb81c256289 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -604,13 +604,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s uiBlockBeginAlign(block); uiBlockSetEmboss(block, UI_EMBOSS); - if ((prev_proxylock) || (con->prev==NULL)) { - /* don't draw 'button' behind arrow if disabled (and button doesn't do anything anyways) */ - uiBlockSetEmboss(block, UI_EMBOSSN); - uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack"); - uiBlockSetEmboss(block, UI_EMBOSS); - } - else { + /* only show buttons that will do anything valid */ + if ((prev_proxylock==0) && (con->prev)) { but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack"); uiButSetFunc(but, constraint_moveUp, ob, con); } @@ -619,12 +614,6 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack"); uiButSetFunc(but, constraint_moveDown, ob, con); } - else { - /* don't draw 'button' behind arrow if no next constraint (it doesn't do anything anyways) */ - uiBlockSetEmboss(block, UI_EMBOSSN); - uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack"); - uiBlockSetEmboss(block, UI_EMBOSS); - } uiBlockEndAlign(block); @@ -1441,6 +1430,54 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s draw_constraint_spaceselect(block, con, *xco, *yco-130, is_armature_owner(ob), -1); } break; + case CONSTRAINT_TYPE_DISTLIMIT: + { + bDistLimitConstraint *data = con->data; + + height = 105; + uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); + + uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); + + /* Draw target parameters */ + uiBlockBeginAlign(block); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); + + if (is_armature_target(data->tar)) { + but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone"); + uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar); + } + else if (is_geom_target(data->tar)) { + but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points"); + uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar); + } + else { + strcpy(data->subtarget, ""); + } + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + if (is_armature_target(data->tar)) { + uiDefButF(block, BUT, B_CONSTRAINT_TEST, "R", *xco, *yco-60, 20, 18, &data->dist, 0, 0, 0, 0, "Recalculate distance"); + uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Distance:", *xco+18, *yco-60,139,18, &data->dist, 0.0, 100, 0.5, 0.5, "Radius of limiting sphere"); + uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Head/Tail:", *xco+155, *yco-60,100,18, &con->headtail, 0.0, 1, 0.1, 0.1, "Target along length of bone: Head=0, Tail=1"); + } + else { + uiDefButF(block, BUT, B_CONSTRAINT_TEST, "R", *xco, *yco-60, 20, 18, &data->dist, 0, 0, 0, 0, "Recalculate distance"); + uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Distance:", *xco+18, *yco-60, 237, 18, &data->dist, 0.0, 100, 0.5, 0.5, "Radius of limiting sphere"); + } + + /* disabled soft-distance controls... currently it doesn't work yet. It was intended to be used for soft-ik (see xsi-blog for details) */ +#if 0 + uiDefButBitS(block, TOG, LIMITDIST_USESOFT, B_CONSTRAINT_TEST, "Soft", *xco, *yco-82, 50, 18, &data->flag, 0, 24, 0, 0, "Enables soft-distance"); + if (data->flag & LIMITDIST_USESOFT) + uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Soft-Distance:", *xco+50, *yco-82, 187, 18, &data->soft, 0.0, 100, 0.5, 0.5, "Distance surrounding radius when transforms should get 'delayed'"); +#endif + uiBlockEndAlign(block); + + uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Limit Mode%t|Inside %x0|Outside %x1|Surface %x2", *xco+((width/2)-50), *yco-104, 100, 18, &data->mode, 0, 24, 0, 0, "Distances in relation to sphere of influence to allow"); + } + break; case CONSTRAINT_TYPE_RIGIDBODYJOINT: { bRigidBodyJointConstraint *data = con->data; @@ -1750,6 +1787,7 @@ static uiBlock *add_constraintmenu(void *arg_unused) uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIMIT, "Limit Location", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, ""); uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIMIT, "Limit Rotation", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, ""); uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SIZELIMIT, "Limit Scale", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, BUTM, B_CONSTRAINT_ADD_DISTLIMIT, "Limit Distance", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -1982,6 +2020,14 @@ void do_constraintbuts(unsigned short event) BIF_undo_push("Add constraint"); } break; + case B_CONSTRAINT_ADD_DISTLIMIT: + { + con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT); + add_constraint_to_active(ob, con); + + BIF_undo_push("Add constraint"); + } + break; default: break; @@ -3490,7 +3536,7 @@ static char sbsolvers[] = "Solver %t|RKP almost SOFT not usable but for some ger /* SIF would have been candidate .. well lack of time .. brecht is busy .. better make a stable version for peach now :) */ static char sbsolvers[] = "SIF semi implicit euler with fixed step size (worth a try with real stiff egdes)%x3|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; #else -static char sbsolvers[] = "SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; +static char sbsolvers[] = "RKCP correct physics (harder to get stable but usefull for education :)%x1|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; #endif static void object_softbodies_collision(Object *ob) @@ -3582,42 +3628,7 @@ static void object_softbodies_collision(Object *ob) uiBlockEndAlign(block); /*SOLVER SETTINGS*/ - uiBlockBeginAlign(block); /* done in another panel now*/ - /* - uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,100,50,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver"); - sb->solver_ID = 0; - switch (sb->solver_ID) { - case 0: - case 1: - {adaptive_mode = 1; break;} - case 3: - {adaptive_mode = 0; break;} - default: printf("SB_solver?\n"); // should never happen - - } - if(adaptive_mode){ - uiDefButF(block, NUM, B_DIFF, "Error Lim:", 60,100,120,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed"); - uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"O", 180,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Old Error Calculation"); - uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 200,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); - uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 290,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); - uiBlockEndAlign(block); - uiDefButS(block, NUM, B_DIFF, "MinS:", 10,80,100,20, &sb->minloops, 0.00, 30000.0, 10, 0, "Minimal # solver steps/frame "); - uiDefButS(block, NUM, B_DIFF, "MaxS:", 110,80,100,20, &sb->maxloops, 0.00, 30000.0, 10, 0, "Maximal # solver steps/frame "); - uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); - } - else{ - uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 210,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); - uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 290,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); - uiBlockEndAlign(block); - uiDefButS(block, NUM, B_DIFF, "Steps:", 10,80,100,20, &sb->minloops, 1.00, 30000.0, 10, 0, "Solver steps/frame "); - uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); - } - */ - - } /* OTHER OBJECTS COLLISION STUFF */ if (ob->type==OB_MESH){ @@ -3640,12 +3651,12 @@ static void object_softbodies_solver(Object *ob) static int val; short *softflag=&ob->softflag, psys_cur=0, adaptive_mode=0; int ob_has_hair=psys_ob_has_hair(ob); - if(!_can_softbodies_at_all(ob)) return; + if(!_can_softbodies_at_all(ob)) return; block= uiNewBlock(&curarea->uiblocks, "object_softbodies_solver", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Soft Body Solver", "Physics", 651, 0, 318, 204)==0) return; uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - /* doubt that is really needed here but for now */ + /* doubt that is really needed here but for now */ if(ob_has_hair) { if(PE_get_current_num(ob) >= 0) { ParticleSystem *psys = PE_get_current(ob); @@ -3680,11 +3691,10 @@ static void object_softbodies_solver(Object *ob) /*SOLVER SETTINGS*/ uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Solver select",10,200,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,180,300,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver (choose 1 of 1 i was working on some other but failed *sigh* BM) "); + uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,180,300,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver"); uiBlockEndAlign(block); - + /*some have adapive step size - some not*/ - sb->solver_ID = 0; /* ugly hack to prepare peach freeze */ switch (sb->solver_ID) { case 0: case 1: @@ -3695,7 +3705,7 @@ static void object_softbodies_solver(Object *ob) } if(adaptive_mode){ uiBlockBeginAlign(block); - uiDefBut(block, LABEL, 0, "Step size controls",10,160,300,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Step size controls",10,160,300,20, NULL, 0.0, 0, 0, 0, ""); uiDefButF(block, NUM, B_DIFF, "Error Lim:", 10,140,280,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed"); uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"V", 290,140,20,20, &sb->solverflags, 0, 0, 0, 0, "Use velocities for automagic step sizes"); uiDefButS(block, NUM, B_DIFF, "MinS:", 10,120,150,20, &sb->minloops, 0.00, 30000.0, 10, 0, "Minimal # solver steps/frame "); @@ -3703,11 +3713,11 @@ static void object_softbodies_solver(Object *ob) uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefBut(block, LABEL, 0, "Collision helpers",10,100,300,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Collision helpers",10,100,300,20, NULL, 0.0, 0, 0, 0, ""); uiDefButS(block, NUM, B_DIFF, "Choke:", 10,80,150,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 160,80,150,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); uiBlockEndAlign(block); - + uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Diagnosis stuff",10,60,300,20, NULL, 0.0, 0, 0, 0, ""); uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"Print Performance to Console", 10,40,300,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); @@ -3723,10 +3733,9 @@ static void object_softbodies_solver(Object *ob) uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); } - uiBlockEndAlign(block); + uiBlockEndAlign(block); } - //uiDefBut(block, LABEL, 0, "",10,10,1,2, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ } uiBlockEndAlign(block); } @@ -3850,7 +3859,7 @@ static void object_softbodies(Object *ob) uiBlockBeginAlign(block); uiDefButF(block, NUM, B_DIFF, "Friction:", 10, 170,150,20, &sb->mediafrict, 0.0, 50.0, 10, 0, "General media friction for point movements"); uiDefButF(block, NUM, B_DIFF, "Mass:", 160, 170,150,20, &sb->nodemass , 0.001, 50000.0, 10, 0, str); - uiDefButF(block, NUM, B_DIFF, "Grav:", 10,150,150,20, &sb->grav , 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_DIFF, "Grav:", 10,150,150,20, &sb->grav , -10.0, 10.0, 10, 0, "Apply gravitation to point movement"); uiDefButF(block, NUM, B_DIFF, "Speed:", 160,150,150,20, &sb->physics_speed , 0.01, 100.0, 10, 0, "Tweak timing for physics to control frequency and speed"); uiBlockEndAlign(block); @@ -4110,7 +4119,7 @@ static void object_panel_particle_extra(Object *ob) uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_PART_REDRAW, "Attribute%t|TanRot%x10|TanVel%x9|Size%x8|RoughE%x7|Rough2%x6|Rough1%x5|Kink%x4|Clump%x3|Length%x2|Velocity%x1|Density%x0", butx,(buty-=buth),butw-40,buth, &vgnum, 14.0, 0.0, 0, 0, "Attribute effected by vertex group"); + uiDefButS(block, MENU, B_PART_REDRAW, "Attribute%t|Effector%x11|TanRot%x10|TanVel%x9|Size%x8|RoughE%x7|Rough2%x6|Rough1%x5|Kink%x4|Clump%x3|Length%x2|Velocity%x1|Density%x0", butx,(buty-=buth),butw-40,buth, &vgnum, 14.0, 0.0, 0, 0, "Attribute effected by vertex group"); but=uiDefButBitS(block, TOG, (1<<vgnum), B_PART_REDRAW, "Neg", butx+butw-40,buty,40,buth, &psys->vg_neg, 0, 0, 0, 0, "Negate the effect of the vertex group"); uiButSetFunc(but, particle_set_vg, (void *)ob, (void *)(&vgnum)); diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 0dc6c485db5..d06028b09bc 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -2485,7 +2485,7 @@ static void layer_copy_func(void *lay_v, void *lay_p) unsigned int *lay= lay_p; int laybit= (int)lay_v; - if(G.qual & LR_SHIFTKEY) { + if(G.qual & (LR_SHIFTKEY|LR_CTRLKEY)) { if(*lay==0) *lay= 1<<laybit; } else @@ -2556,29 +2556,29 @@ static char *scene_layer_menu(void) return str; } -static void draw_3d_layer_buttons(uiBlock *block, unsigned int *poin, short xco, short yco, short dx, short dy) +static void draw_3d_layer_buttons(uiBlock *block, int type, unsigned int *poin, short xco, short yco, short dx, short dy, char *tip) { uiBut *bt; long a; uiBlockBeginAlign(block); for(a=0; a<5; a++) { - bt= uiDefButBitI(block, TOG, 1<<a, B_NOP, "", (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, ""); + bt= uiDefButBitI(block, type, 1<<a, B_NOP, "", (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, tip); uiButSetFunc(bt, layer_copy_func, (void *)a, poin); } for(a=0; a<5; a++) { - bt=uiDefButBitI(block, TOG, 1<<(a+10), B_NOP, "", (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, ""); + bt=uiDefButBitI(block, type, 1<<(a+10), B_NOP, "", (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, tip); uiButSetFunc(bt, layer_copy_func, (void *)(a+10), poin); } xco+= 7; uiBlockBeginAlign(block); for(a=5; a<10; a++) { - bt=uiDefButBitI(block, TOG, 1<<a, B_NOP, "", (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, ""); + bt=uiDefButBitI(block, type, 1<<a, B_NOP, "", (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, tip); uiButSetFunc(bt, layer_copy_func, (void *)a, poin); } for(a=5; a<10; a++) { - bt=uiDefButBitI(block, TOG, 1<<(a+10), B_NOP, "", (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, ""); + bt=uiDefButBitI(block, type, 1<<(a+10), B_NOP, "", (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, tip); uiButSetFunc(bt, layer_copy_func, (void *)(a+10), poin); } @@ -2603,7 +2603,7 @@ static void render_panel_layers(void) /* first, as reminder, the scene layers */ uiDefBut(block, LABEL, 0, "Scene:", 10,170,100,20, NULL, 0, 0, 0, 0, ""); - draw_3d_layer_buttons(block, &G.scene->lay, 130, 170, 35, 30); + draw_3d_layer_buttons(block, TOG, &G.scene->lay, 130, 170, 35, 30, "Scene layers to render"); /* layer disable, menu, name, delete button */ uiBlockBeginAlign(block); @@ -2623,10 +2623,11 @@ static void render_panel_layers(void) /* RenderLayer visible-layers */ uiDefBut(block, LABEL, 0, "Layer:", 10,110,100,20, NULL, 0, 0, 0, 0, ""); - draw_3d_layer_buttons(block, &srl->lay, 130,110, 35, 30); + draw_3d_layer_buttons(block, BUT_TOGDUAL, &srl->lay, 130,110, 35, 30, "Scene-layers included in this render-layer (Hold CTRL for Z-mask)"); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, SCE_LAY_ALL_Z, B_NOP,"AllZ", 10, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Fill in Z values for all not-rendered faces, for masking"); + uiDefButBitI(block, TOG, SCE_LAY_ALL_Z, B_NOP,"AllZ", 10, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Fill in Z values for solid faces in invisible layers, for masking"); + uiDefButBitI(block, TOG, SCE_LAY_ZMASK, B_NOP,"Zmask", 10, 65, 40, 20, &srl->layflag, 0, 0, 0, 0, "Only render what's in front of the solid z values"); uiBlockBeginAlign(block); uiDefButBitI(block, TOG, SCE_LAY_SOLID, B_NOP,"Solid", 50, 85, 45, 20, &srl->layflag, 0, 0, 0, 0, "Render Solid faces in this Layer"); uiDefButBitI(block, TOG, SCE_LAY_HALO, B_NOP,"Halo", 95, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Halos in this Layer (on top of Solid)"); @@ -2635,8 +2636,8 @@ static void render_panel_layers(void) uiDefButBitI(block, TOG, SCE_LAY_EDGE, B_NOP,"Edge", 215, 85, 45, 20, &srl->layflag, 0, 0, 0, 0, "Render Edge-enhance in this Layer (only works for Solid faces)"); uiDefButBitI(block, TOG, SCE_LAY_STRAND, B_NOP,"Strand",260, 85, 50, 20, &srl->layflag, 0, 0, 0, 0, "Render Strands in this Layer"); - uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_SET_PASS, "Light:", 10, 65, 150, 20, &(srl->light_override), "Name of Group to use as Lamps instead"); - uiDefIDPoinBut(block, test_matpoin_but, ID_MA, B_SET_PASS, "Mat:", 160, 65, 150, 20, &(srl->mat_override), "Name of Material to use as Materials instead"); + uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_SET_PASS, "Light:", 50, 65, 130, 20, &(srl->light_override), "Name of Group to use as Lamps instead"); + uiDefIDPoinBut(block, test_matpoin_but, ID_MA, B_SET_PASS, "Mat:", 180, 65, 130, 20, &(srl->mat_override), "Name of Material to use as Materials instead"); uiBlockEndAlign(block); uiBlockBeginAlign(block); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 2ac76942da7..be307a649b3 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2283,8 +2283,8 @@ static void world_panel_world(World *wrld) uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); - uiDefButF(block, NUMSLI,B_WORLDPRV, "Exp ", 160,30,145,19, &(wrld->exp), 0.0, 1.0, 0, 2, "Sets amount of exponential color correction for light"); - uiDefButF(block, NUMSLI,B_WORLDPRV, "Range ", 160,10,145,19, &(wrld->range), 0.2, 5.0, 0, 2, "Sets the color amount that will be mapped on color 1.0"); + uiDefButF(block, NUMSLI,B_WORLDPRV2, "Exp ", 160,30,145,19, &(wrld->exp), 0.0, 1.0, 0, 2, "Sets amount of exponential color correction for light"); + uiDefButF(block, NUMSLI,B_WORLDPRV2, "Range ", 160,10,145,19, &(wrld->range), 0.2, 5.0, 0, 2, "Sets the color amount that will be mapped on color 1.0"); } @@ -2968,7 +2968,7 @@ void do_matbuts(unsigned short event) allqueue(REDRAWBUTSSHADING, 0); break; case B_WORLDPRV2: - BIF_preview_changed(ID_WO); + BIF_preview_changed(ID_TE); allqueue(REDRAWBUTSSHADING, 0); allqueue(REDRAWVIEW3D, 0); break; diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index a169af6cf93..3339385d565 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -813,19 +813,32 @@ static void draw_channel_strips(void) if (NLA_ACTION_SCALED) map_active_strip(di, OBACT, 0); - /* draw keyframes */ + /* Draw keyframes + * 1) Only channels that are visible in the Action Editor get drawn/evaluated. + * This is to try to optimise this for heavier data sets + * 2) Keyframes which are out of view horizontally could be disregarded (probably as + * option - 'drop-frames' or so). Todo... + */ y = 0.0; for (ale= act_data.first; ale; ale= ale->next) { - switch (ale->datatype) { - case ALE_GROUP: - draw_agroup_channel(di, ale->data, y); - break; - case ALE_IPO: - draw_ipo_channel(di, ale->key_data, y); - break; - case ALE_ICU: - draw_icu_channel(di, ale->key_data, y); - break; + float yminc= y-CHANNELHEIGHT/2; + float ymaxc= y+CHANNELHEIGHT/2; + + /* check if visible */ + if ( IN_RANGE(yminc, G.v2d->cur.ymin, G.v2d->cur.ymax) || + IN_RANGE(ymaxc, G.v2d->cur.ymin, G.v2d->cur.ymax) ) + { + switch (ale->datatype) { + case ALE_GROUP: + draw_agroup_channel(di, ale->data, y); + break; + case ALE_IPO: + draw_ipo_channel(di, ale->key_data, y); + break; + case ALE_ICU: + draw_icu_channel(di, ale->key_data, y); + break; + } } y-=CHANNELHEIGHT+CHANNELSKIP; diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 6c9e6ce1f6f..1c091ed39d9 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -1160,6 +1160,7 @@ void duplicate_action_keys (void) BLI_freelistN(&act_data); /* now, go into transform-grab mode, to move keys */ + BIF_TransformSetUndo("Add Duplicate"); transform_action_keys('g', 0); } diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c index ac5129dd021..ba73767387e 100644 --- a/source/blender/src/editconstraint.c +++ b/source/blender/src/editconstraint.c @@ -364,21 +364,21 @@ void add_constraint (short only_IK) else { if (pchanact) { if (pchansel) - nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); + nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); else if ((obsel) && (obsel->type==OB_CURVE)) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18"); + nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18"); else if (obsel) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); + nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); else - nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); + nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); } else { if ((obsel) && (obsel->type==OB_CURVE)) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18"); + nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18"); else if (obsel) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18"); + nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18"); else - nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18"); + nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18"); } } @@ -475,6 +475,7 @@ void add_constraint (short only_IK) } } else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM); + else if (nr==21) con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT); if (con==NULL) return; /* paranoia */ diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index 6fe2e032eed..b3ea3e1931c 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -2515,7 +2515,7 @@ static int match_adr_constraint(ID * id, int blocktype, char *actname, int adrco case CONSTRAINT_TYPE_LOCKTRACK: if (searchtype==2) foundmatch=1; break; - case CONSTRAINT_TYPE_DISTANCELIMIT: + case CONSTRAINT_TYPE_DISTLIMIT: if (searchtype==1) foundmatch=1; break; case CONSTRAINT_TYPE_MINMAX: diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 1992ea8468a..9fc6f1896ea 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -51,6 +51,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -1283,6 +1284,19 @@ static EditVert *subdivide_edge_addvert(EditEdge *edge, float rad, int beauty, f /* offset for smooth or sphere or fractal */ alter_co(co, edge, rad, beauty, percent); + /* clip if needed by mirror modifier */ + if (edge->v1->f2) { + if ( edge->v1->f2 & edge->v2->f2 & 1) { + co[0]= 0.0f; + } + if ( edge->v1->f2 & edge->v2->f2 & 2) { + co[1]= 0.0f; + } + if ( edge->v1->f2 & edge->v2->f2 & 4) { + co[2]= 0.0f; + } + } + ev = addvertlist(co, NULL); /* vert data (vgroups, ..) */ @@ -2403,12 +2417,39 @@ void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype) EditMesh *em = G.editMesh; EditFace *ef; EditEdge *eed, *cedge, *sort[4]; - EditVert **templist; + EditVert *eve, **templist; struct GHash *gh; float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3]; int i, j, edgecount, touchcount, facetype,hold; + ModifierData *md= G.obedit->modifiers.first; if(multires_test()) return; + + for (; md; md=md->next) { + if (md->type==eModifierType_Mirror) { + MirrorModifierData *mmd = (MirrorModifierData*) md; + + if(mmd->flag & MOD_MIR_CLIPPING) { + for (eve= em->verts.first; eve; eve= eve->next) { + eve->f2= 0; + switch(mmd->axis){ + case 0: + if (fabs(eve->co[0]) < mmd->tolerance) + eve->f2 |= 1; + break; + case 1: + if (fabs(eve->co[1]) < mmd->tolerance) + eve->f2 |= 2; + break; + case 2: + if (fabs(eve->co[2]) < mmd->tolerance) + eve->f2 |= 4; + break; + } + } + } + } + } //Set faces f1 to 0 cause we need it later for(ef=em->faces.first;ef;ef = ef->next) { diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index 645dc77c337..e42de1031e5 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -300,8 +300,12 @@ static void composit_node_event(SpaceNode *snode, short event) /* not the best implementation of the world... but we need it to work now :) */ if(node->type==CMP_NODE_R_LAYERS && node->custom2) { + /* add event for this window (after render curarea can be changed) */ + addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); + composite_node_render(snode, node); - /* new event, a render can go fullscreen and open new window */ + + /* add another event, a render can go fullscreen and open new window */ addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); } else { diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index cb1ed4c3e5a..a7b8400fb9d 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -5148,7 +5148,7 @@ void selectlinks_menu(void) /* If you modify this menu, please remember to update view3d_select_linksmenu * in header_view3d.c and the menu in toolbox.c */ - nr= pupmenu("Select Linked%t|Object Ipo%x1|ObData%x2|Material%x3|Texture%x4|DupliGroup%x5"); + nr= pupmenu("Select Linked%t|Object Ipo%x1|ObData%x2|Material%x3|Texture%x4|DupliGroup%x5|ParticleSystem%x6"); if (nr <= 0) return; @@ -5171,6 +5171,7 @@ void selectlinks(int nr) * Current Material: 3 * Current Texture: 4 * DupliGroup: 5 + * PSys: 6 */ @@ -5196,6 +5197,9 @@ void selectlinks(int nr) else if(nr==5) { if(ob->dup_group==NULL) return; } + else if(nr==6) { + if(ob->particlesystem.first==NULL) return; + } else return; base= FIRSTBASE; @@ -5224,6 +5228,7 @@ void selectlinks(int nr) if(tex==mat1->mtex[b]->tex) { base->flag |= SELECT; changed = 1; + break; } } } @@ -5236,6 +5241,25 @@ void selectlinks(int nr) changed = 1; } } + else if(nr==6) { + /* loop through other, then actives particles*/ + ParticleSystem *psys; + ParticleSystem *psys_act; + + for(psys=base->object->particlesystem.first; psys; psys=psys->next) { + for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) { + if (psys->part == psys_act->part) { + base->flag |= SELECT; + changed = 1; + break; + } + } + + if (base->flag & SELECT) { + break; + } + } + } base->object->flag= base->flag; } base= base->next; @@ -5580,17 +5604,9 @@ void mirrormenu(void) if(G.f & G_PARTICLEEDIT) { PE_mirror_x(0); } - else if (G.obedit==0) { - mode=pupmenu("Mirror Axis %t|X Local%x4|Y Local%x5|Z Local%x6|"); - - if (mode==-1) return; /* return */ - Mirror(mode); /* separating functionality from interface | call*/ - } else { - mode=pupmenu("Mirror Axis %t|X Global%x1|Y Global%x2|Z Global%x3|%l|X Local%x4|Y Local%x5|Z Local%x6|%l|X View%x7|Y View%x8|Z View%x9|"); - - if (mode==-1) return; /* return */ - Mirror(mode); /* separating functionality from interface | call*/ + initTransform(TFM_MIRROR, CTX_NO_PET); + Transform(); } } diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index 5d511b35633..a3bdbd0f7ab 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -788,7 +788,7 @@ void mouse_select_seq(void) int hand,seldir; TimeMarker *marker; - marker=find_nearest_marker(0, 1); + marker=find_nearest_marker(SCE_MARKERS, 1); if (marker) { int oldflag; diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index f7cf9dd22cd..4cbad8a9758 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1881,10 +1881,24 @@ static uiBlock *view3d_transformmenu(void *arg_unused) void do_view3d_object_mirrormenu(void *arg, int event) { switch(event) { + case 0: + initTransform(TFM_MIRROR, CTX_NO_PET); + Transform(); + break; case 1: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('X', " on X axis"); + Transform(); + break; case 2: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('Y', " on Y axis"); + Transform(); + break; case 3: - Mirror(event + 3); /* + 3 because the first three modes are global*/ + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('Z', " on Z axis"); + Transform(); break; } allqueue(REDRAWVIEW3D, 0); @@ -1898,9 +1912,11 @@ static uiBlock *view3d_object_mirrormenu(void *arg_unused) block= uiNewBlock(&curarea->uiblocks, "view3d_object_mirrormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); uiBlockSetButmFunc(block, do_view3d_object_mirrormenu, NULL); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Interactive Mirror|Ctrl M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); @@ -2853,17 +2869,44 @@ static uiBlock *view3d_edit_mesh_normalsmenu(void *arg_unused) void do_view3d_edit_mirrormenu(void *arg, int event) { + float mat[3][3]; + + Mat3One(mat); + switch(event) { + case 0: + initTransform(TFM_MIRROR, CTX_NO_PET); + Transform(); + break; case 1: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setSingleAxisConstraint(mat[0], " on global X axis"); + Transform(); + break; case 2: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setSingleAxisConstraint(mat[1], " on global Y axis"); + Transform(); + break; case 3: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setSingleAxisConstraint(mat[2], "on global Z axis"); + Transform(); + break; case 4: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('X', " on local X axis"); + Transform(); + break; case 5: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('Y', " on local Y axis"); + Transform(); + break; case 6: - case 7: - case 8: - case 9: - Mirror(event); + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('Z', " on local Z axis"); + Transform(); break; } allqueue(REDRAWVIEW3D, 0); @@ -2877,21 +2920,19 @@ static uiBlock *view3d_edit_mirrormenu(void *arg_unused) block= uiNewBlock(&curarea->uiblocks, "view3d_edit_mirrormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); uiBlockSetButmFunc(block, do_view3d_edit_mirrormenu, NULL); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|Ctrl M, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|Ctrl M, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|Ctrl M, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Interactive Mirror|Ctrl M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|Ctrl M, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|Ctrl M, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|Ctrl M, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X View|Ctrl M, 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y View|Ctrl M, 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z View|Ctrl M, 9", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, X X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, Y Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, Z Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index 63f39608f5d..c8ca48f64eb 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -2362,9 +2362,11 @@ void outliner_select(struct ScrArea *sa ) /* ************ SELECTION OPERATIONS ********* */ -static int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0; // globals, euh... you can do better - -static void set_operation_types(SpaceOops *soops, ListBase *lb) +static void set_operation_types(SpaceOops *soops, ListBase *lb, + int *scenelevel, + int *objectlevel, + int *idlevel, + int *datalevel) { TreeElement *te; TreeStoreElem *tselem; @@ -2374,22 +2376,22 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb) if(tselem->flag & TSE_SELECTED) { if(tselem->type) { #ifdef WITH_VERSE - if(te->idcode==ID_VS) datalevel= TSE_VERSE_SESSION; - else if(te->idcode==ID_VN) datalevel= TSE_VERSE_OBJ_NODE; - else if(datalevel==0) datalevel= tselem->type; + if(te->idcode==ID_VS) *datalevel= TSE_VERSE_SESSION; + else if(te->idcode==ID_VN) *datalevel= TSE_VERSE_OBJ_NODE; + else if(*datalevel==0) *datalevel= tselem->type; #else - if(datalevel==0) datalevel= tselem->type; + if(*datalevel==0) *datalevel= tselem->type; #endif - else if(datalevel!=tselem->type) datalevel= -1; + else if(*datalevel!=tselem->type) *datalevel= -1; } else { int idcode= GS(tselem->id->name); switch(idcode) { case ID_SCE: - scenelevel= 1; + *scenelevel= 1; break; case ID_OB: - objectlevel= 1; + *objectlevel= 1; break; case ID_ME: case ID_CU: case ID_MB: case ID_LT: @@ -2397,13 +2399,16 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb) case ID_MA: case ID_TE: case ID_IP: case ID_IM: case ID_SO: case ID_KE: case ID_WO: case ID_AC: case ID_NLA: case ID_TXT: case ID_GR: - if(idlevel==0) idlevel= idcode; - else if(idlevel!=idcode) idlevel= -1; + if(*idlevel==0) *idlevel= idcode; + else if(*idlevel!=idcode) *idlevel= -1; break; } } } - if((tselem->flag & TSE_CLOSED)==0) set_operation_types(soops, &te->subtree); + if((tselem->flag & TSE_CLOSED)==0) { + set_operation_types(soops, &te->subtree, + scenelevel, objectlevel, idlevel, datalevel); + } } } @@ -2559,6 +2564,30 @@ static void id_local_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tse } } +static void group_linkobs2scene_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +{ + Group *group= (Group *)tselem->id; + GroupObject *gob; + Base *base; + + for(gob=group->gobject.first; gob; gob=gob->next) { + base= object_in_scene(gob->ob, G.scene); + if (base) { + base->object->flag |= SELECT; + base->flag |= SELECT; + } else { + + /* link to scene */ + base= MEM_callocN( sizeof(Base), "add_base"); + BLI_addhead(&G.scene->base, base); + base->lay= (1<<20)-1; /*G.vd->lay;*/ /* would be nice to use the 3d layer but the include's not here */ + gob->ob->flag |= SELECT; + base->flag = gob->ob->flag; + base->object= gob->ob; + } + } +} + static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb, void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *)) { @@ -2674,11 +2703,9 @@ void outliner_del(ScrArea *sa) void outliner_operation_menu(ScrArea *sa) { SpaceOops *soops= sa->spacedata.first; + int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0; - // bad globals - scenelevel= objectlevel= idlevel= datalevel=0; - - set_operation_types(soops, &soops->tree); + set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); if(scenelevel) { if(objectlevel || datalevel || idlevel) error("Mixed selection"); @@ -2719,7 +2746,12 @@ void outliner_operation_menu(ScrArea *sa) else if(idlevel) { if(idlevel==-1 || datalevel) error("Mixed selection"); else { - short event= pupmenu("Unlink %x1|Make Local %x2"); + short event; + if (idlevel==ID_GR) + event = pupmenu("Unlink %x1|Make Local %x2|Link Group Objects to Scene%x3"); + else + event = pupmenu("Unlink %x1|Make Local %x2"); + if(event==1) { switch(idlevel) { @@ -2747,6 +2779,10 @@ void outliner_operation_menu(ScrArea *sa) BIF_undo_push("Localized Data"); allqueue(REDRAWALL, 0); } + else if(event==3 && idlevel==ID_GR) { + outliner_do_libdata_operation(soops, &soops->tree, group_linkobs2scene_cb); + BIF_undo_push("Link Group Objects to Scene"); + } } } else if(datalevel) { diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c index 2f7b4754d76..383b73b7619 100644 --- a/source/blender/src/previewrender.c +++ b/source/blender/src/previewrender.c @@ -270,6 +270,11 @@ static Scene *preview_prepare_scene(RenderInfo *ri, int id_type, ID *id, int pr_ sce->r.scemode |= R_PREVIEWBUTS; /* set world always back, is used now */ sce->world= pr_main->world.first; + /* now: exposure copy */ + if(G.scene->world) { + sce->world->exp= G.scene->world->exp; + sce->world->range= G.scene->world->range; + } sce->r.cfra= G.scene->r.cfra; diff --git a/source/blender/src/sculptmode-stroke.c b/source/blender/src/sculptmode-stroke.c index c2c96b04a1d..69c20eeeddf 100644 --- a/source/blender/src/sculptmode-stroke.c +++ b/source/blender/src/sculptmode-stroke.c @@ -178,7 +178,7 @@ float sculpt_stroke_final_length(SculptStroke *stroke) } /* If partial is nonzero, cuts off apply after that length has been processed */ -static StrokePoint *sculpt_stroke_apply_generic(SculptStroke *stroke, struct EditData *e, const int partial) +static StrokePoint *sculpt_stroke_apply_generic(SculptStroke *stroke, struct BrushAction *a, const int partial) { const int sdspace = sculpt_data()->spacing; const short spacing = sdspace > 0 ? sdspace : 2; @@ -215,13 +215,13 @@ static StrokePoint *sculpt_stroke_apply_generic(SculptStroke *stroke, struct Edi co[0] = p->x*v + p->next->x*u; co[1] = p->y*v + p->next->y*u; - do_symmetrical_brush_actions(e, co, NULL); + do_symmetrical_brush_actions(a, co, NULL); } return p ? p->next : NULL; } -void sculpt_stroke_apply(struct EditData *e) +void sculpt_stroke_apply(struct BrushAction *a) { SculptStroke *stroke = sculpt_session()->stroke; /* TODO: make these values user-modifiable? */ @@ -232,7 +232,7 @@ void sculpt_stroke_apply(struct EditData *e) sculpt_stroke_create_final(); if(sculpt_stroke_final_length(stroke) > min_len) { - StrokePoint *p = sculpt_stroke_apply_generic(stroke, e, partial_len); + StrokePoint *p = sculpt_stroke_apply_generic(stroke, a, partial_len); /* Replace remaining values in stroke->loc with remaining stroke->final values */ stroke->index = -1; @@ -249,14 +249,14 @@ void sculpt_stroke_apply(struct EditData *e) } } -void sculpt_stroke_apply_all(struct EditData *e) +void sculpt_stroke_apply_all(struct BrushAction *a) { SculptStroke *stroke = sculpt_session()->stroke; sculpt_stroke_create_final(); if(stroke) { - sculpt_stroke_apply_generic(stroke, e, 0); + sculpt_stroke_apply_generic(stroke, a, 0); } } diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index 9e1fa16a44c..dbefadb2646 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -125,36 +125,39 @@ typedef struct ActiveData { float dist; } ActiveData; -typedef struct GrabData { - char firsttime; - ListBase active_verts[8]; - unsigned char index; - vec3f delta, delta_symm; - float depth; -} GrabData; +typedef struct BrushActionSymm { + float center_3d[3]; + char index; -typedef struct EditData { - vec3f center; - float size; - char flip; - short mouse[2]; + float up[3], right[3], out[3]; - /* Adjust brush strength along each axis - to adjust for object scaling */ - float scale[3]; + // Grab brush + float grab_delta[3]; +} BrushActionSymm; - /* View normals */ - vec3f up, right, out; +typedef struct BrushAction { + BrushActionSymm symm; + + char firsttime; + + short mouse[2]; + float size_3d; - GrabData *grabdata; float *layer_disps; vec3f *layer_store; - + char flip; + char clip[3]; float cliptol[3]; - - char symm; -} EditData; + + // Grab brush + ListBase grab_active_verts[8]; + float depth; + + /* Adjust brush strength along each axis + to adjust for object scaling */ + float scale[3]; +} BrushAction; typedef struct RectNode { struct RectNode *next, *prev; @@ -178,7 +181,7 @@ SculptData *sculpt_data(void) } void sculpt_init_session(void); -void init_editdata(EditData *e, short *, short *); +void init_brushaction(BrushAction *a, short *, short *); void sculpt_undo_push(const short); SculptSession *sculpt_session(void) @@ -294,18 +297,16 @@ float get_depth(short x, short y) /* Uses window coordinates (x,y) and depth component z to find a point in modelspace */ -vec3f unproject(const short x, const short y, const float z) +void unproject(float out[3], const short x, const short y, const float z) { SculptSession *ss= sculpt_session(); double ux, uy, uz; - vec3f p; gluUnProject(x,y,z, ss->mats->modelview, ss->mats->projection, (GLint *)ss->mats->viewport, &ux, &uy, &uz ); - p.x= ux; - p.y= uy; - p.z= uz; - return p; + out[0] = ux; + out[1] = uy; + out[2] = uz; } /* Convert a point in model coordinates to 2D screen coordinates. */ @@ -348,13 +349,13 @@ char brush_size() /* Return modified brush strength. Includes the direction of the brush, positive values pull vertices, negative values push. Uses tablet pressure and a special multiplier found experimentally to scale the strength factor. */ -float brush_strength(EditData *e) +float brush_strength(BrushAction *a) { const BrushData* b= sculptmode_brush(); float dir= b->dir==1 ? 1 : -1; float pressure= 1; short activedevice= get_activedevice(); - float flip= e->flip ? -1:1; + float flip= a->flip ? -1:1; const float strength_factor= G.scene->sculptdata.tablet_strength / 10.0f; if(ELEM(activedevice, DEV_STYLUS, DEV_ERASER)) @@ -385,11 +386,11 @@ float brush_strength(EditData *e) } /* For clipping against a mirror modifier */ -void sculpt_clip(const EditData *e, float *co, const float val[3]) +void sculpt_clip(const BrushAction *a, float *co, const float val[3]) { char i; for(i=0; i<3; ++i) { - if(e->clip[i] && (fabs(co[i]) <= e->cliptol[i])) + if(a->clip[i] && (fabs(co[i]) <= a->cliptol[i])) co[i]= 0.0f; else co[i]= val[i]; @@ -398,7 +399,7 @@ void sculpt_clip(const EditData *e, float *co, const float val[3]) /* Currently only for the draw brush; finds average normal for all active vertices */ -vec3f calc_area_normal(const vec3f *outdir, const ListBase* active_verts) +vec3f calc_area_normal(const float *outdir, const ListBase* active_verts) { Mesh *me= get_mesh(OBACT); vec3f area_normal= {0,0,0}; @@ -412,28 +413,30 @@ vec3f calc_area_normal(const vec3f *outdir, const ListBase* active_verts) node= node->next; } Normalize(&area_normal.x); + if(outdir) { - area_normal.x= outdir->x * view + area_normal.x * (10-view); - area_normal.y= outdir->y * view + area_normal.y * (10-view); - area_normal.z= outdir->z * view + area_normal.z * (10-view); + area_normal.x= outdir[0] * view + area_normal.x * (10-view); + area_normal.y= outdir[1] * view + area_normal.y * (10-view); + area_normal.z= outdir[2] * view + area_normal.z * (10-view); } + Normalize(&area_normal.x); return area_normal; } -void do_draw_brush(const EditData *e, const ListBase* active_verts) +void do_draw_brush(const BrushAction *a, const ListBase* active_verts) { Mesh *me= get_mesh(OBACT); - const vec3f area_normal= calc_area_normal(&e->out, active_verts); + const vec3f area_normal= calc_area_normal(a->symm.out, active_verts); ActiveData *node= active_verts->first; while(node){ float *co= me->mvert[node->Index].co; - const float val[3]= {co[0]+area_normal.x*node->Fade*e->scale[0], - co[1]+area_normal.y*node->Fade*e->scale[1], - co[2]+area_normal.z*node->Fade*e->scale[2]}; + const float val[3]= {co[0]+area_normal.x*node->Fade*a->scale[0], + co[1]+area_normal.y*node->Fade*a->scale[1], + co[2]+area_normal.z*node->Fade*a->scale[2]}; - sculpt_clip(e, co, val); + sculpt_clip(a, co, val); node= node->next; } @@ -489,7 +492,7 @@ vec3f neighbor_average(const int vert) return avg; } -void do_smooth_brush(const EditData *e, const ListBase* active_verts) +void do_smooth_brush(const BrushAction *a, const ListBase* active_verts) { ActiveData *node= active_verts->first; Mesh *me= get_mesh(OBACT); @@ -500,53 +503,53 @@ void do_smooth_brush(const EditData *e, const ListBase* active_verts) const float val[3]= {co[0]+(avg.x-co[0])*node->Fade, co[1]+(avg.y-co[1])*node->Fade, co[2]+(avg.z-co[2])*node->Fade}; - sculpt_clip(e, co, val); + sculpt_clip(a, co, val); node= node->next; } } -void do_pinch_brush(const EditData *e, const ListBase* active_verts) +void do_pinch_brush(const BrushAction *a, const ListBase* active_verts) { Mesh *me= get_mesh(OBACT); ActiveData *node= active_verts->first; while(node) { float *co= me->mvert[node->Index].co; - const float val[3]= {co[0]+(e->center.x-co[0])*node->Fade, - co[1]+(e->center.y-co[1])*node->Fade, - co[2]+(e->center.z-co[2])*node->Fade}; - sculpt_clip(e, co, val); + const float val[3]= {co[0]+(a->symm.center_3d[0]-co[0])*node->Fade, + co[1]+(a->symm.center_3d[1]-co[1])*node->Fade, + co[2]+(a->symm.center_3d[2]-co[2])*node->Fade}; + sculpt_clip(a, co, val); node= node->next; } } -void do_grab_brush(EditData *e) +void do_grab_brush(BrushAction *a) { Mesh *me= get_mesh(OBACT); - ActiveData *node= e->grabdata->active_verts[e->grabdata->index].first; + ActiveData *node= a->grab_active_verts[a->symm.index].first; float add[3]; while(node) { float *co= me->mvert[node->Index].co; - VecCopyf(add, &e->grabdata->delta_symm.x); + VecCopyf(add, a->symm.grab_delta); VecMulf(add, node->Fade); VecAddf(add, add, co); - sculpt_clip(e, co, add); + sculpt_clip(a, co, add); node= node->next; } } -void do_layer_brush(EditData *e, const ListBase *active_verts) +void do_layer_brush(BrushAction *a, const ListBase *active_verts) { Mesh *me= get_mesh(OBACT); vec3f area_normal= calc_area_normal(NULL, active_verts); ActiveData *node= active_verts->first; - const float bstr= brush_strength(e); + const float bstr= brush_strength(a); while(node){ - float *disp= &e->layer_disps[node->Index]; + float *disp= &a->layer_disps[node->Index]; if((bstr > 0 && *disp < bstr) || (bstr < 0 && *disp > bstr)) { @@ -563,10 +566,10 @@ void do_layer_brush(EditData *e, const ListBase *active_verts) } { - const float val[3]= {e->layer_store[node->Index].x+area_normal.x * *disp*e->scale[0], - e->layer_store[node->Index].y+area_normal.y * *disp*e->scale[1], - e->layer_store[node->Index].z+area_normal.z * *disp*e->scale[2]}; - sculpt_clip(e, co, val); + const float val[3]= {a->layer_store[node->Index].x+area_normal.x * *disp*a->scale[0], + a->layer_store[node->Index].y+area_normal.y * *disp*a->scale[1], + a->layer_store[node->Index].z+area_normal.z * *disp*a->scale[2]}; + sculpt_clip(a, co, val); } } @@ -574,7 +577,7 @@ void do_layer_brush(EditData *e, const ListBase *active_verts) } } -void do_inflate_brush(const EditData *e, const ListBase *active_verts) +void do_inflate_brush(const BrushAction *a, const ListBase *active_verts) { ActiveData *node= active_verts->first; float add[3]; @@ -588,18 +591,18 @@ void do_inflate_brush(const EditData *e, const ListBase *active_verts) add[1]= no[1]/ 32767.0f; add[2]= no[2]/ 32767.0f; VecMulf(add, node->Fade); - add[0]*= e->scale[0]; - add[1]*= e->scale[1]; - add[2]*= e->scale[2]; + add[0]*= a->scale[0]; + add[1]*= a->scale[1]; + add[2]*= a->scale[2]; VecAddf(add, add, co); - sculpt_clip(e, co, add); + sculpt_clip(a, co, add); node= node->next; } } -void calc_flatten_center(Mesh *me, ActiveData *node, const EditData *e, float co[3]) +void calc_flatten_center(Mesh *me, ActiveData *node, float co[3]) { ActiveData *outer[FLATTEN_SAMPLE_SIZE]; int i; @@ -622,15 +625,15 @@ void calc_flatten_center(Mesh *me, ActiveData *node, const EditData *e, float co VecMulf(co, 1.0f / FLATTEN_SAMPLE_SIZE); } -void do_flatten_brush(const EditData *e, const ListBase *active_verts) +void do_flatten_brush(const BrushAction *a, const ListBase *active_verts) { Mesh *me= get_mesh(OBACT); ActiveData *node= active_verts->first; /* area_normal and cntr define the plane towards which vertices are squashed */ - vec3f area_normal= calc_area_normal(&e->out, active_verts); + vec3f area_normal= calc_area_normal(a->symm.out, active_verts); float cntr[3]; - calc_flatten_center(me, node, e, cntr); + calc_flatten_center(me, node, cntr); while(node){ float *co= me->mvert[node->Index].co; @@ -648,7 +651,7 @@ void do_flatten_brush(const EditData *e, const ListBase *active_verts) VecMulf(val, node->Fade); VecAddf(val, val, co); - sculpt_clip(e, co, val); + sculpt_clip(a, co, val); node= node->next; } @@ -709,7 +712,7 @@ unsigned *get_texcache_pixel(const SculptSession *ss, int px, int py) } /* Return a multiplier for brush strength on a particular vertex. */ -float tex_strength(EditData *e, float *point, const float len,const unsigned vindex) +float tex_strength(BrushAction *a, float *point, const float len,const unsigned vindex) { SculptData *sd= sculpt_data(); SculptSession *ss= sculpt_session(); @@ -747,12 +750,12 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin /* If the active area is being applied for symmetry, flip it across the symmetry axis in order to project it. This insures that the brush texture will be oriented correctly. */ - if(!e->symm) + if(!a->symm.index) pv= ss->projverts[vindex]; else { float co[3]; VecCopyf(co, point); - flip_coord(co, e->symm); + flip_coord(co, a->symm.index); project(co, pv.co); } @@ -781,15 +784,15 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin py %= sy-1; p= get_texcache_pixel(ss, tcw*px/sx, tch*py/sy); } else { - float fx= (pv.co[0] - e->mouse[0] + half) * (tcw*1.0f/bsize) - tcw/2; - float fy= (pv.co[1] - e->mouse[1] + half) * (tch*1.0f/bsize) - tch/2; - + float fx= (pv.co[0] - a->mouse[0] + half) * (tcw*1.0f/bsize) - tcw/2; + float fy= (pv.co[1] - a->mouse[1] + half) * (tch*1.0f/bsize) - tch/2; + float angle= atan2(fy, fx) - rot; float len= sqrtf(fx*fx + fy*fy); px= tcw/2 + len * cos(angle); py= tch/2 + len * sin(angle); - + p= get_texcache_pixel(ss, px, py); } @@ -801,7 +804,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin } if(sd->texfade) - avg*= curve_strength(len,e->size); /* Smooth curve */ + avg*= curve_strength(len, a->size_3d); /* Smooth curve */ return avg; } @@ -809,7 +812,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin /* Mark area around the brush as damaged. projverts are marked if they are inside the area and the damaged rectangle in 2D screen coordinates is added to damaged_rects. */ -void sculpt_add_damaged_rect(EditData *e) +void sculpt_add_damaged_rect(BrushAction *a) { short p[2]; const float radius= brush_size(); @@ -819,7 +822,7 @@ void sculpt_add_damaged_rect(EditData *e) unsigned i; /* Find center */ - project(&e->center.x, p); + project(a->symm.center_3d, p); rn->r.xmin= p[0]-radius; rn->r.ymin= p[1]-radius; rn->r.xmax= p[0]+radius; @@ -868,7 +871,7 @@ void sculpt_clear_damaged_areas(SculptSession *ss) } } -void do_brush_action(EditData e) +void do_brush_action(BrushAction *a) { int i; float av_dist; @@ -876,29 +879,32 @@ void do_brush_action(EditData e) ActiveData *adata= 0; float *vert; Mesh *me= get_mesh(OBACT); - const float bstrength= brush_strength(&e); + const float bstrength= brush_strength(a); KeyBlock *keyblock= ob_get_keyblock(OBACT); + SculptData *sd = sculpt_data(); SculptSession *ss = sculpt_session(); - sculpt_add_damaged_rect(&e); + sculpt_add_damaged_rect(a); /* Build a list of all vertices that are potentially within the brush's area of influence. Only do this once for the grab brush. */ - if(!e.grabdata || (e.grabdata && e.grabdata->firsttime)) { + if((sd->brush_type != GRAB_BRUSH) || a->firsttime) { for(i=0; i<me->totvert; ++i) { /* Projverts.inside provides a rough bounding box */ if(ss->projverts[i].inside) { vert= ss->vertexcosnos ? &ss->vertexcosnos[i*6] : me->mvert[i].co; - av_dist= VecLenf(&e.center.x,vert); - if(av_dist < e.size) { + av_dist= VecLenf(a->symm.center_3d, vert); + if(av_dist < a->size_3d) { adata= (ActiveData*)MEM_mallocN(sizeof(ActiveData), "ActiveData"); + adata->Index = i; /* Fade is used to store the final strength at which the brush should modify a particular vertex. */ - adata->Fade= tex_strength(&e,vert,av_dist,i) * bstrength; + adata->Fade= tex_strength(a, vert, av_dist, i) * bstrength; adata->dist = av_dist; - if(e.grabdata && e.grabdata->firsttime) - BLI_addtail(&e.grabdata->active_verts[e.grabdata->index], adata); + + if(sd->brush_type == GRAB_BRUSH && a->firsttime) + BLI_addtail(&a->grab_active_verts[a->symm.index], adata); else BLI_addtail(&active_verts, adata); } @@ -907,29 +913,29 @@ void do_brush_action(EditData e) } /* Only act if some verts are inside the brush area */ - if(active_verts.first || (e.grabdata && e.grabdata->active_verts[e.grabdata->index].first)) { + if(active_verts.first || (sd->brush_type == GRAB_BRUSH && a->grab_active_verts[a->symm.index].first)) { /* Apply one type of brush action */ switch(G.scene->sculptdata.brush_type){ case DRAW_BRUSH: - do_draw_brush(&e, &active_verts); + do_draw_brush(a, &active_verts); break; case SMOOTH_BRUSH: - do_smooth_brush(&e, &active_verts); + do_smooth_brush(a, &active_verts); break; case PINCH_BRUSH: - do_pinch_brush(&e, &active_verts); + do_pinch_brush(a, &active_verts); break; case INFLATE_BRUSH: - do_inflate_brush(&e, &active_verts); + do_inflate_brush(a, &active_verts); break; case GRAB_BRUSH: - do_grab_brush(&e); + do_grab_brush(a); break; case LAYER_BRUSH: - do_layer_brush(&e, &active_verts); + do_layer_brush(a, &active_verts); break; case FLATTEN_BRUSH: - do_flatten_brush(&e, &active_verts); + do_flatten_brush(a, &active_verts); break; } @@ -937,7 +943,11 @@ void do_brush_action(EditData e) if(keyblock) { float *co= keyblock->data; if(co) { - adata = e.grabdata ? e.grabdata->active_verts[e.grabdata->index].first : active_verts.first; + if(sd->brush_type == GRAB_BRUSH) + adata = a->grab_active_verts[a->symm.index].first; + else + adata = active_verts.first; + for(; adata; adata= adata->next) if(adata->Index < keyblock->totelem) VecCopyf(&co[adata->Index*3], me->mvert[adata->Index].co); @@ -947,7 +957,7 @@ void do_brush_action(EditData e) if(ss->vertexcosnos) BLI_freelistN(&active_verts); else { - if(!e.grabdata) + if(sd->brush_type != GRAB_BRUSH) addlisttolist(&ss->damaged_verts, &active_verts); } } @@ -955,51 +965,37 @@ void do_brush_action(EditData e) /* Flip all the editdata across the axis/axes specified by symm. Used to calculate multiple modifications to the mesh when symmetry is enabled. */ -EditData flip_editdata(EditData *e, const char symm) +void calc_brushdata_symm(BrushAction *a, const char symm) { - EditData fe= *e; - GrabData *gd= fe.grabdata; - - flip_coord(&fe.center.x, symm); - flip_coord(&fe.up.x, symm); - flip_coord(&fe.right.x, symm); - flip_coord(&fe.out.x, symm); + flip_coord(a->symm.center_3d, symm); + flip_coord(a->symm.up, symm); + flip_coord(a->symm.right, symm); + flip_coord(a->symm.out, symm); - fe.symm= symm; - - project(&e->center.x,fe.mouse); - - if(gd) { - gd->index= symm; - gd->delta_symm= gd->delta; - flip_coord(&gd->delta_symm.x, symm); - } + a->symm.index= symm; - return fe; + flip_coord(a->symm.grab_delta, symm); } -void do_symmetrical_brush_actions(EditData * e, short co[2], short pr_co[2]) +void do_symmetrical_brush_actions(BrushAction *a, short co[2], short pr_co[2]) { - const char symm= sculpt_data()->symm; + const char symm = sculpt_data()->symm; + BrushActionSymm orig; + int i; - init_editdata(e, co, pr_co); - - do_brush_action(flip_editdata(e, 0)); + init_brushaction(a, co, pr_co); + orig = a->symm; + do_brush_action(a); - if(symm & SYMM_X) - do_brush_action(flip_editdata(e, SYMM_X)); - if(symm & SYMM_Y) - do_brush_action(flip_editdata(e, SYMM_Y)); - if(symm & SYMM_Z) - do_brush_action(flip_editdata(e, SYMM_Z)); - if(symm & SYMM_X && symm & SYMM_Y) - do_brush_action(flip_editdata(e, SYMM_X | SYMM_Y)); - if(symm & SYMM_X && symm & SYMM_Z) - do_brush_action(flip_editdata(e, SYMM_X | SYMM_Z)); - if(symm & SYMM_Y && symm & SYMM_Z) - do_brush_action(flip_editdata(e, SYMM_Y | SYMM_Z)); - if(symm & SYMM_X && symm & SYMM_Y && symm & SYMM_Z) - do_brush_action(flip_editdata(e, SYMM_X | SYMM_Y | SYMM_Z)); + for(i = 1; i <= symm; ++i) { + if(symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))) { + // Restore the original symmetry data + a->symm = orig; + + calc_brushdata_symm(a, i); + do_brush_action(a); + } + } } void add_face_normal(vec3f *norm, const MFace* face) @@ -1039,19 +1035,17 @@ void update_damaged_vert(Mesh *me, ListBase *lb) } } -void calc_damaged_verts(ListBase *damaged_verts, GrabData *grabdata) +void calc_damaged_verts(ListBase *damaged_verts, BrushAction *a) { Mesh *me= get_mesh(OBACT); + int i; + + for(i=0; i<8; ++i) + update_damaged_vert(me, &a->grab_active_verts[i]); - if(grabdata) { - int i; - for(i=0; i<8; ++i) - update_damaged_vert(me,&grabdata->active_verts[i]); - } else { - update_damaged_vert(me,damaged_verts); - BLI_freelistN(damaged_verts); - damaged_verts->first = damaged_verts->last = NULL; - } + update_damaged_vert(me, damaged_verts); + BLI_freelistN(damaged_verts); + damaged_verts->first = damaged_verts->last = NULL; } void projverts_clear_inside(SculptSession *ss) @@ -1137,83 +1131,80 @@ void sculptmode_update_tex() } /* pr_mouse is only used for the grab brush, can be NULL otherwise */ -void init_editdata(EditData *e, short *mouse, short *pr_mouse) +void init_brushaction(BrushAction *a, short *mouse, short *pr_mouse) { SculptData *sd = sculpt_data(); - const float mouse_depth= get_depth(mouse[0],mouse[1]); - vec3f brush_edge_loc, zero_loc, oldloc; + const float mouse_depth = get_depth(mouse[0], mouse[1]); + float brush_edge_loc[3], zero_loc[3], oldloc[3]; ModifierData *md; int i; const char flip = (get_qual() == LR_SHIFTKEY); - e->flip= flip; + a->flip = flip; + a->symm.index = 0; + a->mouse[0] = mouse[0]; + a->mouse[1] = mouse[1]; /* Convert the location and size of the brush to modelspace coords */ - e->center= unproject(mouse[0],mouse[1],mouse_depth); - brush_edge_loc= unproject(mouse[0] + - brush_size(),mouse[1], - mouse_depth); - e->size= VecLenf(&e->center.x,&brush_edge_loc.x); + unproject(a->symm.center_3d, mouse[0], mouse[1], mouse_depth); + unproject(brush_edge_loc, mouse[0] + brush_size(), mouse[1], mouse_depth); + a->size_3d = VecLenf(a->symm.center_3d, brush_edge_loc); /* Set the pivot to allow the model to rotate around the center of the brush */ if(get_depth(mouse[0],mouse[1]) < 1.0) - sculpt_session()->pivot= e->center; + VecCopyf(&sculpt_session()->pivot.x, a->symm.center_3d); /* Now project the Up, Right, and Out normals from view to model coords */ - zero_loc= unproject(0, 0, 0); - e->up= unproject(0, -1, 0); - e->right= unproject(1, 0, 0); - e->out= unproject(0, 0, -1); - VecSubf(&e->up.x, &e->up.x, &zero_loc.x); - VecSubf(&e->right.x, &e->right.x, &zero_loc.x); - VecSubf(&e->out.x, &e->out.x, &zero_loc.x); - Normalize(&e->up.x); - Normalize(&e->right.x); - Normalize(&e->out.x); + unproject(zero_loc, 0, 0, 0); + unproject(a->symm.up, 0, -1, 0); + unproject(a->symm.right, 1, 0, 0); + unproject(a->symm.out, 0, 0, -1); + VecSubf(a->symm.up, a->symm.up, zero_loc); + VecSubf(a->symm.right, a->symm.right, zero_loc); + VecSubf(a->symm.out, a->symm.out, zero_loc); + Normalize(a->symm.up); + Normalize(a->symm.right); + Normalize(a->symm.out); /* Initialize mirror modifier clipping */ for(i=0; i<3; ++i) { - e->clip[i]= 0; - e->cliptol[i]= 0; + a->clip[i]= 0; + a->cliptol[i]= 0; } for(md= OBACT->modifiers.first; md; md= md->next) { if(md->type==eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) { const MirrorModifierData *mmd = (MirrorModifierData*) md; if(mmd->flag & MOD_MIR_CLIPPING) { - e->clip[mmd->axis]= 1; - if(mmd->tolerance > e->cliptol[mmd->axis]) - e->cliptol[mmd->axis]= mmd->tolerance; + a->clip[mmd->axis]= 1; + if(mmd->tolerance > a->cliptol[mmd->axis]) + a->cliptol[mmd->axis] = mmd->tolerance; } } } if(sd->brush_type == GRAB_BRUSH) { - vec3f gcenter; - if(!e->grabdata) { - e->grabdata= MEM_callocN(sizeof(GrabData),"grab data"); - e->grabdata->firsttime= 1; - e->grabdata->depth= mouse_depth; - } - else - e->grabdata->firsttime= 0; - + float gcenter[3]; + + if(a->firsttime) + a->depth = mouse_depth; + /* Find the delta */ - gcenter= unproject(mouse[0],mouse[1],e->grabdata->depth); - oldloc= unproject(pr_mouse[0],pr_mouse[1],e->grabdata->depth); - VecSubf(&e->grabdata->delta.x,&gcenter.x,&oldloc.x); + unproject(gcenter, mouse[0], mouse[1], a->depth); + unproject(oldloc, pr_mouse[0], pr_mouse[1], a->depth); + VecSubf(a->symm.grab_delta, gcenter, oldloc); } else if(sd->brush_type == LAYER_BRUSH) { Mesh *me= get_mesh(OBACT); - if(!e->layer_disps) - e->layer_disps= MEM_callocN(sizeof(float)*me->totvert,"Layer disps"); - if(!e->layer_store) { + if(!a->layer_disps) + a->layer_disps= MEM_callocN(sizeof(float)*me->totvert,"Layer disps"); + if(!a->layer_store) { unsigned i; - e->layer_store= MEM_mallocN(sizeof(vec3f)*me->totvert,"Layer store"); + a->layer_store= MEM_mallocN(sizeof(vec3f)*me->totvert,"Layer store"); for(i=0; i<me->totvert; ++i) - VecCopyf(&e->layer_store[i].x,me->mvert[i].co); + VecCopyf(&a->layer_store[i].x, me->mvert[i].co); } } } @@ -1470,11 +1461,11 @@ void sculpt(void) /* lastSigMouse is for the rake, to store the last place the mouse movement was significant */ short mouse[2], mvalo[2], lastSigMouse[2],firsttime=1, mousebut; short modifier_calculations= 0; - EditData e; + BrushAction *a = MEM_callocN(sizeof(BrushAction), "brush action"); short spacing= 32000; int scissor_box[4]; float offsetRot; - int smooth_stroke = 0; + int smooth_stroke = 0, i; if(!(G.f & G_SCULPTMODE) || G.obedit || !ob || ob->id.lib || !get_mesh(ob) || (get_mesh(ob)->totface == 0)) return; @@ -1541,14 +1532,13 @@ void sculpt(void) ss->vertexcosnos= mesh_get_mapped_verts_nors(ob); sculptmode_update_all_projverts(ss->vertexcosnos); - e.grabdata= NULL; - e.layer_disps= NULL; - e.layer_store= NULL; + a->layer_disps= NULL; + a->layer_store= NULL; /* Set scaling adjustment */ - e.scale[0]= 1.0f / ob->size[0]; - e.scale[1]= 1.0f / ob->size[1]; - e.scale[2]= 1.0f / ob->size[2]; + a->scale[0]= 1.0f / ob->size[0]; + a->scale[1]= 1.0f / ob->size[1]; + a->scale[2]= 1.0f / ob->size[2]; /* Capture original copy */ if(sd->flags & SCULPT_DRAW_FAST) @@ -1571,6 +1561,7 @@ void sculpt(void) } if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] || sculptmode_brush()->airbrush) { + a->firsttime = firsttime; firsttime= 0; if(smooth_stroke) @@ -1583,27 +1574,27 @@ void sculpt(void) if(G.scene->sculptdata.brush_type != GRAB_BRUSH) { if(smooth_stroke) { - sculpt_stroke_apply(&e); + sculpt_stroke_apply(a); } else if(sd->spacing==0 || spacing>sd->spacing) { - do_symmetrical_brush_actions(&e, mouse, NULL); + do_symmetrical_brush_actions(a, mouse, NULL); spacing= 0; } } else { - do_symmetrical_brush_actions(&e, mouse, mvalo); - ss->pivot= unproject(mouse[0],mouse[1],e.grabdata->depth); + do_symmetrical_brush_actions(a, mouse, mvalo); + unproject(&ss->pivot.x, mouse[0], mouse[1], a->depth); } if(modifier_calculations || ob_get_keyblock(ob)) DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); if(modifier_calculations || sd->brush_type == GRAB_BRUSH || !(sd->flags & SCULPT_DRAW_FAST)) { - calc_damaged_verts(&ss->damaged_verts,e.grabdata); + calc_damaged_verts(&ss->damaged_verts, a); scrarea_do_windraw(curarea); screen_swapbuffers(); } else { /* Optimized drawing */ - calc_damaged_verts(&ss->damaged_verts,e.grabdata); + calc_damaged_verts(&ss->damaged_verts, a); /* Draw the stored image to the screen */ glAccum(GL_RETURN, 1); @@ -1648,20 +1639,16 @@ void sculpt(void) set_tex_angle(offsetRot); if(smooth_stroke) { - sculpt_stroke_apply_all(&e); - calc_damaged_verts(&ss->damaged_verts,e.grabdata); + sculpt_stroke_apply_all(a); + calc_damaged_verts(&ss->damaged_verts, a); BLI_freelistN(&ss->damaged_rects); } - if(e.layer_disps) MEM_freeN(e.layer_disps); - if(e.layer_store) MEM_freeN(e.layer_store); - /* Free GrabData */ - if(e.grabdata) { - int i; - for(i=0; i<8; ++i) - BLI_freelistN(&e.grabdata->active_verts[i]); - MEM_freeN(e.grabdata); - } + if(a->layer_disps) MEM_freeN(a->layer_disps); + if(a->layer_store) MEM_freeN(a->layer_store); + for(i=0; i<8; ++i) + BLI_freelistN(&a->grab_active_verts[i]); + MEM_freeN(a); sculpt_stroke_free(); sculpt_undo_push(G.scene->sculptdata.brush_type); @@ -1728,7 +1715,7 @@ void set_sculptmode(void) static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode) { Mesh *me= get_mesh(ob); - vec3f hidebox[6]; + float hidebox[6][3]; vec3f plane_normals[4]; float plane_ds[4]; unsigned i, j; @@ -1740,23 +1727,23 @@ static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode) const unsigned SHOW= 0, HIDE=1; /* Convert hide box from 2D to 3D */ - hidebox[0]= unproject(hb_2d->xmin, hb_2d->ymax, 1); - hidebox[1]= unproject(hb_2d->xmax, hb_2d->ymax, 1); - hidebox[2]= unproject(hb_2d->xmax, hb_2d->ymin, 1); - hidebox[3]= unproject(hb_2d->xmin, hb_2d->ymin, 1); - hidebox[4]= unproject(hb_2d->xmin, hb_2d->ymax, 0); - hidebox[5]= unproject(hb_2d->xmax, hb_2d->ymin, 0); + unproject(hidebox[0], hb_2d->xmin, hb_2d->ymax, 1); + unproject(hidebox[1], hb_2d->xmax, hb_2d->ymax, 1); + unproject(hidebox[2], hb_2d->xmax, hb_2d->ymin, 1); + unproject(hidebox[3], hb_2d->xmin, hb_2d->ymin, 1); + unproject(hidebox[4], hb_2d->xmin, hb_2d->ymax, 0); + unproject(hidebox[5], hb_2d->xmax, hb_2d->ymin, 0); /* Calculate normals for each side of hide box */ - CalcNormFloat(&hidebox[0].x,&hidebox[1].x,&hidebox[4].x,&plane_normals[0].x); - CalcNormFloat(&hidebox[1].x,&hidebox[2].x,&hidebox[5].x,&plane_normals[1].x); - CalcNormFloat(&hidebox[2].x,&hidebox[3].x,&hidebox[5].x,&plane_normals[2].x); - CalcNormFloat(&hidebox[3].x,&hidebox[0].x,&hidebox[4].x,&plane_normals[3].x); + CalcNormFloat(hidebox[0], hidebox[1], hidebox[4], &plane_normals[0].x); + CalcNormFloat(hidebox[1], hidebox[2], hidebox[5], &plane_normals[1].x); + CalcNormFloat(hidebox[2], hidebox[3], hidebox[5], &plane_normals[2].x); + CalcNormFloat(hidebox[3], hidebox[0], hidebox[4], &plane_normals[3].x); /* Calculate D for each side of hide box */ for(i= 0; i<4; ++i) - plane_ds[i]= hidebox[i].x*plane_normals[i].x + hidebox[i].y*plane_normals[i].y + - hidebox[i].z*plane_normals[i].z; + plane_ds[i]= hidebox[i][0]*plane_normals[i].x + hidebox[i][1]*plane_normals[i].y + + hidebox[i][2]*plane_normals[i].z; /* Add partial visibility to mesh */ if(!me->pv) { diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index bbb5e514942..1855ad3d147 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -888,6 +888,8 @@ static char *transform_to_undostr(TransInfo *t) return "Time Slide"; case TFM_BAKE_TIME: return "Key Time"; + case TFM_MIRROR: + return "Mirror"; } return "Transform"; } @@ -1323,6 +1325,9 @@ void initTransform(int mode, int context) { case TFM_BAKE_TIME: initBakeTime(&Trans); break; + case TFM_MIRROR: + initMirror(&Trans); + break; } } @@ -1359,6 +1364,13 @@ void Transform() } Trans.redraw = 0; } + + /* If auto confirm is on, break after one pass */ + if (Trans.context & CTX_AUTOCONFIRM) + { + Trans.state = TRANS_CONFIRM; + break; + } /* essential for idling subloop */ if( qtest()==0) PIL_sleep_ms(2); @@ -4033,105 +4045,83 @@ int BakeTime(TransInfo *t, short mval[2]) return 1; } - /* ************************** MIRROR *************************** */ -void Mirror(short mode) +void initMirror(TransInfo *t) { - TransData *td; - float mati[3][3], matview[3][3], mat[3][3]; - float size[3]; - int i; - - Trans.context = CTX_NO_PET; - - initTrans(&Trans); // internal data, mouse, vectors - - Mat3One(mati); - Mat3CpyMat4(matview, Trans.viewinv); // t->viewinv was set in initTrans - Mat3Ortho(matview); - - createTransData(&Trans); // make TransData structs from selection - - calculatePropRatio(&Trans); - calculateCenter(&Trans); - - initResize(&Trans); - - if (Trans.total == 0) { - postTrans(&Trans); - return; - } - - size[0] = size[1] = size[2] = 1.0f; - td = Trans.data; - - switch (mode) { - case 1: - size[0] = -1.0f; - setConstraint(&Trans, mati, (CON_AXIS0), ""); - break; - case 2: - size[1] = -1.0f; - setConstraint(&Trans, mati, (CON_AXIS1), ""); - break; - case 3: - size[2] = -1.0f; - setConstraint(&Trans, mati, (CON_AXIS2), ""); - break; - case 4: - size[0] = -1.0f; - setLocalConstraint(&Trans, (CON_AXIS0), ""); - break; - case 5: - size[1] = -1.0f; - setLocalConstraint(&Trans, (CON_AXIS1), ""); - break; - case 6: - size[2] = -1.0f; - setLocalConstraint(&Trans, (CON_AXIS2), ""); - break; - case 7: - size[0] = -1.0f; - setConstraint(&Trans, matview, (CON_AXIS0), ""); - break; - case 8: - size[1] = -1.0f; - setConstraint(&Trans, matview, (CON_AXIS1), ""); - break; - case 9: - size[2] = -1.0f; - setConstraint(&Trans, matview, (CON_AXIS2), ""); - break; - default: - return; + t->flag |= T_NULL_ONE; + if (!G.obedit) { + t->flag |= T_NO_ZERO; } + + t->transform = Mirror; +} - SizeToMat3(size, mat); - - if (Trans.con.applySize) { - Trans.con.applySize(&Trans, NULL, mat); - } +int Mirror(TransInfo *t, short mval[2]) +{ + TransData *td; + float size[3], mat[3][3]; + int i; + char str[200]; - for(i = 0 ; i < Trans.total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + /* + * OPTIMISATION: + * This still recalcs transformation on mouse move + * while it should only recalc on constraint change + * */ - if (td->flag & TD_SKIP) - continue; + /* if an axis has been selected */ + if (t->con.mode & CON_APPLY) { + size[0] = size[1] = size[2] = -1; + + SizeToMat3(size, mat); + + if (t->con.applySize) { + t->con.applySize(t, NULL, mat); + } - ElementResize(&Trans, td, mat); + sprintf(str, "Mirror%s", t->con.text); + + for(i = 0, td=t->data; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + ElementResize(t, td, mat); + } + + recalcData(t); + + headerprint(str); + + viewRedrawForce(t); } - - recalcData(&Trans); + else + { + size[0] = size[1] = size[2] = 1; - BIF_undo_push("Mirror"); - - /* free data, reset vars */ - postTrans(&Trans); + SizeToMat3(size, mat); + + for(i = 0, td=t->data; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + ElementResize(t, td, mat); + } + + recalcData(t); + + headerprint("Select a mirror axis (X, Y, Z)"); + + viewRedrawForce(t); + } - /* send events out for redraws */ - viewRedrawPost(&Trans); + return 1; } /* ************************** ANIM EDITORS - TRANSFORM TOOLS *************************** */ |