diff options
author | Joseph Eagar <joeedh@gmail.com> | 2009-09-16 21:43:09 +0400 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2009-09-16 21:43:09 +0400 |
commit | deebf4f8f0d79169a0e6c2a391670419b6492bfe (patch) | |
tree | 2a0aaf4042aa78e9d1d835f4544e07c6123e67a9 /source/blender/blenkernel/intern | |
parent | 6b0679a3999d8e5abc60730f523879eadbedcd8f (diff) |
merge with 2.5/trunk at r23271
Diffstat (limited to 'source/blender/blenkernel/intern')
49 files changed, 3410 insertions, 2342 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d37a0329582..57af8ce9ae2 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2311,7 +2311,7 @@ static void clear_mesh_caches(Object *ob) static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) { Object *obact = scene->basact?scene->basact->object:NULL; - int editing = paint_facesel_test(ob)|(ob && ob->mode & OB_MODE_PARTICLE_EDIT); + int editing = paint_facesel_test(ob); int needMapping = editing && (ob==obact); float min[3], max[3]; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 47de044ea25..2bde61818bf 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -214,7 +214,7 @@ bAction *copy_action (bAction *src) /* Get the active action-group for an Action */ -bActionGroup *get_active_actiongroup (bAction *act) +static bActionGroup *get_active_actiongroup (bAction *act) { bActionGroup *agrp= NULL; @@ -1165,7 +1165,7 @@ typedef struct NlaIpoChannel { int type; } NlaIpoChannel; -void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime) +static void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime) { bActionChannel *achan= get_action_channel(act, name); IpoCurve *icu; @@ -1258,7 +1258,7 @@ static void blend_ipochannels(ListBase *dst, ListBase *src, float srcweight, int } } -int execute_ipochannels(ListBase *lb) +static int execute_ipochannels(ListBase *lb) { NlaIpoChannel *nic; int count = 0; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 7d9d261f306..63092379825 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -88,15 +88,16 @@ void free_path(Path *path) void calc_curvepath(Object *ob) { BevList *bl; - BevPoint *bevp, *bevpn, *bevpfirst, *bevplast, *tempbevp; + BevPoint *bevp, *bevpn, *bevpfirst, *bevplast; + PathPoint *pp; Curve *cu; Nurb *nu; Path *path; - float *fp, *dist, *maxdist, x, y, z; + float *fp, *dist, *maxdist, xyz[3]; float fac, d=0, fac1, fac2; int a, tot, cycl=0; - float *ft; + /* in a path vertices are with equal differences: path->len = number of verts */ /* NOW WITH BEVELCURVE!!! */ @@ -133,19 +134,12 @@ void calc_curvepath(Object *ob) *fp= 0; for(a=0; a<tot; a++) { fp++; - if(cycl && a==tot-1) { - x= bevpfirst->x - bevp->x; - y= bevpfirst->y - bevp->y; - z= bevpfirst->z - bevp->z; - } - else { - tempbevp = bevp+1; - x= (tempbevp)->x - bevp->x; - y= (tempbevp)->y - bevp->y; - z= (tempbevp)->z - bevp->z; - } - *fp= *(fp-1)+ (float)sqrt(x*x+y*y+z*z); + if(cycl && a==tot-1) + VecSubf(xyz, bevpfirst->vec, bevp->vec); + else + VecSubf(xyz, (bevp+1)->vec, bevp->vec); + *fp= *(fp-1)+VecLength(xyz); bevp++; } @@ -153,7 +147,7 @@ void calc_curvepath(Object *ob) /* the path verts in path->data */ /* now also with TILT value */ - ft= path->data = (float *)MEM_callocN(16*path->len, "pathdata"); + pp= path->data = (PathPoint *)MEM_callocN(sizeof(PathPoint)*4*path->len, "pathdata"); // XXX - why *4? - in 2.4x each element was 4 and the size was 16, so better leave for now - Campbell bevp= bevpfirst; bevpn= bevp+1; @@ -183,13 +177,13 @@ void calc_curvepath(Object *ob) fac1= fac2/fac1; fac2= 1.0f-fac1; - ft[0]= fac1*bevp->x+ fac2*(bevpn)->x; - ft[1]= fac1*bevp->y+ fac2*(bevpn)->y; - ft[2]= fac1*bevp->z+ fac2*(bevpn)->z; - ft[3]= fac1*bevp->alfa+ fac2*(bevpn)->alfa; + VecLerpf(pp->vec, bevp->vec, bevpn->vec, fac2); + pp->vec[3]= fac1*bevp->alfa + fac2*bevpn->alfa; + pp->radius= fac1*bevp->radius + fac2*bevpn->radius; + QuatInterpol(pp->quat, bevp->quat, bevpn->quat, fac2); + NormalQuat(pp->quat); - ft+= 4; - + pp++; } MEM_freeN(dist); @@ -213,13 +207,14 @@ int interval_test(int min, int max, int p1, int cycl) /* warning, *vec needs FOUR items! */ /* ctime is normalized range <0-1> */ -int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK */ +int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius) /* returns OK */ { Curve *cu; Nurb *nu; BevList *bl; Path *path; - float *fp, *p0, *p1, *p2, *p3, fac; + PathPoint *pp, *p0, *p1, *p2, *p3; + float fac; float data[4]; int cycl=0, s0, s1, s2, s3; @@ -230,7 +225,7 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK return 0; } path= cu->path; - fp= path->data; + pp= path->data; /* test for cyclic */ bl= cu->bev.first; @@ -249,19 +244,19 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK s2= interval_test(0, path->len-1-cycl, s1+1, cycl); s3= interval_test(0, path->len-1-cycl, s1+2, cycl); - p0= fp + 4*s0; - p1= fp + 4*s1; - p2= fp + 4*s2; - p3= fp + 4*s3; + p0= pp + s0; + p1= pp + s1; + p2= pp + s2; + p3= pp + s3; /* note, commented out for follow constraint */ //if(cu->flag & CU_FOLLOW) { - set_afgeleide_four_ipo(1.0f-fac, data, KEY_BSPLINE); + key_curve_tangent_weights(1.0f-fac, data, KEY_BSPLINE); - dir[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ; - dir[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ; - dir[2]= data[0]*p0[2] + data[1]*p1[2] + data[2]*p2[2] + data[3]*p3[2] ; + dir[0]= data[0]*p0->vec[0] + data[1]*p1->vec[0] + data[2]*p2->vec[0] + data[3]*p3->vec[0] ; + dir[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ; + dir[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ; /* make compatible with vectoquat */ dir[0]= -dir[0]; @@ -272,16 +267,35 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK nu= cu->nurb.first; /* make sure that first and last frame are included in the vectors here */ - if((nu->type & 7)==CU_POLY) set_four_ipo(1.0f-fac, data, KEY_LINEAR); - else if((nu->type & 7)==CU_BEZIER) set_four_ipo(1.0f-fac, data, KEY_LINEAR); - else if(s0==s1 || p2==p3) set_four_ipo(1.0f-fac, data, KEY_CARDINAL); - else set_four_ipo(1.0f-fac, data, KEY_BSPLINE); - - vec[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ; - vec[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ; - vec[2]= data[0]*p0[2] + data[1]*p1[2] + data[2]*p2[2] + data[3]*p3[2] ; + if(nu->type == CU_POLY) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR); + else if(nu->type == CU_BEZIER) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR); + else if(s0==s1 || p2==p3) key_curve_position_weights(1.0f-fac, data, KEY_CARDINAL); + else key_curve_position_weights(1.0f-fac, data, KEY_BSPLINE); + + vec[0]= data[0]*p0->vec[0] + data[1]*p1->vec[0] + data[2]*p2->vec[0] + data[3]*p3->vec[0] ; /* X */ + vec[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ; /* Y */ + vec[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ; /* Z */ + vec[3]= data[0]*p0->vec[3] + data[1]*p1->vec[3] + data[2]*p2->vec[3] + data[3]*p3->vec[3] ; /* Tilt, should not be needed since we have quat still used */ + /* Need to verify the quat interpolation is correct - XXX */ + + if (quat) { + float totfac, q1[4], q2[4]; + + totfac= data[0]+data[1]; + QuatInterpol(q1, p0->quat, p1->quat, data[0] / totfac); + NormalQuat(q1); + + totfac= data[2]+data[3]; + QuatInterpol(q2, p2->quat, p3->quat, data[2] / totfac); + NormalQuat(q2); + + totfac = data[0]+data[1]+data[2]+data[3]; + QuatInterpol(quat, q1, q2, (data[0]+data[1]) / totfac); + NormalQuat(quat); + } - vec[3]= data[0]*p0[3] + data[1]*p1[3] + data[2]*p2[3] + data[3]*p3[3] ; + if(radius) + *radius= data[0]*p0->radius + data[1]*p1->radius + data[2]*p2->radius + data[3]*p3->radius; return 1; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index df7004d3f6b..643aa6bc779 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -204,6 +204,32 @@ AnimData *BKE_copy_animdata (AnimData *adt) return dadt; } +/* Make Local -------------------------------------------- */ + +static void make_local_strips(ListBase *strips) +{ + NlaStrip *strip; + + for(strip=strips->first; strip; strip=strip->next) { + if(strip->act) make_local_action(strip->act); + if(strip->remap && strip->remap->target) make_local_action(strip->remap->target); + + make_local_strips(&strip->strips); + } +} + +void BKE_animdata_make_local(AnimData *adt) +{ + NlaTrack *nlt; + + if(adt->action) make_local_action(adt->action); + if(adt->tmpact) make_local_action(adt->tmpact); + if(adt->remap && adt->remap->target) make_local_action(adt->remap->target); + + for(nlt=adt->nla_tracks.first; nlt; nlt=nlt->next) + make_local_strips(&nlt->strips); +} + /* *********************************** */ /* KeyingSet API */ @@ -239,7 +265,7 @@ KS_Path *BKE_keyingset_find_destination (KeyingSet *ks, ID *id, const char group if ((ksp->rna_path==0) || strcmp(rna_path, ksp->rna_path)) eq_path= 0; - /* index */ + /* index - need to compare whole-array setting too... */ if (ksp->array_index != array_index) eq_index= 0; @@ -412,7 +438,7 @@ void BKE_keyingsets_free (ListBase *list) * - path: original path string (as stored in F-Curve data) * - dst: destination string to write data to */ -short animsys_remap_path (AnimMapper *remap, char *path, char **dst) +static short animsys_remap_path (AnimMapper *remap, char *path, char **dst) { /* is there a valid remapping table to use? */ //if (remap) { @@ -1424,7 +1450,6 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a * standard 'root') block are overridden by a larger 'user' */ -// FIXME?: we currently go over entire 'main' database... void BKE_animsys_evaluate_all_animation (Main *main, float ctime) { ID *id; @@ -1448,8 +1473,11 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) * when there are no actions, don't go over database and loop over heaps of datablocks, * which should ultimately be empty, since it is not possible for now to have any animation * without some actions, and drivers wouldn't get affected by any state changes + * + * however, if there are some curves, we will need to make sure that their 'ctime' property gets + * set correctly, so this optimisation must be skipped in that case... */ - if (main->action.first == NULL) { + if ((main->action.first == NULL) && (main->curve.first == NULL)) { if (G.f & G_DEBUG) printf("\tNo Actions, so no animation needs to be evaluated...\n"); @@ -1483,6 +1511,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) * value of the curve gets set in case there's no animation for that * - it needs to be set before animation is evaluated just so that * animation can successfully override... + * - it shouldn't get set when calculating drivers... */ for (id= main->curve.first; id; id= id->next) { AnimData *adt= BKE_animdata_from_id(id); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 31ae4d6cbec..5f74edb97d4 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -131,7 +131,6 @@ void free_bones (bArmature *arm) void free_armature(bArmature *arm) { if (arm) { - /* unlink_armature(arm);*/ free_bones(arm); /* free editmode data */ @@ -668,10 +667,10 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) if(bone->segments > MAX_BBONE_SUBDIV) bone->segments= MAX_BBONE_SUBDIV; - forward_diff_bezier(0.0, h1[0], h2[0], 0.0, data[0], MAX_BBONE_SUBDIV, 4); - forward_diff_bezier(0.0, h1[1], length + h2[1], length, data[0]+1, MAX_BBONE_SUBDIV, 4); - forward_diff_bezier(0.0, h1[2], h2[2], 0.0, data[0]+2, MAX_BBONE_SUBDIV, 4); - forward_diff_bezier(roll1, roll1 + 0.390464f*(roll2-roll1), roll2 - 0.390464f*(roll2-roll1), roll2, data[0]+3, MAX_BBONE_SUBDIV, 4); + forward_diff_bezier(0.0, h1[0], h2[0], 0.0, data[0], MAX_BBONE_SUBDIV, 4*sizeof(float)); + forward_diff_bezier(0.0, h1[1], length + h2[1], length, data[0]+1, MAX_BBONE_SUBDIV, 4*sizeof(float)); + forward_diff_bezier(0.0, h1[2], h2[2], 0.0, data[0]+2, MAX_BBONE_SUBDIV, 4*sizeof(float)); + forward_diff_bezier(roll1, roll1 + 0.390464f*(roll2-roll1), roll2 - 0.390464f*(roll2-roll1), roll2, data[0]+3, MAX_BBONE_SUBDIV, 4*sizeof(float)); equalize_bezier(data[0], bone->segments); // note: does stride 4! @@ -1988,10 +1987,14 @@ void chan_calc_mat(bPoseChannel *chan) /* get scaling matrix */ SizeToMat3(chan->size, smat); - /* rotations may either be quats or eulers (no rotation modes for now...) */ - if (chan->rotmode) { - /* euler rotations (will cause gimble lock... no rotation order to solve that yet) */ - EulToMat3(chan->eul, rmat); + /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */ + if (chan->rotmode > 0) { + /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ + EulOToMat3(chan->eul, chan->rotmode, rmat); + } + else if (chan->rotmode == PCHAN_ROT_AXISANGLE) { + /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ + AxisAngleToMat3(&chan->quat[1], chan->quat[0], rmat); } else { /* quats are normalised before use to eliminate scaling issues */ diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 5c62e434cb6..18f065b59d9 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -74,6 +74,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, BoidSettings *boids = bbd->part->boids; ParticleEffectorCache *ec; Object *priority_ob = NULL; + BoidParticle *bpa = pa->boid; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0); float priority = 0.0f, len = 0.0f; @@ -81,7 +82,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, /* first find out goal/predator with highest priority */ /* if rule->ob specified use it */ - if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != pa->stick_ob)) { + if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) { PartDeflect *pd = gabr->ob->pd; float vec_to_part[3]; @@ -104,7 +105,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, PartDeflect *pd = eob->pd; /* skip current object */ - if(rule->type == eBoidRuleType_Goal && eob == pa->stick_ob) + if(rule->type == eBoidRuleType_Goal && eob == bpa->ground) continue; if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f) { @@ -169,10 +170,10 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, VECCOPY(bbd->goal_nor, nor); } } - else if(rule->type == eBoidRuleType_Avoid && pa->boid->mode == eBoidMode_Climbing && + else if(rule->type == eBoidRuleType_Avoid && bpa->data.mode == eBoidMode_Climbing && priority > 2.0f * gabr->fear_factor) { /* detach from surface and try to fly away from danger */ - VECCOPY(vec_to_part, pa->r_ve); + VECCOPY(vec_to_part, bpa->gravity); VecMulf(vec_to_part, -1.0f); } @@ -205,6 +206,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * KDTreeNearest *ptn = NULL; ParticleEffectorCache *ec; ParticleTarget *pt; + BoidParticle *bpa = pa->boid; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; float co1[3], vel1[3], co2[3], vel2[3]; float len, t, inp, t_min = 2.0f; @@ -231,7 +233,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * Object *eob = ec->ob; /* don't check with current ground object */ - if(eob == pa->stick_ob) + if(eob == bpa->ground) continue; col.md = ( CollisionModifierData * ) ( modifiers_findByType ( eob, eModifierType_Collision ) ); @@ -558,18 +560,19 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va } static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa) { + BoidParticle *bpa = pa->boid; BoidRuleAverageSpeed *asbr = (BoidRuleAverageSpeed*)rule; float vec[3] = {0.0f, 0.0f, 0.0f}; if(asbr->wander > 0.0f) { /* abuse pa->r_ave for wandering */ - pa->r_ave[0] += asbr->wander * (-1.0f + 2.0f * BLI_frand()); - pa->r_ave[1] += asbr->wander * (-1.0f + 2.0f * BLI_frand()); - pa->r_ave[2] += asbr->wander * (-1.0f + 2.0f * BLI_frand()); + bpa->wander[0] += asbr->wander * (-1.0f + 2.0f * BLI_frand()); + bpa->wander[1] += asbr->wander * (-1.0f + 2.0f * BLI_frand()); + bpa->wander[2] += asbr->wander * (-1.0f + 2.0f * BLI_frand()); - Normalize(pa->r_ave); + Normalize(bpa->wander); - VECCOPY(vec, pa->r_ave); + VECCOPY(vec, bpa->wander); QuatMulVecf(pa->prev_state.rot, vec); @@ -615,6 +618,7 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti ParticleTarget *pt; ParticleData *epars; ParticleData *enemy_pa = NULL; + BoidParticle *bpa; /* friends & enemies */ float closest_enemy[3] = {0.0f,0.0f,0.0f}; float closest_dist = fbr->distance + 1.0f; @@ -624,8 +628,10 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti /* calculate own group strength */ int neighbors = BLI_kdtree_range_search(bbd->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); - for(n=0; n<neighbors; n++) - health += bbd->psys->particles[ptn[n].index].boid->health; + for(n=0; n<neighbors; n++) { + bpa = bbd->psys->particles[ptn[n].index].boid; + health += bpa->data.health; + } f_strength += bbd->part->boids->strength * health; @@ -642,7 +648,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti health = 0.0f; for(n=0; n<neighbors; n++) { - health += epars[ptn[n].index].boid->health; + bpa = epars[ptn[n].index].boid; + health += bpa->data.health; if(n==0 && pt->mode==PTARGET_MODE_ENEMY && ptn[n].dist < closest_dist) { VECCOPY(closest_enemy, ptn[n].co); @@ -674,7 +681,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti /* must face enemy to fight */ if(Inpf(pa->prev_state.ave, enemy_dir)>0.5f) { - enemy_pa->boid->health -= bbd->part->boids->strength * bbd->timestep * ((1.0f-bbd->part->boids->accuracy)*damage + bbd->part->boids->accuracy); + bpa = enemy_pa->boid; + bpa->data.health -= bbd->part->boids->strength * bbd->timestep * ((1.0f-bbd->part->boids->accuracy)*damage + bbd->part->boids->accuracy); } } else { @@ -683,7 +691,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti } /* check if boid doesn't want to fight */ - if(pa->boid->health/bbd->part->boids->health * bbd->part->boids->aggression < e_strength / f_strength) { + bpa = pa->boid; + if(bpa->data.health/bbd->part->boids->health * bbd->part->boids->aggression < e_strength / f_strength) { /* decide to flee */ if(closest_dist < fbr->flee_distance * fbr->distance) { VecMulf(bbd->wanted_co, -1.0f); @@ -721,18 +730,20 @@ static boid_rule_cb boid_rules[] = { static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *pa) { - if(ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing)) { - val->max_speed = boids->land_max_speed * pa->boid->health/boids->health; + BoidParticle *bpa = pa->boid; + + if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) { + val->max_speed = boids->land_max_speed * bpa->data.health/boids->health; val->max_acc = boids->land_max_acc * val->max_speed; - val->max_ave = boids->land_max_ave * M_PI * pa->boid->health/boids->health; + val->max_ave = boids->land_max_ave * M_PI * bpa->data.health/boids->health; val->min_speed = 0.0f; /* no minimum speed on land */ val->personal_space = boids->land_personal_space; - val->jump_speed = boids->land_jump_speed * pa->boid->health/boids->health; + val->jump_speed = boids->land_jump_speed * bpa->data.health/boids->health; } else { - val->max_speed = boids->air_max_speed * pa->boid->health/boids->health; + val->max_speed = boids->air_max_speed * bpa->data.health/boids->health; val->max_acc = boids->air_max_acc * val->max_speed; - val->max_ave = boids->air_max_ave * M_PI * pa->boid->health/boids->health; + val->max_ave = boids->air_max_ave * M_PI * bpa->data.health/boids->health; val->min_speed = boids->air_min_speed * boids->air_max_speed; val->personal_space = boids->air_personal_space; val->jump_speed = 0.0f; /* no jumping in air */ @@ -740,11 +751,13 @@ static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData * } static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *ground_co, float *ground_nor) { - if(pa->boid->mode == eBoidMode_Climbing) { + BoidParticle *bpa = pa->boid; + + if(bpa->data.mode == eBoidMode_Climbing) { SurfaceModifierData *surmd = NULL; float x[3], v[3]; - surmd = (SurfaceModifierData *)modifiers_findByType ( pa->stick_ob, eModifierType_Surface ); + surmd = (SurfaceModifierData *)modifiers_findByType ( bpa->ground, eModifierType_Surface ); /* take surface velocity into account */ effector_find_co(bbd->scene, pa->state.co, surmd, NULL, NULL, x, NULL, v, NULL); @@ -753,7 +766,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro /* get actual position on surface */ effector_find_co(bbd->scene, x, surmd, NULL, NULL, ground_co, ground_nor, NULL, NULL); - return pa->stick_ob; + return bpa->ground; } else { float zvec[3] = {0.0f, 0.0f, 2000.0f}; @@ -803,13 +816,15 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro } static int boid_rule_applies(ParticleData *pa, BoidSettings *boids, BoidRule *rule) { + BoidParticle *bpa = pa->boid; + if(rule==NULL) return 0; - if(ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing) && rule->flag & BOIDRULE_ON_LAND) + if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing) && rule->flag & BOIDRULE_ON_LAND) return 1; - if(pa->boid->mode==eBoidMode_InAir && rule->flag & BOIDRULE_IN_AIR) + if(bpa->data.mode==eBoidMode_InAir && rule->flag & BOIDRULE_IN_AIR) return 1; return 0; @@ -835,12 +850,13 @@ void boids_precalc_rules(ParticleSettings *part, float cfra) } static void boid_climb(BoidSettings *boids, ParticleData *pa, float *surface_co, float *surface_nor) { + BoidParticle *bpa = pa->boid; float nor[3], vel[3]; VECCOPY(nor, surface_nor); - /* gather apparent gravity to r_ve */ - VECADDFAC(pa->r_ve, pa->r_ve, surface_nor, -1.0); - Normalize(pa->r_ve); + /* gather apparent gravity */ + VECADDFAC(bpa->gravity, bpa->gravity, surface_nor, -1.0); + Normalize(bpa->gravity); /* raise boid it's size from surface */ VecMulf(nor, pa->size * boids->height); @@ -877,16 +893,17 @@ static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, } static BoidState *get_boid_state(BoidSettings *boids, ParticleData *pa) { BoidState *state = boids->states.first; + BoidParticle *bpa = pa->boid; for(; state; state=state->next) { - if(state->id==pa->boid->state_id) + if(state->id==bpa->data.state_id) return state; } /* for some reason particle isn't at a valid state */ state = boids->states.first; if(state) - pa->boid->state_id = state->id; + bpa->data.state_id = state->id; return state; } @@ -902,9 +919,11 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) BoidSettings *boids = bbd->part->boids; BoidValues val; BoidState *state = get_boid_state(boids, pa); + BoidParticle *bpa = pa->boid; + int rand; //BoidCondition *cond; - if(pa->boid->health <= 0.0f) { + if(bpa->data.health <= 0.0f) { pa->alive = PARS_DYING; return; } @@ -922,7 +941,9 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) bbd->wanted_co[0]=bbd->wanted_co[1]=bbd->wanted_co[2]=bbd->wanted_speed=0.0f; /* create random seed for every particle & frame */ - BLI_srandom(bbd->psys->seed + p + (int)bbd->cfra + (int)(1000*pa->r_rot[0])); + BLI_srandom(bbd->psys->seed + p); + rand = BLI_rand(); + BLI_srandom((int)bbd->cfra + rand); set_boid_values(&val, bbd->part->boids, pa); @@ -939,7 +960,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) case eBoidRulesetType_Random: { /* use random rule for each particle (allways same for same particle though) */ - rule = BLI_findlink(&state->rules, (int)(1000.0f * pa->r_rot[1]) % BLI_countlist(&state->rules)); + rule = BLI_findlink(&state->rules, rand % BLI_countlist(&state->rules)); apply_boid_rule(bbd, rule, &val, pa, -1.0); } @@ -969,7 +990,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) } /* decide on jumping & liftoff */ - if(pa->boid->mode == eBoidMode_OnLand) { + if(bpa->data.mode == eBoidMode_OnLand) { /* fuzziness makes boids capable of misjudgement */ float mul = 1.0 + state->rule_fuzziness; @@ -983,7 +1004,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) Normalize2(cvel); if(Inp2f(cvel, dir) > 0.95 / mul) - pa->boid->mode = eBoidMode_Liftoff; + bpa->data.mode = eBoidMode_Liftoff; } else if(val.jump_speed > 0.0f) { float jump_v[3]; @@ -1036,7 +1057,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) if(jump) { VECCOPY(pa->prev_state.vel, jump_v); - pa->boid->mode = eBoidMode_Falling; + bpa->data.mode = eBoidMode_Falling; } } } @@ -1045,6 +1066,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) void boid_body(BoidBrainData *bbd, ParticleData *pa) { BoidSettings *boids = bbd->part->boids; + BoidParticle *bpa = pa->boid; BoidValues val; float acc[3] = {0.0f, 0.0f, 0.0f}, tan_acc[3], nor_acc[3]; float dvec[3], bvec[3]; @@ -1066,10 +1088,10 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) pa_mass*=pa->size; /* if boids can't fly they fall to the ground */ - if((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && bbd->part->acc[2] != 0.0f) - pa->boid->mode = eBoidMode_Falling; + if((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && bbd->part->acc[2] != 0.0f) + bpa->data.mode = eBoidMode_Falling; - if(pa->boid->mode == eBoidMode_Falling) { + if(bpa->data.mode == eBoidMode_Falling) { /* Falling boids are only effected by gravity. */ acc[2] = bbd->part->acc[2]; } @@ -1079,14 +1101,14 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) float level = landing_level + 1.0f; float new_vel[3]; - if(pa->boid->mode == eBoidMode_Liftoff) { - pa->boid->mode = eBoidMode_InAir; - pa->stick_ob = boid_find_ground(bbd, pa, ground_co, ground_nor); + if(bpa->data.mode == eBoidMode_Liftoff) { + bpa->data.mode = eBoidMode_InAir; + bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); } - else if(pa->boid->mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) { + else if(bpa->data.mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) { /* auto-leveling & landing if close to ground */ - pa->stick_ob = boid_find_ground(bbd, pa, ground_co, ground_nor); + bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); /* level = how many particle sizes above ground */ level = (pa->prev_state.co[2] - ground_co[2])/(2.0f * pa->size) - 0.5; @@ -1097,7 +1119,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) if(level < 1.0f) { bbd->wanted_co[0] = bbd->wanted_co[1] = bbd->wanted_co[2] = 0.0f; bbd->wanted_speed = 0.0f; - pa->boid->mode = eBoidMode_Falling; + bpa->data.mode = eBoidMode_Falling; } else if(level < landing_level) { bbd->wanted_speed *= (level - 1.0f)/landing_level; @@ -1188,7 +1210,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) /* account for effectors */ do_effectors(p, pa, &pa->state, bbd->scene, bbd->ob, bbd->psys, pa->state.co, force, tvel, bbd->dfra, bbd->cfra); - if(ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing)) { + if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) { float length = Normalize(force); length = MAX2(0.0f, length - boids->land_stick_force); @@ -1199,8 +1221,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) VecAddf(acc, acc, force); /* store smoothed acceleration for nice banking etc. */ - VECADDFAC(pa->boid->acc, pa->boid->acc, acc, dtime); - VecMulf(pa->boid->acc, 1.0f / (1.0f + dtime)); + VECADDFAC(bpa->data.acc, bpa->data.acc, acc, dtime); + VecMulf(bpa->data.acc, 1.0f / (1.0f + dtime)); /* integrate new location & velocity */ @@ -1218,32 +1240,32 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) VECADDFAC(pa->state.vel, pa->state.vel, acc, dtime); - if(pa->boid->mode != eBoidMode_InAir) - pa->stick_ob = boid_find_ground(bbd, pa, ground_co, ground_nor); + if(bpa->data.mode != eBoidMode_InAir) + bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); /* change modes, constrain movement & keep track of down vector */ - switch(pa->boid->mode) { + switch(bpa->data.mode) { case eBoidMode_InAir: { float grav[3] = {0.0f, 0.0f, bbd->part->acc[2] < 0.0f ? -1.0f : 0.0f}; /* don't take forward acceleration into account (better banking) */ - if(Inpf(pa->boid->acc, pa->state.vel) > 0.0f) { - Projf(dvec, pa->boid->acc, pa->state.vel); - VecSubf(dvec, pa->boid->acc, dvec); + if(Inpf(bpa->data.acc, pa->state.vel) > 0.0f) { + Projf(dvec, bpa->data.acc, pa->state.vel); + VecSubf(dvec, bpa->data.acc, dvec); } else { - VECCOPY(dvec, pa->boid->acc); + VECCOPY(dvec, bpa->data.acc); } - /* gather apparent gravity to r_ve */ - VECADDFAC(pa->r_ve, grav, dvec, -boids->banking); - Normalize(pa->r_ve); + /* gather apparent gravity */ + VECADDFAC(bpa->gravity, grav, dvec, -boids->banking); + Normalize(bpa->gravity); /* stick boid on goal when close enough */ if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) { - pa->boid->mode = eBoidMode_Climbing; - pa->stick_ob = bbd->goal_ob; + bpa->data.mode = eBoidMode_Climbing; + bpa->ground = bbd->goal_ob; boid_find_ground(bbd, pa, ground_co, ground_nor); boid_climb(boids, pa, ground_co, ground_nor); } @@ -1251,7 +1273,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) else if(boids->options & BOID_ALLOW_LAND && pa->state.co[2] <= ground_co[2] + pa->size * boids->height) { pa->state.co[2] = ground_co[2] + pa->size * boids->height; pa->state.vel[2] = 0.0f; - pa->boid->mode = eBoidMode_OnLand; + bpa->data.mode = eBoidMode_OnLand; } break; } @@ -1259,15 +1281,15 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) { float grav[3] = {0.0f, 0.0f, bbd->part->acc[2] < 0.0f ? -1.0f : 0.0f}; - /* gather apparent gravity to r_ve */ - VECADDFAC(pa->r_ve, pa->r_ve, grav, dtime); - Normalize(pa->r_ve); + /* gather apparent gravity */ + VECADDFAC(bpa->gravity, bpa->gravity, grav, dtime); + Normalize(bpa->gravity); if(boids->options & BOID_ALLOW_LAND) { /* stick boid on goal when close enough */ if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) { - pa->boid->mode = eBoidMode_Climbing; - pa->stick_ob = bbd->goal_ob; + bpa->data.mode = eBoidMode_Climbing; + bpa->ground = bbd->goal_ob; boid_find_ground(bbd, pa, ground_co, ground_nor); boid_climb(boids, pa, ground_co, ground_nor); } @@ -1275,14 +1297,14 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) else if(pa->state.co[2] <= ground_co[2] + 1.01 * pa->size * boids->height){ pa->state.co[2] = ground_co[2] + pa->size * boids->height; pa->state.vel[2] = 0.0f; - pa->boid->mode = eBoidMode_OnLand; + bpa->data.mode = eBoidMode_OnLand; } /* if we're falling, can fly and want to go upwards lets fly */ else if(boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f) - pa->boid->mode = eBoidMode_InAir; + bpa->data.mode = eBoidMode_InAir; } else - pa->boid->mode = eBoidMode_InAir; + bpa->data.mode = eBoidMode_InAir; break; } case eBoidMode_Climbing: @@ -1308,14 +1330,14 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) { /* stick boid on goal when close enough */ if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) { - pa->boid->mode = eBoidMode_Climbing; - pa->stick_ob = bbd->goal_ob; + bpa->data.mode = eBoidMode_Climbing; + bpa->ground = bbd->goal_ob; boid_find_ground(bbd, pa, ground_co, ground_nor); boid_climb(boids, pa, ground_co, ground_nor); } /* ground is too far away so boid falls */ else if(pa->state.co[2]-ground_co[2] > 1.1 * pa->size * boids->height) - pa->boid->mode = eBoidMode_Falling; + bpa->data.mode = eBoidMode_Falling; else { /* constrain to surface */ pa->state.co[2] = ground_co[2] + pa->size * boids->height; @@ -1329,17 +1351,17 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) VECCOPY(grav, ground_nor); VecMulf(grav, -1.0f); - Projf(dvec, pa->boid->acc, pa->state.vel); - VecSubf(dvec, pa->boid->acc, dvec); + Projf(dvec, bpa->data.acc, pa->state.vel); + VecSubf(dvec, bpa->data.acc, dvec); - /* gather apparent gravity to r_ve */ - VECADDFAC(pa->r_ve, grav, dvec, -boids->banking); - Normalize(pa->r_ve); + /* gather apparent gravity */ + VECADDFAC(bpa->gravity, grav, dvec, -boids->banking); + Normalize(bpa->gravity); } else { - /* gather negative surface normal to r_ve */ - VECADDFAC(pa->r_ve, pa->r_ve, ground_nor, -1.0f); - Normalize(pa->r_ve); + /* gather negative surface normal */ + VECADDFAC(bpa->gravity, bpa->gravity, ground_nor, -1.0f); + Normalize(bpa->gravity); } break; } @@ -1347,29 +1369,29 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) /* save direction to state.ave unless the boid is falling */ /* (boids can't effect their direction when falling) */ - if(pa->boid->mode!=eBoidMode_Falling && VecLength(pa->state.vel) > 0.1*pa->size) { + if(bpa->data.mode!=eBoidMode_Falling && VecLength(pa->state.vel) > 0.1*pa->size) { VECCOPY(pa->state.ave, pa->state.vel); Normalize(pa->state.ave); } /* apply damping */ - if(ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing)) + if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) VecMulf(pa->state.vel, 1.0f - 0.2f*bbd->part->dampfac); /* calculate rotation matrix based on forward & down vectors */ - if(pa->boid->mode == eBoidMode_InAir) { + if(bpa->data.mode == eBoidMode_InAir) { VECCOPY(mat[0], pa->state.ave); - Projf(dvec, pa->r_ve, pa->state.ave); - VecSubf(mat[2], pa->r_ve, dvec); + Projf(dvec, bpa->gravity, pa->state.ave); + VecSubf(mat[2], bpa->gravity, dvec); Normalize(mat[2]); } else { - Projf(dvec, pa->state.ave, pa->r_ve); + Projf(dvec, pa->state.ave, bpa->gravity); VecSubf(mat[0], pa->state.ave, dvec); Normalize(mat[0]); - VECCOPY(mat[2], pa->r_ve); + VECCOPY(mat[2], bpa->gravity); } VecMulf(mat[2], -1.0f); Crossf(mat[1], mat[2], mat[0]); diff --git a/source/blender/blenkernel/intern/booleanops.c b/source/blender/blenkernel/intern/booleanops.c index b6d1f7612b0..76355045186 100644 --- a/source/blender/blenkernel/intern/booleanops.c +++ b/source/blender/blenkernel/intern/booleanops.c @@ -591,7 +591,7 @@ int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type) MEM_freeN(mat); /* update dag */ - DAG_object_flush_update(scene, ob_new, OB_RECALC_DATA); + DAG_id_flush_update(&ob_new->id, OB_RECALC_DATA); return 1; } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index bce4e1120be..76a26762abe 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -711,7 +711,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i } } -void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos) +static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos) { Brush *brush= painter->brush; BrushPainterCache *cache= &painter->cache; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 2d330748772..bd737ccdc3f 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -96,7 +96,7 @@ static CM_SOLVER_DEF solvers [] = static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); +static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ); @@ -156,7 +156,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->goalfrict = 0.0f; } -BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) +static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; @@ -197,7 +197,7 @@ BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) return bvhtree; } -BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) +static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; @@ -348,7 +348,7 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) BKE_ptcache_id_from_cloth(&pid, ob, clmd); // don't do anything as long as we're in editmode! - if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) + if(pid.cache->edit && ob->mode & OB_MODE_PARTICLE_EDIT) return; BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr); @@ -497,23 +497,32 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, if(!do_init_cloth(ob, clmd, result, framenr)) return result; + if(framenr == startframe) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + do_init_cloth(ob, clmd, result, framenr); + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->flag &= ~PTCACHE_REDO_NEEDED; + return result; + } + /* try to read from cache */ cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= framenr; - implicit_set_positions(clmd); cloth_to_object (ob, clmd, result); + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; + + if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) + BKE_ptcache_write_cache(&pid, framenr); + return result; } else if(cache_result==PTCACHE_READ_OLD) { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); - implicit_set_positions(clmd); - cache->flag |= PTCACHE_SIMULATION_VALID; } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { @@ -524,38 +533,25 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, return result; } - if(framenr == startframe) { - if(cache->flag & PTCACHE_REDO_NEEDED) { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - do_init_cloth(ob, clmd, result, framenr); - } - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= framenr; - - /* don't write cache on first frame, but on second frame write - * cache for frame 1 and 2 */ - } - else { - /* if on second frame, write cache for first frame */ - if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write_cache(&pid, startframe); - - clmd->sim_parms->timescale *= framenr - cache->simframe; + /* if on second frame, write cache for first frame */ + if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) + BKE_ptcache_write_cache(&pid, startframe); - /* do simulation */ - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= framenr; + clmd->sim_parms->timescale *= framenr - cache->simframe; - if(!do_step_cloth(ob, clmd, result, framenr)) { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; - } - else - BKE_ptcache_write_cache(&pid, framenr); + /* do simulation */ + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; - cloth_to_object (ob, clmd, result); + if(!do_step_cloth(ob, clmd, result, framenr)) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + cache->last_exact= 0; } + else + BKE_ptcache_write_cache(&pid, framenr); + + cloth_to_object (ob, clmd, result); return result; } @@ -1003,7 +999,7 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in return 0; } -void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist) +static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist) { unsigned int i = 0; @@ -1036,7 +1032,7 @@ void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgeli BLI_edgehash_free ( cloth->edgehash, NULL ); } -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) +static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) { Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 37e9c93a108..8ef1c285370 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -313,7 +313,7 @@ gsl_poly_solve_quadratic (double a, double b, double c, * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" * page 4, left column */ -int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) +static int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) { int num_sols = 0; @@ -427,7 +427,7 @@ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3 // w3 is not perfect -void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) +static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -726,7 +726,7 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap return collpair; } -int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +static int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; Cloth *cloth1; @@ -891,7 +891,7 @@ static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, floa } // calculates the distance of 2 edges -float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) +static float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) { float line1[3], line2[3], cross[3]; float length; @@ -1065,7 +1065,7 @@ float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3 return 0; } -int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) +static int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; Cloth *cloth1=NULL; @@ -1275,7 +1275,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat return result; } -int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +static int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { Cloth *cloth1; cloth1 = clmd->clothObject; @@ -1392,7 +1392,7 @@ CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *nu return objs; } -void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap) +static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap) { int i; @@ -1405,7 +1405,7 @@ void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModi } } -int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) +static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) { Cloth *cloth = clmd->clothObject; int i=0, j = 0, numfaces = 0, numverts = 0; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 26f9245abc7..8cd64ae2ece 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -502,8 +502,8 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) for(a=0; a<cuma->totpoint-1; a++, fp += 2*CM_RESOL) { correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a+1].vec[0], bezt[a+1].vec[1]); - forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a+1].vec[0][0], bezt[a+1].vec[1][0], fp, CM_RESOL-1, 2); - forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2); + forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a+1].vec[0][0], bezt[a+1].vec[1][0], fp, CM_RESOL-1, 2*sizeof(float)); + forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2*sizeof(float)); } /* store first and last handle for extrapolation, unit length */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index a9611039dab..ad474fb7910 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -123,6 +123,7 @@ bConstraintOb *constraints_make_evalob (Scene *scene, Object *ob, void *subdata, if (ob) { cob->ob = ob; cob->type = datatype; + cob->rotOrder = EULER_ORDER_DEFAULT; // TODO: when objects have rotation order too, use that Mat4CpyMat4(cob->matrix, ob->obmat); } else @@ -139,6 +140,15 @@ bConstraintOb *constraints_make_evalob (Scene *scene, Object *ob, void *subdata, cob->pchan = (bPoseChannel *)subdata; cob->type = datatype; + if (cob->pchan->rotmode > 0) { + /* should be some type of Euler order */ + cob->rotOrder= cob->pchan->rotmode; + } + else { + /* Quats, so eulers should just use default order */ + cob->rotOrder= EULER_ORDER_DEFAULT; + } + /* matrix in world-space */ Mat4MulMat4(cob->matrix, cob->pchan->pose_mat, ob->obmat); } @@ -666,6 +676,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ +// TODO: cope with getting rotation order... #define SINGLETARGET_GET_TARS(con, datatar, datasubtarget, ct, list) \ { \ ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \ @@ -689,6 +700,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ +// TODO: cope with getting rotation order... #define SINGLETARGETNS_GET_TARS(con, datatar, ct, list) \ { \ ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \ @@ -797,11 +809,11 @@ static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta /* extract components of both matrices */ VECCOPY(loc, ct->matrix[3]); - Mat4ToEul(ct->matrix, eul); + Mat4ToEulO(ct->matrix, eul, ct->rotOrder); Mat4ToSize(ct->matrix, size); VECCOPY(loco, invmat[3]); - Mat4ToEul(invmat, eulo); + Mat4ToEulO(invmat, eulo, cob->rotOrder); Mat4ToSize(invmat, sizo); /* disable channels not enabled */ @@ -816,8 +828,8 @@ static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f; /* make new target mat and offset mat */ - LocEulSizeToMat4(ct->matrix, loc, eul, size); - LocEulSizeToMat4(invmat, loco, eulo, sizo); + LocEulOSizeToMat4(ct->matrix, loc, eul, size, ct->rotOrder); + LocEulOSizeToMat4(invmat, loco, eulo, sizo, cob->rotOrder); /* multiply target (parent matrix) by offset (parent inverse) to get * the effect of the parent that will be exherted on the owner @@ -1152,7 +1164,7 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr if (VALID_CONS_TARGET(ct)) { Curve *cu= ct->tar->data; - float q[4], vec[4], dir[3], quat[4], x1; + float q[4], vec[4], dir[3], quat[4], radius, x1; float totmat[4][4]; float curvetime; @@ -1164,21 +1176,30 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr */ /* only happens on reload file, but violates depsgraph still... fix! */ - if (cu->path==NULL || cu->path->data==NULL) + if (cu->path==NULL || cu->path->data==NULL) makeDispListCurveTypes(cob->scene, ct->tar, 0); if (cu->path && cu->path->data) { - curvetime= bsystem_time(cob->scene, ct->tar, (float)ctime, 0.0) - data->offset; - -#if 0 // XXX old animation system - if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) { - curvetime /= cu->pathlen; + if ((data->followflag & FOLLOWPATH_STATIC) == 0) { + /* animated position along curve depending on time */ + curvetime= bsystem_time(cob->scene, ct->tar, ctime, 0.0) - data->offset; + + /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated, + * but this will only work if it actually is animated... + * + * we firstly calculate the modulus of cu->ctime/cu->pathlen to clamp ctime within the 0.0 to 1.0 times pathlen + * range, then divide this (the modulus) by pathlen to get a value between 0.0 and 1.0 + */ + curvetime= fmod(cu->ctime, cu->pathlen) / cu->pathlen; CLAMP(curvetime, 0.0, 1.0); } -#endif // XXX old animation system + else { + /* fixed position along curve */ + curvetime= data->offset; // XXX might need a more sensible value + } - if ( where_on_path(ct->tar, curvetime, vec, dir) ) { - if (data->followflag) { + if ( where_on_path(ct->tar, curvetime, vec, dir, NULL, &radius) ) { + if (data->followflag & FOLLOWPATH_FOLLOW) { vectoquat(dir, (short) data->trackflag, (short) data->upflag, quat); Normalize(dir); @@ -1191,6 +1212,14 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr QuatToMat4(quat, totmat); } + + if (data->followflag & FOLLOWPATH_RADIUS) { + float tmat[4][4], rmat[4][4]; + Mat4Scale(tmat, radius); + Mat4MulMat4(rmat, totmat, tmat); + Mat4CpyMat4(totmat, rmat); + } + VECCOPY(totmat[3], vec); Mat4MulSerie(ct->matrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL); @@ -1208,7 +1237,8 @@ static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase /* only evaluate if there is a target */ if (VALID_CONS_TARGET(ct)) { float obmat[4][4]; - float size[3], obsize[3]; + float size[3]; + bFollowPathConstraint *data= con->data; /* get Object local transform (loc/rot/size) to determine transformation from path */ //object_to_mat4(ob, obmat); @@ -1221,13 +1251,17 @@ static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase Mat4MulSerie(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL); /* un-apply scaling caused by path */ - Mat4ToSize(cob->matrix, obsize); - if (obsize[0]) - VecMulf(cob->matrix[0], size[0] / obsize[0]); - if (obsize[1]) - VecMulf(cob->matrix[1], size[1] / obsize[1]); - if (obsize[2]) - VecMulf(cob->matrix[2], size[2] / obsize[2]); + if ((data->followflag & FOLLOWPATH_RADIUS)==0) { /* XXX - assume that scale correction means that radius will have some scale error in it - Campbell */ + float obsize[3]; + + Mat4ToSize(cob->matrix, obsize); + if (obsize[0]) + VecMulf(cob->matrix[0], size[0] / obsize[0]); + if (obsize[1]) + VecMulf(cob->matrix[1], size[1] / obsize[1]); + if (obsize[2]) + VecMulf(cob->matrix[2], size[2] / obsize[2]); + } } } @@ -1306,7 +1340,7 @@ static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t VECCOPY(loc, cob->matrix[3]); Mat4ToSize(cob->matrix, size); - Mat4ToEul(cob->matrix, eul); + Mat4ToEulO(cob->matrix, eul, cob->rotOrder); /* eulers: radians to degrees! */ eul[0] = (float)(eul[0] / M_PI * 180); @@ -1341,7 +1375,7 @@ static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *t eul[1] = (float)(eul[1] / 180 * M_PI); eul[2] = (float)(eul[2] / 180 * M_PI); - LocEulSizeToMat4(cob->matrix, loc, eul, size); + LocEulOSizeToMat4(cob->matrix, loc, eul, size, cob->rotOrder); } static bConstraintTypeInfo CTI_ROTLIMIT = { @@ -1548,14 +1582,14 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta VECCOPY(loc, cob->matrix[3]); Mat4ToSize(cob->matrix, size); - Mat4ToEul(ct->matrix, eul); - Mat4ToEul(cob->matrix, obeul); + Mat4ToEulO(ct->matrix, eul, ct->rotOrder); + Mat4ToEulO(cob->matrix, obeul, cob->rotOrder); if ((data->flag & ROTLIKE_X)==0) eul[0] = obeul[0]; else { if (data->flag & ROTLIKE_OFFSET) - euler_rot(eul, obeul[0], 'x'); + eulerO_rot(eul, obeul[0], 'x', cob->rotOrder); if (data->flag & ROTLIKE_X_INVERT) eul[0] *= -1; @@ -1565,7 +1599,7 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta eul[1] = obeul[1]; else { if (data->flag & ROTLIKE_OFFSET) - euler_rot(eul, obeul[1], 'y'); + eulerO_rot(eul, obeul[1], 'y', cob->rotOrder); if (data->flag & ROTLIKE_Y_INVERT) eul[1] *= -1; @@ -1575,14 +1609,14 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta eul[2] = obeul[2]; else { if (data->flag & ROTLIKE_OFFSET) - euler_rot(eul, obeul[2], 'z'); + eulerO_rot(eul, obeul[2], 'z', cob->rotOrder); if (data->flag & ROTLIKE_Z_INVERT) eul[2] *= -1; } compatible_eul(eul, obeul); - LocEulSizeToMat4(cob->matrix, loc, eul, size); + LocEulOSizeToMat4(cob->matrix, loc, eul, size, cob->rotOrder); } } @@ -2845,7 +2879,7 @@ static void clampto_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain */ /* only happens on reload file, but violates depsgraph still... fix! */ - if (cu->path==NULL || cu->path->data==NULL) + if (cu->path==NULL || cu->path->data==NULL) makeDispListCurveTypes(cob->scene, ct->tar, 0); } @@ -2956,7 +2990,7 @@ static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta } /* 3. position on curve */ - if (where_on_path(ct->tar, curvetime, vec, dir) ) { + if (where_on_path(ct->tar, curvetime, vec, dir, NULL, NULL) ) { Mat4One(totmat); VECCOPY(totmat[3], vec); @@ -3038,7 +3072,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * Mat4ToSize(ct->matrix, dvec); break; case 1: /* rotation (convert to degrees first) */ - Mat4ToEul(ct->matrix, dvec); + Mat4ToEulO(ct->matrix, dvec, cob->rotOrder); for (i=0; i<3; i++) dvec[i] = (float)(dvec[i] / M_PI * 180); break; @@ -3049,7 +3083,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * /* extract components of owner's matrix */ VECCOPY(loc, cob->matrix[3]); - Mat4ToEul(cob->matrix, eul); + Mat4ToEulO(cob->matrix, eul, cob->rotOrder); Mat4ToSize(cob->matrix, size); /* determine where in range current transforms lie */ @@ -3104,7 +3138,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * } /* apply to matrix */ - LocEulSizeToMat4(cob->matrix, loc, eul, size); + LocEulOSizeToMat4(cob->matrix, loc, eul, size, cob->rotOrder); } } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 7dd868278f4..ea3fce9ffaf 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -65,11 +65,10 @@ #include "BKE_object.h" #include "BKE_utildefines.h" // VECCOPY - /* globals */ /* local */ -int cu_isectLL(float *v1, float *v2, float *v3, float *v4, +static int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec); @@ -137,7 +136,7 @@ Curve *add_curve(char *name, int type) cu= alloc_libblock(&G.main->curve, ID_CU, name); cu->size[0]= cu->size[1]= cu->size[2]= 1.0; - cu->flag= CU_FRONT+CU_BACK; + cu->flag= CU_FRONT|CU_BACK|CU_PATH_RADIUS; cu->pathlen= 100; cu->resolu= cu->resolv= 12; cu->width= 1.0; @@ -470,8 +469,11 @@ void test2DNurb(Nurb *nu) BezTriple *bezt; BPoint *bp; int a; + + if((nu->flag & CU_2D)==0) + return; - if( nu->type== CU_BEZIER+CU_2D ) { + if(nu->type == CU_BEZIER) { a= nu->pntsu; bezt= nu->bezt; while(a--) { @@ -481,7 +483,7 @@ void test2DNurb(Nurb *nu) bezt++; } } - else if(nu->type & CU_2D) { + else { a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a--) { @@ -497,7 +499,7 @@ void minmaxNurb(Nurb *nu, float *min, float *max) BPoint *bp; int a; - if( (nu->type & 7)==CU_BEZIER ) { + if(nu->type == CU_BEZIER) { a= nu->pntsu; bezt= nu->bezt; while(a--) { @@ -594,7 +596,7 @@ static void makecyclicknots(float *knots, short pnts, short order) void makeknots(Nurb *nu, short uv) { - if( (nu->type & 7)==CU_NURBS ) { + if(nu->type == CU_NURBS) { if(uv == 1) { if(nu->knotsu) MEM_freeN(nu->knotsu); if(check_valid_nurb_u(nu)) { @@ -850,7 +852,7 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride) MEM_freeN(jend); } -void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu) +void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu, int stride) /* coord_array has to be 3*4*pntsu*resolu in size and zero-ed * tilt_array and radius_array will be written to if valid */ { @@ -934,10 +936,10 @@ void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radiu } } - coord_fp+= 3; + coord_fp = (float *)(((char *)coord_fp) + stride); - if (tilt_fp) tilt_fp++; - if (radius_fp) radius_fp++; + if (tilt_fp) tilt_fp = (float *)(((char *)tilt_fp) + stride); + if (radius_fp) radius_fp = (float *)(((char *)radius_fp) + stride); u+= ustep; } @@ -968,12 +970,31 @@ void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int i for(a=0; a<=it; a++) { *p= q0; - p+= stride; + p = (float *)(((char *)p)+stride); q0+= q1; q1+= q2; q2+= q3; } -} +} + +static void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float *p3, float *p, int it, int stride) +{ + /* note that these are not purpendicular to the curve + * they need to be rotated for this, + * + * This could also be optimized like forward_diff_bezier */ + int a; + for(a=0; a<=it; a++) { + float t = (float)a / (float)it; + + int i; + for(i=0; i<3; i++) { + p[i]= (-6*t + 6)*p0[i] + (18*t - 12)*p1[i] + (-18*t + 6)*p2[i] + (6*t)*p3[i]; + } + Normalize(p); + p = (float *)(((char *)p)+stride); + } +} /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -1342,7 +1363,7 @@ void makebevelcurve(Scene *scene, Object *ob, ListBase *disp) } } -int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec) +static int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec) { /* return: -1: colliniar @@ -1387,8 +1408,8 @@ static short bevelinside(BevList *bl1,BevList *bl2) /* take first vertex of possible hole */ bevp= (BevPoint *)(bl2+1); - hvec1[0]= bevp->x; - hvec1[1]= bevp->y; + hvec1[0]= bevp->vec[0]; + hvec1[1]= bevp->vec[1]; hvec1[2]= 0.0; VECCOPY(hvec2,hvec1); hvec2[0]+=1000; @@ -1401,16 +1422,16 @@ static short bevelinside(BevList *bl1,BevList *bl2) prevbevp= bevp+(nr-1); while(nr--) { - min= prevbevp->y; - max= bevp->y; + min= prevbevp->vec[0]; + max= bevp->vec[1]; if(max<min) { min= max; - max= prevbevp->y; + max= prevbevp->vec[1]; } if(min!=max) { if(min<=hvec1[1] && max>=hvec1[1]) { /* there's a transition, calc intersection point */ - mode= cu_isectLL(&(prevbevp->x),&(bevp->x),hvec1,hvec2,0,1,&lab,&mu,vec); + mode= cu_isectLL(prevbevp->vec, bevp->vec, hvec1, hvec2, 0, 1, &lab, &mu, vec); /* if lab==0.0 or lab==1.0 then the edge intersects exactly a transition only allow for one situation: we choose lab= 1.0 */ @@ -1483,12 +1504,15 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si } -static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, int resolu) +static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, int resolu, int stride) { BezTriple *pprev, *next, *last; float fac, dfac, t[4]; int a; + if(tilt_array==NULL && radius_array==NULL) + return; + last= nu->bezt+(nu->pntsu-1); /* returns a point */ @@ -1511,11 +1535,13 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * for(a=0; a<resolu; a++, fac+= dfac) { if (tilt_array) { if (nu->tilt_interp==3) { /* May as well support for tilt also 2.47 ease interp */ - tilt_array[a] = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac); + *tilt_array = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac); } else { - set_four_ipo(fac, t, nu->tilt_interp); - tilt_array[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; + key_curve_position_weights(fac, t, nu->tilt_interp); + *tilt_array= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; } + + tilt_array = (float *)(((char *)tilt_array) + stride); } if (radius_array) { @@ -1523,19 +1549,363 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * /* Support 2.47 ease interp * Note! - this only takes the 2 points into account, * giving much more localized results to changes in radius, sometimes you want that */ - radius_array[a] = prevbezt->radius + (bezt->radius - prevbezt->radius)*(3.0f*fac*fac - 2.0f*fac*fac*fac); + *radius_array = prevbezt->radius + (bezt->radius - prevbezt->radius)*(3.0f*fac*fac - 2.0f*fac*fac*fac); } else { /* reuse interpolation from tilt if we can */ if (tilt_array==NULL || nu->tilt_interp != nu->radius_interp) { - set_four_ipo(fac, t, nu->radius_interp); + key_curve_position_weights(fac, t, nu->radius_interp); } - radius_array[a]= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius; + *radius_array= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius; + } + + radius_array = (float *)(((char *)radius_array) + stride); + } + } +} + +/* make_bevel_list_3D_* funcs, at a minimum these must + * fill in the bezp->quat and bezp->dir values */ + +/* correct non-cyclic cases by copying direction and rotation + * values onto the first & last end-points */ +static void bevel_list_cyclic_fix(BevList *bl) +{ + BevPoint *bevp, *bevp1; + + bevp= (BevPoint *)(bl+1); + bevp1= bevp+1; + QUATCOPY(bevp->quat, bevp1->quat); + VECCOPY(bevp->dir, bevp1->dir); + VECCOPY(bevp->tan, bevp1->tan); + bevp= (BevPoint *)(bl+1); + bevp+= (bl->nr-1); + bevp1= bevp-1; + QUATCOPY(bevp->quat, bevp1->quat); + VECCOPY(bevp->dir, bevp1->dir); + VECCOPY(bevp->tan, bevp1->tan); +} +/* utility for make_bevel_list_3D_* funcs */ +static void bevel_list_calc_bisect(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; + int nr; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + /* totally simple */ + VecBisect3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} +static void bevel_list_flip_tangents(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; + int nr; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + if(VecAngle2(bevp0->tan, bevp1->tan) > 90) + VecNegf(bevp1->tan); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} +/* apply user tilt */ +static void bevel_list_apply_tilt(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; + int nr; + float q[4]; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + AxisAngleToQuat(q, bevp1->dir, bevp1->alfa); + QuatMul(bevp1->quat, q, bevp1->quat); + NormalQuat(bevp1->quat); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} +/* smooth quats, this function should be optimized, it can get slow with many iterations. */ +static void bevel_list_smooth(BevList *bl, int smooth_iter) +{ + BevPoint *bevp2, *bevp1, *bevp0; + int nr; + + float q[4]; + float bevp0_quat[4]; + int a; + + for(a=0; a < smooth_iter; a++) { + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + + if(bl->poly== -1) { /* check its not cyclic */ + /* skip the first point */ + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + nr--; + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + nr--; + + } + + QUATCOPY(bevp0_quat, bevp0->quat); + + while(nr--) { + /* interpolate quats */ + float zaxis[3] = {0,0,1}, cross[3], q2[4]; + QuatInterpol(q, bevp0_quat, bevp2->quat, 0.5); + NormalQuat(q); + + QuatMulVecf(q, zaxis); + Crossf(cross, zaxis, bevp1->dir); + AxisAngleToQuat(q2, cross, NormalizedVecAngle2(zaxis, bevp1->dir)); + NormalQuat(q2); + + QUATCOPY(bevp0_quat, bevp1->quat); + QuatMul(q, q2, q); + QuatInterpol(bevp1->quat, bevp1->quat, q, 0.5); + NormalQuat(bevp1->quat); + + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + } +} + +static void make_bevel_list_3D_zup(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */ + int nr; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + /* totally simple */ + VecBisect3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec); + vectoquat(bevp1->dir, 5, 1, bevp1->quat); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} + +static void make_bevel_list_3D_minimum_twist(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */ + int nr; + float q[4]; + + float cross_tmp[3]; + + bevel_list_calc_bisect(bl); + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + + if(nr+4 > bl->nr) { /* first time and second time, otherwise first point adjusts last */ + vectoquat(bevp1->dir, 5, 1, bevp1->quat); + } + else { + float angle= NormalizedVecAngle2(bevp0->dir, bevp1->dir); + + if(angle > 0.0f) { /* otherwise we can keep as is */ + Crossf(cross_tmp, bevp0->dir, bevp1->dir); + AxisAngleToQuat(q, cross_tmp, angle); + QuatMul(bevp1->quat, q, bevp0->quat); } + else { + QUATCOPY(bevp1->quat, bevp0->quat); + } + } + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + + if(bl->poly != -1) { /* check for cyclic */ + + /* Need to correct for the start/end points not matching + * do this by calculating the tilt angle difference, then apply + * the rotation gradually over the entire curve + * + * note that the split is between last and second last, rather then first/last as youd expect. + * + * real order is like this + * 0,1,2,3,4 --> 1,2,3,4,0 + * + * this is why we compare last with second last + * */ + float vec_1[3]= {0,1,0}, vec_2[3]= {0,1,0}, angle, ang_fac, cross_tmp[3]; + + BevPoint *bevp_first; + BevPoint *bevp_last; + + + bevp_first= (BevPoint *)(bl+1); + bevp_first+= bl->nr-1; + bevp_last = bevp_first; + bevp_last--; + + /* quats and vec's are normalized, should not need to re-normalize */ + QuatMulVecf(bevp_first->quat, vec_1); + QuatMulVecf(bevp_last->quat, vec_2); + Normalize(vec_1); + Normalize(vec_2); + + /* align the vector, can avoid this and it looks 98% OK but + * better to align the angle quat roll's before comparing */ + { + Crossf(cross_tmp, bevp_last->dir, bevp_first->dir); + angle = NormalizedVecAngle2(bevp_first->dir, bevp_last->dir); + AxisAngleToQuat(q, cross_tmp, angle); + QuatMulVecf(q, vec_2); } + + angle= NormalizedVecAngle2(vec_1, vec_2); + + /* flip rotation if needs be */ + Crossf(cross_tmp, vec_1, vec_2); + Normalize(cross_tmp); + if(NormalizedVecAngle2(bevp_first->dir, cross_tmp) < 90/(180.0/M_PI)) + angle = -angle; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + ang_fac= angle * (1.0f-((float)nr/bl->nr)); /* also works */ + + AxisAngleToQuat(q, bevp1->dir, ang_fac); + QuatMul(bevp1->quat, q, bevp1->quat); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + } +} + +static void make_bevel_list_3D_tangent(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */ + int nr; + + float bevp0_tan[3], cross_tmp[3]; + + bevel_list_calc_bisect(bl); + if(bl->poly== -1) /* check its not cyclic */ + bevel_list_cyclic_fix(bl); // XXX - run this now so tangents will be right before doing the flipping + bevel_list_flip_tangents(bl); + + /* correct the tangents */ + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + + Crossf(cross_tmp, bevp1->tan, bevp1->dir); + Crossf(bevp1->tan, cross_tmp, bevp1->dir); + Normalize(bevp1->tan); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + + + /* now for the real twist calc */ + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + VECCOPY(bevp0_tan, bevp0->tan); + + nr= bl->nr; + while(nr--) { + + /* make perpendicular, modify tan in place, is ok */ + float cross_tmp[3]; + float zero[3] = {0,0,0}; + + Crossf(cross_tmp, bevp1->tan, bevp1->dir); + Normalize(cross_tmp); + triatoquat(zero, cross_tmp, bevp1->tan, bevp1->quat); /* XXX - could be faster */ + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; } } +static void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode) +{ + switch(twist_mode) { + case CU_TWIST_TANGENT: + make_bevel_list_3D_tangent(bl); + break; + case CU_TWIST_MINIMUM: + make_bevel_list_3D_minimum_twist(bl); + break; + default: /* CU_TWIST_Z_UP default, pre 2.49c */ + make_bevel_list_3D_zup(bl); + } + + if(bl->poly== -1) /* check its not cyclic */ + bevel_list_cyclic_fix(bl); + + if(smooth_iter) + bevel_list_smooth(bl, smooth_iter); + + bevel_list_apply_tilt(bl); +} + + + void makeBevelList(Object *ob) { /* @@ -1550,9 +1920,7 @@ void makeBevelList(Object *ob) BPoint *bp; BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; - float min, inp, x1, x2, y1, y2, vec[3]; - float *coord_array, *tilt_array=NULL, *radius_array=NULL, *coord_fp, *tilt_fp=NULL, *radius_fp=NULL; - float *v1, *v2; + float min, inp, x1, x2, y1, y2; struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu, len=0; int do_tilt, do_radius; @@ -1587,7 +1955,7 @@ void makeBevelList(Object *ob) else resolu= nu->resolu; - if((nu->type & 7)==CU_POLY) { + if(nu->type == CU_POLY) { len= nu->pntsu; bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList2"); BLI_addtail(&(cu->bev), bl); @@ -1595,22 +1963,20 @@ void makeBevelList(Object *ob) if(nu->flagu & CU_CYCLIC) bl->poly= 0; else bl->poly= -1; bl->nr= len; - bl->flag= 0; + bl->dupe_nr= 0; bevp= (BevPoint *)(bl+1); bp= nu->bp; while(len--) { - bevp->x= bp->vec[0]; - bevp->y= bp->vec[1]; - bevp->z= bp->vec[2]; + VECCOPY(bevp->vec, bp->vec); bevp->alfa= bp->alfa; bevp->radius= bp->radius; - bevp->f1= SELECT; + bevp->split_tag= TRUE; bevp++; bp++; } } - else if((nu->type & 7)==CU_BEZIER) { + else if(nu->type == CU_BEZIER) { len= resolu*(nu->pntsu+ (nu->flagu & CU_CYCLIC) -1)+1; /* in case last point is not cyclic */ bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelBPoints"); @@ -1631,139 +1997,81 @@ void makeBevelList(Object *ob) bezt++; } - coord_array= coord_fp= MEM_mallocN(3*sizeof(float)*(resolu+1), "makeBevelCoords"); - - if(do_tilt) - tilt_array= tilt_fp= MEM_callocN(sizeof(float)*(resolu+1), "makeBevelTilt"); - - if (do_radius) - radius_array= radius_fp= MEM_callocN(sizeof(float)*(resolu+1), "nakeBevelRadius"); - while(a--) { if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) { - - bevp->x= prevbezt->vec[1][0]; - bevp->y= prevbezt->vec[1][1]; - bevp->z= prevbezt->vec[1][2]; + + VECCOPY(bevp->vec, prevbezt->vec[1]); bevp->alfa= prevbezt->alfa; bevp->radius= prevbezt->radius; - bevp->f1= SELECT; - bevp->f2= 0; + bevp->split_tag= TRUE; + bevp->dupe_tag= FALSE; bevp++; bl->nr++; - bl->flag= 1; + bl->dupe_nr= 1; } else { - v1= prevbezt->vec[1]; - v2= bezt->vec[0]; - /* always do all three, to prevent data hanging around */ - forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], coord_array, resolu, 3); - forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], coord_array+1, resolu, 3); - forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], coord_array+2, resolu, 3); + int j; - if (do_tilt || do_radius) - alfa_bezpart(prevbezt, bezt, nu, tilt_array, radius_array, resolu); + /* BevPoint must stay aligned to 4 so sizeof(BevPoint)/sizeof(float) works */ + for(j=0; j<3; j++) { + forward_diff_bezier( prevbezt->vec[1][j], prevbezt->vec[2][j], + bezt->vec[0][j], bezt->vec[1][j], + &(bevp->vec[j]), resolu, sizeof(BevPoint)); + } + + /* if both arrays are NULL do nothiong */ + alfa_bezpart( prevbezt, bezt, nu, + do_tilt ? &bevp->alfa : NULL, + do_radius ? &bevp->radius : NULL, + resolu, sizeof(BevPoint)); + + if(cu->twist_mode==CU_TWIST_TANGENT) { + forward_diff_bezier_cotangent( + prevbezt->vec[1], prevbezt->vec[2], + bezt->vec[0], bezt->vec[1], + bevp->tan, resolu, sizeof(BevPoint)); + } + /* indicate with handlecodes double points */ if(prevbezt->h1==prevbezt->h2) { - if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= SELECT; + if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->split_tag= TRUE; } else { - if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= SELECT; - else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= SELECT; - } - - nr= resolu; - - coord_fp = coord_array; - tilt_fp = tilt_array; - radius_fp = radius_array; - - while(nr--) { - bevp->x= coord_fp[0]; - bevp->y= coord_fp[1]; - bevp->z= coord_fp[2]; - coord_fp+=3; - - if (do_tilt) { - bevp->alfa= *tilt_fp; - tilt_fp++; - } - - if (do_radius) { - bevp->radius= *radius_fp; - radius_fp++; - } - bevp++; + if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->split_tag= TRUE; + else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->split_tag= TRUE; } bl->nr+= resolu; - + bevp+= resolu; } prevbezt= bezt; bezt++; } - MEM_freeN(coord_array); - if (do_tilt) MEM_freeN(tilt_array); - if (do_radius) MEM_freeN(radius_array); - coord_array = tilt_array = radius_array = NULL; - if((nu->flagu & CU_CYCLIC)==0) { /* not cyclic: endpoint */ - bevp->x= prevbezt->vec[1][0]; - bevp->y= prevbezt->vec[1][1]; - bevp->z= prevbezt->vec[1][2]; + VECCOPY(bevp->vec, prevbezt->vec[1]); bevp->alfa= prevbezt->alfa; bevp->radius= prevbezt->radius; bl->nr++; } } - else if((nu->type & 7)==CU_NURBS) { + else if(nu->type == CU_NURBS) { if(nu->pntsv==1) { len= (resolu*SEGMENTSU(nu)); bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); BLI_addtail(&(cu->bev), bl); bl->nr= len; - bl->flag= 0; + bl->dupe_nr= 0; if(nu->flagu & CU_CYCLIC) bl->poly= 0; else bl->poly= -1; bevp= (BevPoint *)(bl+1); - - coord_array= coord_fp= MEM_callocN(3*sizeof(float)*len, "makeBevelCoords"); /* has to be zero-ed */ - - if(do_tilt) - tilt_array= tilt_fp= MEM_callocN(sizeof(float)*len, "makeBevelTilt"); - if (do_radius) - radius_array= radius_fp= MEM_callocN(sizeof(float)*len, "nakeBevelRadius"); - - makeNurbcurve(nu, coord_array, tilt_array, radius_array, resolu); - - while(len--) { - bevp->x= coord_fp[0]; - bevp->y= coord_fp[1]; - bevp->z= coord_fp[2]; - coord_fp+=3; - - if (do_tilt) { - bevp->alfa= *tilt_fp; - tilt_fp++; - } - - if (do_radius) { - bevp->radius= *radius_fp; - radius_fp++; - } - - - bevp->f1= bevp->f2= 0; - bevp++; - } - MEM_freeN(coord_array); - if (do_tilt) MEM_freeN(tilt_array); - if (do_radius) MEM_freeN(radius_array); - coord_array = tilt_array = radius_array = NULL; + makeNurbcurve( nu, &bevp->vec[0], + do_tilt ? &bevp->alfa : NULL, + do_radius ? &bevp->radius : NULL, + resolu, sizeof(BevPoint)); } } } @@ -1779,11 +2087,11 @@ void makeBevelList(Object *ob) bevp0= bevp1+(nr-1); nr--; while(nr--) { - if( fabs(bevp0->x-bevp1->x)<0.00001 ) { - if( fabs(bevp0->y-bevp1->y)<0.00001 ) { - if( fabs(bevp0->z-bevp1->z)<0.00001 ) { - bevp0->f2= SELECT; - bl->flag++; + if( fabs(bevp0->vec[0]-bevp1->vec[0])<0.00001 ) { + if( fabs(bevp0->vec[1]-bevp1->vec[1])<0.00001 ) { + if( fabs(bevp0->vec[2]-bevp1->vec[2])<0.00001 ) { + bevp0->dupe_tag= TRUE; + bl->dupe_nr++; } } } @@ -1796,8 +2104,8 @@ void makeBevelList(Object *ob) bl= cu->bev.first; while(bl) { blnext= bl->next; - if(bl->nr && bl->flag) { - nr= bl->nr- bl->flag+1; /* +1 because vectorbezier sets flag too */ + if(bl->nr && bl->dupe_nr) { + nr= bl->nr- bl->dupe_nr+1; /* +1 because vectorbezier sets flag too */ blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList4"); memcpy(blnew, bl, sizeof(BevList)); blnew->nr= 0; @@ -1807,7 +2115,7 @@ void makeBevelList(Object *ob) bevp1= (BevPoint *)(blnew+1); nr= bl->nr; while(nr--) { - if(bevp0->f2==0) { + if(bevp0->dupe_tag==0) { memcpy(bevp1, bevp0, sizeof(BevPoint)); bevp1++; blnew->nr++; @@ -1815,19 +2123,19 @@ void makeBevelList(Object *ob) bevp0++; } MEM_freeN(bl); - blnew->flag= 0; + blnew->dupe_nr= 0; } bl= blnext; } - /* STEP 3: COUNT POLYS TELLEN AND AUTOHOLE */ + /* STEP 3: POLYS COUNT AND AUTOHOLE */ bl= cu->bev.first; poly= 0; while(bl) { if(bl->nr && bl->poly>=0) { poly++; bl->poly= poly; - bl->gat= 0; /* 'gat' is dutch for hole */ + bl->hole= 0; } bl= bl->next; } @@ -1844,8 +2152,8 @@ void makeBevelList(Object *ob) bevp= (BevPoint *)(bl+1); nr= bl->nr; while(nr--) { - if(min>bevp->x) { - min= bevp->x; + if(min>bevp->vec[0]) { + min= bevp->vec[0]; bevp1= bevp; } bevp++; @@ -1860,8 +2168,7 @@ void makeBevelList(Object *ob) if(bevp1== bevp) bevp2= (BevPoint *)(bl+1); else bevp2= bevp1+1; - inp= (bevp1->x- bevp0->x)*(bevp0->y- bevp2->y) - +(bevp0->y- bevp1->y)*(bevp0->x- bevp2->x); + inp= (bevp1->vec[0]- bevp0->vec[0]) * (bevp0->vec[1]- bevp2->vec[1]) + (bevp0->vec[1]- bevp1->vec[1]) * (bevp0->vec[0]- bevp2->vec[0]); if(inp>0.0) sd->dir= 1; else sd->dir= 0; @@ -1879,7 +2186,7 @@ void makeBevelList(Object *ob) sd1= sortdata+ (a-1); for(b=a-1; b>=0; b--, sd1--) { /* all polys to the left */ if(bevelinside(sd1->bl, bl)) { - bl->gat= 1- sd1->bl->gat; + bl->hole= 1- sd1->bl->hole; break; } } @@ -1889,7 +2196,7 @@ void makeBevelList(Object *ob) if((cu->flag & CU_3D)==0) { sd= sortdata; for(a=0; a<poly; a++, sd++) { - if(sd->bl->gat==sd->dir) { + if(sd->bl->hole==sd->dir) { bl= sd->bl; bevp1= (BevPoint *)(bl+1); bevp2= bevp1+ (bl->nr-1); @@ -1905,104 +2212,90 @@ void makeBevelList(Object *ob) MEM_freeN(sortdata); } - /* STEP 4: COSINES */ - bl= cu->bev.first; - while(bl) { - - if(bl->nr==2) { /* 2 pnt, treat separate */ - bevp2= (BevPoint *)(bl+1); - bevp1= bevp2+1; + /* STEP 4: 2D-COSINES or 3D ORIENTATION */ + if((cu->flag & CU_3D)==0) { /* 3D */ + bl= cu->bev.first; + while(bl) { - x1= bevp1->x- bevp2->x; - y1= bevp1->y- bevp2->y; + if(bl->nr < 2) { + /* do nothing */ + } + else if(bl->nr==2) { /* 2 pnt, treat separate */ + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+1; - calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa)); - bevp2->sina= bevp1->sina; - bevp2->cosa= bevp1->cosa; + x1= bevp1->vec[0]- bevp2->vec[0]; + y1= bevp1->vec[1]- bevp2->vec[1]; - if(cu->flag & CU_3D) { /* 3D */ - float quat[4], q[4]; - - vec[0]= bevp1->x - bevp2->x; - vec[1]= bevp1->y - bevp2->y; - vec[2]= bevp1->z - bevp2->z; - - vectoquat(vec, 5, 1, quat); - - Normalize(vec); - q[0]= (float)cos(0.5*bevp1->alfa); - x1= (float)sin(0.5*bevp1->alfa); - q[1]= x1*vec[0]; - q[2]= x1*vec[1]; - q[3]= x1*vec[2]; - QuatMul(quat, q, quat); - - QuatToMat3(quat, bevp1->mat); - Mat3CpyMat3(bevp2->mat, bevp1->mat); + calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa)); + bevp2->sina= bevp1->sina; + bevp2->cosa= bevp1->cosa; } + else { + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; - } - else if(bl->nr>2) { - bevp2= (BevPoint *)(bl+1); - bevp1= bevp2+(bl->nr-1); - bevp0= bevp1-1; + nr= bl->nr; + while(nr--) { + x1= bevp1->vec[0]- bevp0->vec[0]; + x2= bevp1->vec[0]- bevp2->vec[0]; + y1= bevp1->vec[1]- bevp0->vec[1]; + y2= bevp1->vec[1]- bevp2->vec[1]; - - nr= bl->nr; - - while(nr--) { - - if(cu->flag & CU_3D) { /* 3D */ - float quat[4], q[4]; - - vec[0]= bevp2->x - bevp0->x; - vec[1]= bevp2->y - bevp0->y; - vec[2]= bevp2->z - bevp0->z; - - Normalize(vec); + calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); - vectoquat(vec, 5, 1, quat); - - q[0]= (float)cos(0.5*bevp1->alfa); - x1= (float)sin(0.5*bevp1->alfa); - q[1]= x1*vec[0]; - q[2]= x1*vec[1]; - q[3]= x1*vec[2]; - QuatMul(quat, q, quat); - - QuatToMat3(quat, bevp1->mat); + bevp0= bevp1; + bevp1= bevp2; + bevp2++; } - - x1= bevp1->x- bevp0->x; - x2= bevp1->x- bevp2->x; - y1= bevp1->y- bevp0->y; - y2= bevp1->y- bevp2->y; - - calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); - - - bevp0= bevp1; - bevp1= bevp2; - bevp2++; - } - /* correct non-cyclic cases */ - if(bl->poly== -1) { - if(bl->nr>2) { + + /* correct non-cyclic cases */ + if(bl->poly== -1) { bevp= (BevPoint *)(bl+1); bevp1= bevp+1; bevp->sina= bevp1->sina; bevp->cosa= bevp1->cosa; - Mat3CpyMat3(bevp->mat, bevp1->mat); bevp= (BevPoint *)(bl+1); bevp+= (bl->nr-1); bevp1= bevp-1; bevp->sina= bevp1->sina; bevp->cosa= bevp1->cosa; - Mat3CpyMat3(bevp->mat, bevp1->mat); } } + bl= bl->next; + } + } + else { /* 3D Curves */ + bl= cu->bev.first; + while(bl) { + + if(bl->nr < 2) { + /* do nothing */ + } + else if(bl->nr==2) { /* 2 pnt, treat separate */ + float q[4]; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+1; + + /* simple quat/dir */ + VecSubf(bevp1->dir, bevp1->vec, bevp2->vec); + Normalize(bevp1->dir); + + vectoquat(bevp1->dir, 5, 1, bevp1->quat); + + AxisAngleToQuat(q, bevp1->dir, bevp1->alfa); + QuatMul(bevp1->quat, q, bevp1->quat); + NormalQuat(bevp1->quat); + VECCOPY(bevp2->dir, bevp1->dir); + QUATCOPY(bevp2->quat, bevp1->quat); + } + else { + make_bevel_list_3D(bl, (int)(resolu*cu->twist_smooth), cu->twist_mode); + } + bl= bl->next; } - bl= bl->next; } } @@ -2207,7 +2500,7 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */ BezTriple *bezt, *prev, *next; short a; - if((nu->type & 7)!=CU_BEZIER) return; + if(nu->type != CU_BEZIER) return; if(nu->pntsu<2) return; a= nu->pntsu; @@ -2242,7 +2535,7 @@ void testhandlesNurb(Nurb *nu) BezTriple *bezt; short flag, a; - if((nu->type & 7)!=CU_BEZIER) return; + if(nu->type != CU_BEZIER) return; bezt= nu->bezt; a= nu->pntsu; @@ -2370,7 +2663,7 @@ void sethandlesNurb(ListBase *editnurb, short code) if(code==1 || code==2) { nu= editnurb->first; while(nu) { - if( (nu->type & 7)==CU_BEZIER) { + if(nu->type == CU_BEZIER) { bezt= nu->bezt; a= nu->pntsu; while(a--) { @@ -2400,7 +2693,7 @@ void sethandlesNurb(ListBase *editnurb, short code) } else { /* Toggle */ while(nu) { - if( (nu->type & 7)==CU_BEZIER) { + if(nu->type == CU_BEZIER) { bezt= nu->bezt; a= nu->pntsu; while(a--) { @@ -2417,7 +2710,7 @@ void sethandlesNurb(ListBase *editnurb, short code) } nu= editnurb->first; while(nu) { - if( (nu->type & 7)==CU_BEZIER) { + if(nu->type == CU_BEZIER) { bezt= nu->bezt; a= nu->pntsu; while(a--) { @@ -2465,7 +2758,7 @@ void switchdirectionNurb(Nurb *nu) if(nu->pntsu==1 && nu->pntsv==1) return; - if((nu->type & 7)==CU_BEZIER) { + if(nu->type == CU_BEZIER) { a= nu->pntsu; bezt1= nu->bezt; bezt2= bezt1+(a-1); @@ -2504,7 +2797,7 @@ void switchdirectionNurb(Nurb *nu) bp1++; bp2--; } - if((nu->type & 7)==CU_NURBS) { + if(nu->type == CU_NURBS) { /* inverse knots */ a= KNOTSU(nu); fp1= nu->knotsu; @@ -2567,7 +2860,7 @@ float (*curve_getVertexCos(Curve *cu, ListBase *lb, int *numVerts_r))[3] co = cos[0]; for (nu=lb->first; nu; nu=nu->next) { - if ((nu->type & 7)==CU_BEZIER) { + if (nu->type == CU_BEZIER) { BezTriple *bezt = nu->bezt; for (i=0; i<nu->pntsu; i++,bezt++) { @@ -2594,7 +2887,7 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3]) int i; for (nu=lb->first; nu; nu=nu->next) { - if ((nu->type & 7)==CU_BEZIER) { + if (nu->type == CU_BEZIER) { BezTriple *bezt = nu->bezt; for (i=0; i<nu->pntsu; i++,bezt++) { @@ -2616,7 +2909,7 @@ int check_valid_nurb_u( struct Nurb *nu ) { if (nu==NULL) return 0; if (nu->pntsu <= 1) return 0; - if ((nu->type & 7)!=CU_NURBS) return 1; /* not a nurb, lets assume its valid */ + if (nu->type != CU_NURBS) return 1; /* not a nurb, lets assume its valid */ if (nu->pntsu < nu->orderu) return 0; if (((nu->flag & CU_CYCLIC)==0) && ((nu->flagu>>1) & 2)) { /* Bezier U Endpoints */ @@ -2630,7 +2923,7 @@ int check_valid_nurb_v( struct Nurb *nu) { if (nu==NULL) return 0; if (nu->pntsv <= 1) return 0; - if ((nu->type & 7)!=CU_NURBS) return 1; /* not a nurb, lets assume its valid */ + if (nu->type != CU_NURBS) return 1; /* not a nurb, lets assume its valid */ if (nu->pntsv < nu->orderv) return 0; if (((nu->flag & CU_CYCLIC)==0) && ((nu->flagv>>1) & 2)) { /* Bezier V Endpoints */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 6c765b02e5d..58f3db50d0f 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -61,6 +61,7 @@ #include "DNA_space_types.h" #include "DNA_view2d_types.h" #include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" #include "BLI_ghash.h" @@ -77,6 +78,7 @@ #include "BKE_pointcache.h" #include "BKE_utildefines.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "MEM_guardedalloc.h" @@ -2141,43 +2143,106 @@ void DAG_scene_update_flags(Scene *scene, unsigned int lay) } +static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay) +{ + wmWindowManager *wm; + wmWindow *win; + + /* only one scene supported currently, making more scenes work + correctly requires changes beyond just the dependency graph */ + + *sce= NULL; + *lay= 0; + + if((wm= bmain->wm.first)) { + /* if we have a windowmanager, look into windows */ + for(win=wm->windows.first; win; win=win->next) { + if(win->screen) { + if(!*sce) *sce= win->screen->scene; + *lay |= BKE_screen_visible_layers(win->screen); + } + } + } + else { + /* if not, use the first sce */ + *sce= bmain->scene.first; + if(*sce) *lay= (*sce)->lay; -/* flag this object and all its relations to recalc */ -/* if you need to do more objects, tag object yourself and - use DAG_scene_flush_update() in end */ -void DAG_object_flush_update(Scene *sce, Object *ob, short flag) + /* XXX for background mode, we should get the scen + from somewhere, for the -S option, but it's in + the context, how to get it here? */ + } +} + +void DAG_ids_flush_update(int time) { - - if(ob==NULL || sce->theDag==NULL) return; + Main *bmain= G.main; + Scene *sce; + unsigned int lay; - ob->recalc |= flag; - BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH); - - /* all users of this ob->data should be checked */ - /* BUT! displists for curves are still only on cu */ - if(flag & OB_RECALC_DATA) { - if(ob->type!=OB_CURVE && ob->type!=OB_SURF) { - ID *id= ob->data; - if(id && id->us>1) { - /* except when there's a key and shapes are locked */ - if(ob_get_key(ob) && (ob->shapeflag & (OB_SHAPE_LOCK|OB_SHAPE_TEMPLOCK))); - else { - Object *obt; - for (obt=G.main->object.first; obt; obt= obt->id.next) { - if (obt != ob && obt->data==ob->data) { - obt->recalc |= OB_RECALC_DATA; - BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); - } - } + dag_current_scene_layers(bmain, &sce, &lay); + + if(sce) + DAG_scene_flush_update(sce, lay, time); +} + +void DAG_id_flush_update(ID *id, short flag) +{ + Main *bmain= G.main; + Scene *sce; + Object *obt, *ob= NULL; + short idtype; + unsigned int lay; + + dag_current_scene_layers(bmain, &sce, &lay); + + if(!id || !sce || !sce->theDag) + return; + + /* set flags & pointcache for object */ + if(GS(id->name) == ID_OB) { + ob= (Object*)id; + ob->recalc |= flag; + BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH); + + if(flag & OB_RECALC_DATA) { + /* all users of this ob->data should be checked */ + id= ob->data; + + /* no point in trying in this cases */ + if(!id || id->us <= 1) + id= NULL; + /* curves and surfaces only need to mark one object, since + otherwise cu->displist would be computed multiple times */ + else if(ob->type==OB_CURVE || ob->type==OB_SURF) + id= NULL; + /* also for locked shape keys we make an exception */ + else if(ob_get_key(ob) && (ob->shapeflag & (OB_SHAPE_LOCK|OB_SHAPE_TEMPLOCK))) + id= NULL; + } + } + + /* set flags & pointcache for object data */ + if(id) { + idtype= GS(id->name); + + if(ELEM7(idtype, ID_ME, ID_CU, ID_MB, ID_LA, ID_LT, ID_CA, ID_AR)) { + for(obt=bmain->object.first; obt; obt= obt->id.next) { + if(!(ob && obt == ob) && obt->data == id) { + obt->recalc |= OB_RECALC_DATA; + BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); + + /* for these we only flag one object, otherwise cu->displist + would be computed multiple times */ + if(obt->type==OB_CURVE || obt->type==OB_SURF) + break; } } } } - -// XXX if(G.curscreen) -// DAG_scene_flush_update(sce, dag_screen_view3d_layers(), 0); -// else - DAG_scene_flush_update(sce, sce->lay, 0); + + /* flush to other objects that depend on this one */ + DAG_scene_flush_update(sce, lay, 0); } /* recursively descends tree, each node only checked once */ @@ -2212,10 +2277,25 @@ static int parent_check_node(DagNode *node, int curtime) /* all nodes that influence this object get tagged, for calculating the exact position of this object at a given timeframe */ -void DAG_object_update_flags(Scene *sce, Object *ob, unsigned int lay) +void DAG_id_update_flags(ID *id) { + Main *bmain= G.main; + Scene *sce; DagNode *node; DagAdjList *itA; + Object *ob; + unsigned int lay; + + dag_current_scene_layers(bmain, &sce, &lay); + + if(!id || !sce || !sce->theDag) + return; + + /* objects only currently */ + if(GS(id->name) != ID_OB) + return; + + ob= (Object*)id; /* tag nodes unchecked */ for(node = sce->theDag->DagNode.first; node; node= node->next) diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 6f897be9b05..d8f466835b3 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -821,7 +821,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) DispList *dl; BezTriple *bezt, *prevbezt; BPoint *bp; - float *data, *v1, *v2; + float *data; int a, len, resolu; nu= nubase->first; @@ -834,7 +834,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) resolu= nu->resolu; if(!check_valid_nurb_u(nu)); - else if((nu->type & 7)==CU_BEZIER) { + else if(nu->type == CU_BEZIER) { /* count */ len= 0; @@ -886,11 +886,15 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) data+= 3; } else { - v1= prevbezt->vec[1]; - v2= bezt->vec[0]; - forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], data, resolu, 3); - forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], data+1, resolu, 3); - forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], data+2, resolu, 3); + int j; + for(j=0; j<3; j++) { + forward_diff_bezier( prevbezt->vec[1][j], + prevbezt->vec[2][j], + bezt->vec[0][j], + bezt->vec[1][j], + data+j, resolu, 3*sizeof(float)); + } + data+= 3*resolu; } @@ -902,7 +906,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) bezt++; } } - else if((nu->type & 7)==CU_NURBS) { + else if(nu->type == CU_NURBS) { len= (resolu*SEGMENTSU(nu)); dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); @@ -917,9 +921,9 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) data= dl->verts; if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, NULL, NULL, resolu); + makeNurbcurve(nu, data, NULL, NULL, resolu, 3*sizeof(float)); } - else if((nu->type & 7)==CU_POLY) { + else if(nu->type == CU_POLY) { len= nu->pntsu; dl= MEM_callocN(sizeof(DispList), "makeDispListpoly"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); @@ -1127,7 +1131,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) } -void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) +static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) { if(cu->flag & CU_3D) return; @@ -1424,7 +1428,7 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, int forRende if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, NULL, NULL, nu->resolu); + makeNurbcurve(nu, data, NULL, NULL, nu->resolu, 3*sizeof(float)); } else { len= (nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv); @@ -1539,9 +1543,9 @@ void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) bevp= (BevPoint *)(bl+1); data= dl->verts; while(a--) { - data[0]= bevp->x+widfac*bevp->sina; - data[1]= bevp->y+widfac*bevp->cosa; - data[2]= bevp->z; + data[0]= bevp->vec[0]+widfac*bevp->sina; + data[1]= bevp->vec[1]+widfac*bevp->cosa; + data[2]= bevp->vec[2]; bevp++; data+=3; } @@ -1581,7 +1585,7 @@ void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) fac = calc_taper(scene, cu->taperobj, a, bl->nr); } - if (bevp->f1) { + if (bevp->split_tag) { dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F); } @@ -1595,16 +1599,16 @@ void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) vec[1]= fp1[2]; vec[2]= 0.0; - Mat3MulVecfl(bevp->mat, vec); + QuatMulVecf(bevp->quat, vec); - data[0]= bevp->x+ fac*vec[0]; - data[1]= bevp->y+ fac*vec[1]; - data[2]= bevp->z+ fac*vec[2]; + data[0]= bevp->vec[0] + fac*vec[0]; + data[1]= bevp->vec[1] + fac*vec[1]; + data[2]= bevp->vec[2] + fac*vec[2]; } else { - data[0]= bevp->x+ fac*(widfac+fp1[1])*bevp->sina; - data[1]= bevp->y+ fac*(widfac+fp1[1])*bevp->cosa; - data[2]= bevp->z+ fac*fp1[2]; + data[0]= bevp->vec[0] + fac*(widfac+fp1[1])*bevp->sina; + data[1]= bevp->vec[1] + fac*(widfac+fp1[1])*bevp->cosa; + data[2]= bevp->vec[2] + fac*fp1[2]; } } } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 31f6e2c6067..54d2f85457f 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -916,7 +916,7 @@ void correct_bezpart (float *v1, float *v2, float *v3, float *v4) } /* find root ('zero') */ -int findzero (float x, float q0, float q1, float q2, float q3, float *o) +static int findzero (float x, float q0, float q1, float q2, float q3, float *o) { double c0, c1, c2, c3, a, b, c, p, q, d, t, phi; int nr= 0; @@ -1010,7 +1010,7 @@ int findzero (float x, float q0, float q1, float q2, float q3, float *o) } } -void berekeny (float f1, float f2, float f3, float f4, float *o, int b) +static void berekeny (float f1, float f2, float f3, float f4, float *o, int b) { float t, c0, c1, c2, c3; int a; @@ -1026,7 +1026,7 @@ void berekeny (float f1, float f2, float f3, float f4, float *o, int b) } } -void berekenx (float *f, float *o, int b) +static void berekenx (float *f, float *o, int b) { float t, c0, c1, c2, c3; int a; diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 0024f84d8fb..2233bbbf328 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -80,6 +80,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd) if(!fss) return; + fss->fmd = fluidmd; fss->type = OB_FLUIDSIM_ENABLE; fss->show_advancedoptions = 0; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 70901778585..4e05bf45d3d 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -129,7 +129,7 @@ wcsleninu8(wchar_t *src) } int -utf8slen(char *src) +static utf8slen(char *src) { int size = 0, index = 0; unsigned char c; @@ -462,7 +462,7 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i nu2->resolu= cu->resolu; nu2->bezt = NULL; nu2->knotsu = nu2->knotsv = NULL; - nu2->flag= 0; + nu2->flag= CU_2D; nu2->charidx = charidx+1000; if (mat_nr > 0) nu2->mat_nr= mat_nr-1; nu2->pntsu = 4; @@ -495,7 +495,6 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i nu2->bp[3].vec[2] = 0; nu2->bp[3].vec[3] = 1.0; - nu2->type = CU_2D; BLI_addtail(&(cu->nurb), nu2); } @@ -1040,8 +1039,8 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) /* calc the right loc AND the right rot separately */ /* vec, tvec need 4 items */ - where_on_path(cu->textoncurve, ctime, vec, tvec); - where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec); + where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL); + where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL); VecMulf(vec, sizefac); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index dd8f44c71d5..43c4137e73e 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -214,6 +214,11 @@ bGPdata *gpencil_data_addnew (char name[]) /* initial settings */ gpd->flag = (GP_DATA_DISPINFO|GP_DATA_EXPAND); + /* for now, stick to view is also enabled by default + * since this is more useful... + */ + gpd->flag |= GP_DATA_VIEWALIGN; + return gpd; } @@ -308,7 +313,7 @@ bGPdata *gpencil_data_duplicate (bGPdata *src) void gpencil_frame_delete_laststroke (bGPDlayer *gpl, bGPDframe *gpf) { bGPDstroke *gps= (gpf) ? gpf->strokes.last : NULL; - int cfra = 1; // XXX FIXME!!! + int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */ /* error checking */ if (ELEM(NULL, gpf, gps)) diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 6fffbd794ef..6bb47bc0f0f 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -142,6 +142,16 @@ Group *add_group(char *name) return group; } +Group *copy_group(Group *group) +{ + Group *groupn; + + groupn= MEM_dupallocN(group); + BLI_duplicatelist(&groupn->gobject, &group->gobject); + + return groupn; +} + /* external */ void add_to_group(Group *group, Object *ob) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index eb8872c43a5..cdb175ed661 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -38,6 +38,11 @@ #include <time.h> +#ifdef _WIN32 +#define open _open +#define close _close +#endif + #include "MEM_guardedalloc.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index fc5213d5532..956a5851827 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -43,7 +43,7 @@ #include <windows.h> static LARGE_INTEGER _itstart, _itend; static LARGE_INTEGER ifreq; -void itstart(void) +static void itstart(void) { static int first = 1; if(first) { @@ -52,7 +52,7 @@ void itstart(void) } QueryPerformanceCounter(&_itstart); } -void itend(void) +static void itend(void) { QueryPerformanceCounter(&_itend); } @@ -74,7 +74,7 @@ double itval() { gettimeofday(&_itstart, &itz); } -void itend(void) +static void itend(void) { gettimeofday(&_itend,&itz); } @@ -155,7 +155,7 @@ DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vec /* printf vector[3] on console: for debug output */ -void print_fvector(float m3[3]) +static void print_fvector(float m3[3]) { printf("%f\n%f\n%f\n\n",m3[0],m3[1],m3[2]); } @@ -297,7 +297,7 @@ DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], f // 3x3 matrix /////////////////////////// /* printf 3x3 matrix on console: for debug output */ -void print_fmatrix(float m3[3][3]) +static void print_fmatrix(float m3[3][3]) { printf("%f\t%f\t%f\n",m3[0][0],m3[0][1],m3[0][2]); printf("%f\t%f\t%f\n",m3[1][0],m3[1][1],m3[1][2]); @@ -496,7 +496,7 @@ DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float fro // SPARSE SYMMETRIC big matrix with 3x3 matrix entries /////////////////////////// /* printf a big matrix on console: for debug output */ -void print_bfmatrix(fmatrix3x3 *m3) +static void print_bfmatrix(fmatrix3x3 *m3) { unsigned int i = 0; @@ -887,7 +887,7 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) } } -int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) +static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) { // Solves for unknown X in equation AX=B unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100; @@ -970,7 +970,7 @@ DO_INLINE void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv) } /* // version 1.3 -int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv) +static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100; float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0; @@ -1038,7 +1038,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma } */ // version 1.4 -int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *bigI) +static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *bigI) { unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100; float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0, tol = 0; @@ -1183,7 +1183,8 @@ DO_INLINE void dfdx_spring(float to[3][3], float dir[3],float length,float L,fl //return ( (I-outerprod(dir,dir))*Min(1.0f,rest/length) - I) * -k; mul_fvectorT_fvector(to, dir, dir); sub_fmatrix_fmatrix(to, I, to); - mul_fmatrix_S(to, (((L/length)> 1.0f) ? (1.0f): (L/length))); + + mul_fmatrix_S(to, (L/length)); sub_fmatrix_fmatrix(to, to, I); mul_fmatrix_S(to, -k); } @@ -1218,6 +1219,8 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; float scaling = 0.0; + + int no_compress = clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1254,7 +1257,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, // calculate force of structural + shear springs if((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR)) { - if(length > L) // only on elonglation + if(length > L || no_compress) { s->flags |= CLOTH_SPRING_FLAG_NEEDED; @@ -1388,11 +1391,89 @@ static void CalcFloat4( float *v1, float *v2, float *v3, float *v4, float *n) n[2]= n1[0]*n2[1]-n1[1]*n2[0]; } -float calculateVertexWindForce(float wind[3], float vertexnormal[3]) +static float calculateVertexWindForce(float wind[3], float vertexnormal[3]) { return (INPR(wind, vertexnormal)); } +typedef struct HairGridVert { + float velocity[3]; + float density; +} HairGridVert; +/* Smoothing of hair velocities: + * adapted from + Volumetric Methods for Simulation and Rendering of Hair + by Lena Petrovic, Mark Henne and John Anderson + * Pixar Technical Memo #06-08, Pixar Animation Studios + */ +static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, lfVector *lV, int numverts) +{ + /* TODO: this is an initial implementation and should be made much better in due time */ + + /* 10x10x10 grid gives nice initial results */ + HairGridVert grid[10][10][10]; + float gmin[3], gmax[3], density; + int v = 0; + int i = 0; + int j = 0; + int k = 0; + lfVector temp; + + INIT_MINMAX(gmin, gmax); + + for(i = 0; i < numverts; i++) + DO_MINMAX(lX[i], gmin, gmax); + + /* initialize grid */ + for(i = 0; i < 10; i++) { + for(j = 0; j < 10; j++) { + for(k = 0; k < 10; k++) { + grid[i][j][k].velocity[0] = 0.0f; + grid[i][j][k].velocity[1] = 0.0f; + grid[i][j][k].velocity[2] = 0.0f; + grid[i][j][k].density = 0.0f; + } + } + } + + /* gather velocities & density */ + for(v = 0; v < numverts; v++) { + i = (int)( (lX[v][0] - gmin[0]) / (gmax[0] - gmin[0]) * 9.99f ); + j = (int)( (lX[v][1] - gmin[1]) / (gmax[1] - gmin[1]) * 9.99f ); + k = (int)( (lX[v][2] - gmin[2]) / (gmax[2] - gmin[2]) * 9.99f ); + + grid[i][j][k].velocity[0] += lV[v][0]; + grid[i][j][k].velocity[1] += lV[v][1]; + grid[i][j][k].velocity[2] += lV[v][2]; + grid[i][j][k].density += 1.0f; + } + + /* divide velocity with density */ + for(i = 0; i < 10; i++) { + for(j = 0; j < 10; j++) { + for(k = 0; k < 10; k++) { + density = grid[i][j][k].density; + if(density > 0.0f) { + grid[i][j][k].velocity[0] /= density; + grid[i][j][k].velocity[1] /= density; + grid[i][j][k].velocity[2] /= density; + } + } + } + } + + /* calculate forces */ + for(v = 0; v < numverts; v++) { + i = (int)( (lX[v][0] - gmin[0]) / (gmax[0] - gmin[0]) * 9.99f ); + j = (int)( (lX[v][1] - gmin[1]) / (gmax[1] - gmin[1]) * 9.99f ); + k = (int)( (lX[v][2] - gmin[2]) / (gmax[2] - gmin[2]) * 9.99f ); + + /* 2.0f is an experimental value that seems to give good results */ + lF[v][0] += 2.0f * smoothfac * (grid[i][j][k].velocity[0] - lV[v][0]); + lF[v][1] += 2.0f * smoothfac * (grid[i][j][k].velocity[1] - lV[v][1]); + lF[v][2] += 2.0f * smoothfac * (grid[i][j][k].velocity[2] - lV[v][2]); + } +} static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M) { /* Collect forces and derivatives: F,dFdX,dFdV */ @@ -1416,6 +1497,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, init_lfvector(lF, gravity, numverts); + if(clmd->sim_parms->velocity_smooth > 0.0f) + hair_velocity_smoothing(clmd->sim_parms->velocity_smooth, lF, lX, lV, numverts); + /* multiply lF with mass matrix // force = mass * acceleration (in this case: gravity) */ @@ -1511,7 +1595,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, // printf("\n"); } -void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *M, fmatrix3x3 *bigI) +static void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *M, fmatrix3x3 *bigI) { unsigned int numverts = dFdV[0].vcount; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 2f0e0931588..62f44d92d25 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -820,7 +820,7 @@ static char *particle_adrcodes_to_paths (int adrcode, int *array_index) * - array_index - index in property's array (if applicable) to use * - return - the allocated path... */ -char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index) +static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index) { DynStr *path= BLI_dynstr_new(); char *propname=NULL, *rpath=NULL; diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 4ba1c46d0c3..6d22b170e08 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -267,66 +267,91 @@ void sort_keys(Key *key) /**************** do the key ****************/ +void key_curve_position_weights(float t, float *data, int type) +{ + float t2, t3, fc; + + if(type==KEY_LINEAR) { + data[0]= 0.0f; + data[1]= -t + 1.0f; + data[2]= t; + data[3]= 0.0f; + } + else if(type==KEY_CARDINAL) { + t2= t*t; + t3= t2*t; + fc= 0.71f; + + data[0]= -fc*t3 + 2.0f*fc*t2 - fc*t; + data[1]= (2.0f-fc)*t3 + (fc-3.0f)*t2 + 1.0f; + data[2]= (fc-2.0f)*t3 + (3.0f-2.0f*fc)*t2 + fc*t; + data[3]= fc*t3 - fc*t2; + } + else if(type==KEY_BSPLINE) { + t2= t*t; + t3= t2*t; + + data[0]= -0.16666666f*t3 + 0.5f*t2 - 0.5f*t + 0.16666666f; + data[1]= 0.5f*t3 - t2 + 0.6666666f; + data[2]= -0.5f*t3 + 0.5f*t2 + 0.5f*t + 0.16666666f; + data[3]= 0.16666666f*t3; + } +} -void set_four_ipo(float d, float *data, int type) +/* first derivative */ +void key_curve_tangent_weights(float t, float *data, int type) { - float d2, d3, fc; + float t2, fc; if(type==KEY_LINEAR) { data[0]= 0.0f; - data[1]= 1.0f-d; - data[2]= d; + data[1]= -1.0f; + data[2]= 1.0f; data[3]= 0.0f; } - else { - d2= d*d; - d3= d2*d; + else if(type==KEY_CARDINAL) { + t2= t*t; + fc= 0.71f; - if(type==KEY_CARDINAL) { - - fc= 0.71f; - - data[0]= -fc*d3 +2.0f*fc*d2 -fc*d; - data[1]= (2.0f-fc)*d3 +(fc-3.0f)*d2 +1.0f; - data[2]= (fc-2.0f)*d3 +(3.0f-2.0f*fc)*d2 +fc*d; - data[3]= fc*d3 -fc*d2; - } - else if(type==KEY_BSPLINE) { + data[0]= -3.0f*fc*t2 +4.0f*fc*t - fc; + data[1]= 3.0f*(2.0f-fc)*t2 +2.0f*(fc-3.0f)*t; + data[2]= 3.0f*(fc-2.0f)*t2 +2.0f*(3.0f-2.0f*fc)*t + fc; + data[3]= 3.0f*fc*t2 -2.0f*fc*t; + } + else if(type==KEY_BSPLINE) { + t2= t*t; - data[0]= -0.16666666f*d3 +0.5f*d2 -0.5f*d +0.16666666f; - data[1]= 0.5f*d3 -d2 +0.6666666f; - data[2]= -0.5f*d3 +0.5f*d2 +0.5f*d +0.16666666f; - data[3]= 0.16666666f*d3 ; - } + data[0]= -0.5f*t2 + t - 0.5f; + data[1]= 1.5f*t2 - 2.0f*t; + data[2]= -1.5f*t2 + t + 0.5f; + data[3]= 0.5f*t2; } } -void set_afgeleide_four_ipo(float d, float *data, int type) +/* second derivative */ +void key_curve_normal_weights(float t, float *data, int type) { - float d2, fc; + float fc; if(type==KEY_LINEAR) { - + data[0]= 0.0f; + data[1]= 0.0f; + data[2]= 0.0f; + data[3]= 0.0f; } - else { - d2= d*d; + else if(type==KEY_CARDINAL) { + fc= 0.71f; - if(type==KEY_CARDINAL) { - - fc= 0.71f; - - data[0]= -3.0f*fc*d2 +4.0f*fc*d -fc; - data[1]= 3.0f*(2.0f-fc)*d2 +2.0f*(fc-3.0f)*d; - data[2]= 3.0f*(fc-2.0f)*d2 +2.0f*(3.0f-2.0f*fc)*d +fc; - data[3]= 3.0f*fc*d2 -2.0f*fc*d; - } - else if(type==KEY_BSPLINE) { - - data[0]= -0.16666666f*3.0f*d2 +d -0.5f; - data[1]= 1.5f*d2 -2.0f*d; - data[2]= -1.5f*d2 +d +0.5f; - data[3]= 0.16666666f*3.0f*d2 ; - } + data[0]= -6.0f*fc*t + 4.0f*fc; + data[1]= 6.0f*(2.0f-fc)*t + 2.0f*(fc-3.0f); + data[2]= 6.0f*(fc-2.0f)*t + 2.0f*(3.0f-2.0f*fc); + data[3]= 6.0f*fc*t - 2.0f*fc; + } + else if(type==KEY_BSPLINE) { + data[0]= -1.0f*t + 1.0f; + data[1]= 3.0f*t - 2.0f; + data[2]= -3.0f*t + 1.0f; + data[3]= 1.0f*t; } } @@ -437,10 +462,10 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl) /* interpolation */ - set_four_ipo(d, t, k[1]->type); + key_curve_position_weights(d, t, k[1]->type); if(k[1]->type != k[2]->type) { - set_four_ipo(d, fval, k[2]->type); + key_curve_position_weights(d, fval, k[2]->type); temp= 1.0f-d; t[0]= temp*t[0]+ d*fval[0]; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 70d76d25e93..d58f8447d28 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -365,7 +365,7 @@ void calc_latt_deform(Object *ob, float *co, float weight) u= (vec[0]-lt->fu)/lt->du; ui= (int)floor(u); u -= ui; - set_four_ipo(u, tu, lt->typeu); + key_curve_position_weights(u, tu, lt->typeu); } else { tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0; @@ -376,7 +376,7 @@ void calc_latt_deform(Object *ob, float *co, float weight) v= (vec[1]-lt->fv)/lt->dv; vi= (int)floor(v); v -= vi; - set_four_ipo(v, tv, lt->typev); + key_curve_position_weights(v, tv, lt->typev); } else { tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0; @@ -387,7 +387,7 @@ void calc_latt_deform(Object *ob, float *co, float weight) w= (vec[2]-lt->fw)/lt->dw; wi= (int)floor(w); w -= wi; - set_four_ipo(w, tw, lt->typew); + key_curve_position_weights(w, tw, lt->typew); } else { tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0; @@ -473,7 +473,7 @@ static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd, int dloc } /* this makes sure we can extend for non-cyclic. *vec needs 4 items! */ -static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir) /* returns OK */ +static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius) /* returns OK */ { Curve *cu= ob->data; BevList *bl; @@ -491,21 +491,25 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir) else ctime1= ctime; /* vec needs 4 items */ - if(where_on_path(ob, ctime1, vec, dir)) { + if(where_on_path(ob, ctime1, vec, dir, quat, radius)) { if(cycl==0) { Path *path= cu->path; float dvec[3]; if(ctime < 0.0) { - VecSubf(dvec, path->data+4, path->data); + VecSubf(dvec, path->data[1].vec, path->data[0].vec); VecMulf(dvec, ctime*(float)path->len); VECADD(vec, vec, dvec); + if(quat) QUATCOPY(quat, path->data[0].quat); + if(radius) *radius= path->data[0].radius; } else if(ctime > 1.0) { - VecSubf(dvec, path->data+4*path->len-4, path->data+4*path->len-8); + VecSubf(dvec, path->data[path->len-1].vec, path->data[path->len-2].vec); VecMulf(dvec, (ctime-1.0)*(float)path->len); VECADD(vec, vec, dvec); + if(quat) QUATCOPY(quat, path->data[path->len-1].quat); + if(radius) *radius= path->data[path->len-1].radius; } } return 1; @@ -521,7 +525,7 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir) static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, CurveDeform *cd, float *quatp) { Curve *cu= par->data; - float fac, loc[4], dir[3], cent[3]; + float fac, loc[4], dir[3], cent[3], radius; short upflag, index; if(axis==MOD_CURVE_POSX || axis==MOD_CURVE_NEGX) { @@ -576,7 +580,7 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C } #endif // XXX old animation system - if( where_on_path_deform(par, fac, loc, dir)) { /* returns OK */ + if( where_on_path_deform(par, fac, loc, dir, NULL, &radius)) { /* returns OK */ float q[4], mat[3][3], quat[4]; if(cd->no_rot_axis) /* set by caller */ @@ -596,7 +600,14 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C QuatMul(quat, q, quat); } QuatToMat3(quat, mat); - + + if(cu->flag & CU_PATH_RADIUS) { + float tmat[3][3], rmat[3][3]; + Mat3Scale(tmat, radius); + Mat3MulMat3(rmat, mat, tmat); + Mat3CpyMat3(mat, rmat); + } + /* local rotation */ Mat3MulVecfl(mat, cent); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index c1654646a2b..eb9d578402d 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -119,6 +119,13 @@ #define MAX_IDPUP 60 /* was 24 */ +/* GS reads the memory pointed at in a specific ordering. + only use this definition, makes little and big endian systems + work fine, in conjunction with MAKE_ID */ + +/* from blendef: */ +#define GS(a) (*((short *)(a))) + /* ************* general ************************ */ void id_lib_extern(ID *id) @@ -148,6 +155,220 @@ void id_us_min(ID *id) id->us--; } +int id_make_local(ID *id, int test) +{ + if(id->flag & LIB_INDIRECT) + return 0; + + switch(GS(id->name)) { + case ID_SCE: + return 0; /* not implemented */ + case ID_LI: + return 0; /* can't be linked */ + case ID_OB: + if(!test) make_local_object((Object*)id); + return 1; + case ID_ME: + if(!test) { + make_local_mesh((Mesh*)id); + make_local_key(((Mesh*)id)->key); + } + return 1; + case ID_CU: + if(!test) { + make_local_curve((Curve*)id); + make_local_key(((Curve*)id)->key); + } + return 1; + case ID_MB: + if(!test) make_local_mball((MetaBall*)id); + return 1; + case ID_MA: + if(!test) make_local_material((Material*)id); + return 1; + case ID_TE: + if(!test) make_local_texture((Tex*)id); + return 1; + case ID_IM: + return 0; /* not implemented */ + case ID_WV: + return 0; /* deprecated */ + case ID_LT: + if(!test) { + make_local_lattice((Lattice*)id); + make_local_key(((Lattice*)id)->key); + } + return 1; + case ID_LA: + if(!test) make_local_lamp((Lamp*)id); + return 1; + case ID_CA: + if(!test) make_local_camera((Camera*)id); + return 1; + case ID_IP: + return 0; /* deprecated */ + case ID_KE: + if(!test) make_local_key((Key*)id); + return 1; + case ID_WO: + if(!test) make_local_world((World*)id); + return 1; + case ID_SCR: + return 0; /* can't be linked */ + case ID_VF: + return 0; /* not implemented */ + case ID_TXT: + return 0; /* not implemented */ + case ID_SCRIPT: + return 0; /* deprecated */ + case ID_SO: + return 0; /* not implemented */ + case ID_GR: + return 0; /* not implemented */ + case ID_AR: + if(!test) make_local_armature((bArmature*)id); + return 1; + case ID_AC: + if(!test) make_local_action((bAction*)id); + return 1; + case ID_NT: + return 0; /* not implemented */ + case ID_BR: + if(!test) make_local_brush((Brush*)id); + return 1; + case ID_PA: + if(!test) make_local_particlesettings((ParticleSettings*)id); + return 1; + case ID_WM: + return 0; /* can't be linked */ + case ID_GD: + return 0; /* not implemented */ + } + + return 0; +} + +int id_copy(ID *id, ID **newid, int test) +{ + if(!test) *newid= NULL; + + /* conventions: + * - make shallow copy, only this ID block + * - id.us of the new ID is set to 1 */ + switch(GS(id->name)) { + case ID_SCE: + return 0; /* can't be copied from here */ + case ID_LI: + return 0; /* can't be copied from here */ + case ID_OB: + if(!test) *newid= (ID*)copy_object((Object*)id); + return 1; + case ID_ME: + if(!test) *newid= (ID*)copy_mesh((Mesh*)id); + return 1; + case ID_CU: + if(!test) *newid= (ID*)copy_curve((Curve*)id); + return 1; + case ID_MB: + if(!test) *newid= (ID*)copy_mball((MetaBall*)id); + return 1; + case ID_MA: + if(!test) *newid= (ID*)copy_material((Material*)id); + return 1; + case ID_TE: + if(!test) *newid= (ID*)copy_texture((Tex*)id); + return 1; + case ID_IM: + return 0; /* not implemented */ + case ID_WV: + return 0; /* deprecated */ + case ID_LT: + if(!test) *newid= (ID*)copy_lattice((Lattice*)id); + return 1; + case ID_LA: + if(!test) *newid= (ID*)copy_lamp((Lamp*)id); + return 1; + case ID_CA: + if(!test) *newid= (ID*)copy_camera((Camera*)id); + return 1; + case ID_IP: + return 0; /* deprecated */ + case ID_KE: + if(!test) *newid= (ID*)copy_key((Key*)id); + return 1; + case ID_WO: + if(!test) *newid= (ID*)copy_world((World*)id); + return 1; + case ID_SCR: + return 0; /* can't be copied from here */ + case ID_VF: + return 0; /* not implemented */ + case ID_TXT: + if(!test) *newid= (ID*)copy_text((Text*)id); + return 1; + case ID_SCRIPT: + return 0; /* deprecated */ + case ID_SO: + return 0; /* not implemented */ + case ID_GR: + if(!test) *newid= (ID*)copy_group((Group*)id); + return 1; + case ID_AR: + if(!test) *newid= (ID*)copy_armature((bArmature*)id); + return 1; + case ID_AC: + if(!test) *newid= (ID*)copy_action((bAction*)id); + return 1; + case ID_NT: + if(!test) *newid= (ID*)ntreeCopyTree((bNodeTree*)id, 0); + return 1; + case ID_BR: + if(!test) *newid= (ID*)copy_brush((Brush*)id); + return 1; + case ID_PA: + if(!test) *newid= (ID*)psys_copy_settings((ParticleSettings*)id); + return 1; + case ID_WM: + return 0; /* can't be copied from here */ + case ID_GD: + return 0; /* not implemented */ + } + + return 0; +} + +int id_unlink(ID *id, int test) +{ + Main *mainlib= G.main; + ListBase *lb; + + switch(GS(id->name)) { + case ID_TXT: + if(test) return 1; + unlink_text(mainlib, (Text*)id); + break; + case ID_GR: + if(test) return 1; + unlink_group((Group*)id); + break; + case ID_OB: + if(test) return 1; + unlink_object(NULL, (Object*)id); + break; + } + + if(id->us == 0) { + if(test) return 1; + + lb= wich_libbase(mainlib, GS(id->name)); + free_libblock(lb, id); + + return 1; + } + + return 0; +} + ListBase *wich_libbase(Main *mainlib, short type) { switch( type ) { @@ -234,6 +455,15 @@ void flag_all_listbases_ids(short flag, short value) while(a--) flag_listbase_ids(lbarray[a], flag, value); } +void recalc_all_library_objects(Main *main) +{ + Object *ob; + + /* flag for full recalc */ + for(ob=main->object.first; ob; ob=ob->id.next) + if(ob->id.lib) + ob->recalc |= OB_RECALC; +} /* note: MAX_LIBARRAY define should match this code */ int set_listbasepointers(Main *main, ListBase **lb) @@ -409,13 +639,6 @@ void *alloc_libblock(ListBase *lb, short type, const char *name) return id; } -/* GS reads the memory pointed at in a specific ordering. - only use this definition, makes little and big endian systems - work fine, in conjunction with MAKE_ID */ - -/* from blendef: */ -#define GS(a) (*((short *)(a))) - /* by spec, animdata is first item after ID */ /* we still read ->adt itself, to ensure compiler warns when it doesnt exist */ static void id_copy_animdata(ID *id) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 53de570b55e..1667bd97102 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -159,9 +159,9 @@ void init_material(Material *ma) ma->sss_radius[0]= 1.0f; ma->sss_radius[1]= 1.0f; ma->sss_radius[2]= 1.0f; - ma->sss_col[0]= 0.8f; - ma->sss_col[1]= 0.8f; - ma->sss_col[2]= 0.8f; + ma->sss_col[0]= 1.0f; + ma->sss_col[1]= 1.0f; + ma->sss_col[2]= 1.0f; ma->sss_error= 0.05f; ma->sss_scale= 0.1f; ma->sss_ior= 1.3f; @@ -1031,15 +1031,15 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col) } break; case MA_RAMP_DARK: - tmp= fac*col[0]; - if(tmp < *r) *r= tmp; - if(g) { - tmp= fac*col[1]; - if(tmp < *g) *g= tmp; - tmp= fac*col[2]; - if(tmp < *b) *b= tmp; - } - break; + tmp=col[0]+((1-col[0])*facm); + if(tmp < *r) *r= tmp; + if(g) { + tmp=col[1]+((1-col[1])*facm); + if(tmp < *g) *g= tmp; + tmp=col[2]+((1-col[2])*facm); + if(tmp < *b) *b= tmp; + } + break; case MA_RAMP_LIGHT: tmp= fac*col[0]; if(tmp > *r) *r= tmp; @@ -1169,8 +1169,37 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col) } } break; - } - + case MA_RAMP_SOFT: + if (g){ + float scr, scg, scb; + + /* first calculate non-fac based Screen mix */ + scr = 1.0 - ((1.0 - col[0])) * (1.0 - *r); + scg = 1.0 - ((1.0 - col[1])) * (1.0 - *g); + scb = 1.0 - ((1.0 - col[2])) * (1.0 - *b); + + *r = facm*(*r) + fac*(((1.0 - *r) * col[0] * (*r)) + (*r * scr)); + *g = facm*(*g) + fac*(((1.0 - *g) * col[1] * (*g)) + (*g * scg)); + *b = facm*(*b) + fac*(((1.0 - *b) * col[2] * (*b)) + (*b * scb)); + } + break; + case MA_RAMP_LINEAR: + if (col[0] > 0.5) + *r = *r + fac*(2*(col[0]-0.5)); + else + *r = *r + fac*(2*(col[0]) - 1); + if (g){ + if (col[1] > 0.5) + *g = *g + fac*(2*(col[1]-0.5)); + else + *g = *g + fac*(2*(col[1]) -1); + if (col[2] > 0.5) + *b = *b + fac*(2*(col[2]-0.5)); + else + *b = *b + fac*(2*(col[2]) - 1); + } + break; + } } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 35e2989650a..18a88cdb36a 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1110,7 +1110,7 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) } } -// XXX do this in caller DAG_object_flush_update(scene, meshOb, OB_RECALC_DATA); +// XXX do this in caller DAG_id_flush_update(&me->id, OB_RECALC_DATA); } void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float **faceNors_r) @@ -1398,7 +1398,7 @@ void mesh_pmv_revert(Object *ob, Mesh *me) MEM_freeN(me->pv->vert_map); me->pv->vert_map= NULL; -// XXX do this in caller DAG_object_flush_update(scene, ob, OB_RECALC_DATA); +// XXX do this in caller DAG_id_flush_update(&me->id, OB_RECALC_DATA); } } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 496cc2b8224..a4813eb0247 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -76,8 +76,8 @@ #include "BLI_editVert.h" -#include "MTC_matrixops.h" -#include "MTC_vectorops.h" + + #include "BKE_main.h" #include "BKE_anim.h" @@ -218,7 +218,7 @@ static void curveModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->name, cmd->name, 32); } -CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md) { CurveModifierData *cmd = (CurveModifierData *)md; CustomDataMask dataMask = 0; @@ -294,7 +294,7 @@ static void latticeModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tlmd->name, lmd->name, 32); } -CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md) { LatticeModifierData *lmd = (LatticeModifierData *)md; CustomDataMask dataMask = 0; @@ -1111,7 +1111,7 @@ static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, Sc } } -float vertarray_size(MVert *mvert, int numVerts, int axis) +static float vertarray_size(MVert *mvert, int numVerts, int axis) { int i; float min_co, max_co; @@ -1198,7 +1198,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->end_cap && amd->end_cap != ob) end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH); - MTC_Mat4One(offset); + Mat4One(offset); indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm), "indexmap"); @@ -1220,14 +1220,14 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, float result_mat[4][4]; if(ob) - MTC_Mat4Invert(obinv, ob->obmat); + Mat4Invert(obinv, ob->obmat); else - MTC_Mat4One(obinv); + Mat4One(obinv); - MTC_Mat4MulSerie(result_mat, offset, + Mat4MulSerie(result_mat, offset, obinv, amd->offset_ob->obmat, NULL, NULL, NULL, NULL, NULL); - MTC_Mat4CpyMat4(offset, result_mat); + Mat4CpyMat4(offset, result_mat); } if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { @@ -1252,7 +1252,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, prescribed length */ if(amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) { - float dist = sqrt(MTC_dot3Float(offset[3], offset[3])); + float dist = sqrt(Inpf(offset[3], offset[3])); if(dist > 1e-6f) /* this gives length = first copy start to last copy end @@ -1285,11 +1285,11 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces, 0, 0); /* calculate the offset matrix of the final copy (for merging) */ - MTC_Mat4One(final_offset); + Mat4One(final_offset); for(j=0; j < count - 1; j++) { - MTC_Mat4MulMat4(tmp_mat, final_offset, offset); - MTC_Mat4CpyMat4(final_offset, tmp_mat); + Mat4MulMat4(tmp_mat, final_offset, offset); + Mat4CpyMat4(final_offset, tmp_mat); } numVerts = numEdges = numFaces = 0; @@ -1325,7 +1325,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if((count > 1) && (amd->flags & MOD_ARR_MERGE)) { float tmp_co[3]; VECCOPY(tmp_co, mv->co); - MTC_Mat4MulVecfl(offset, tmp_co); + Mat4MulVecfl(offset, tmp_co); for(j = 0; j < maxVerts; j++) { /* if vertex already merged, don't use it */ @@ -1340,7 +1340,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->flags & MOD_ARR_MERGEFINAL) { VECCOPY(tmp_co, inMV->co); inMV = &src_mvert[i]; - MTC_Mat4MulVecfl(final_offset, tmp_co); + Mat4MulVecfl(final_offset, tmp_co); if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) indexMap[i].merge_final = 1; } @@ -1358,7 +1358,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, *mv2 = *mv; numVerts++; - MTC_Mat4MulVecfl(offset, co); + Mat4MulVecfl(offset, co); VECCOPY(mv2->co, co); } } else if(indexMap[i].merge != i && indexMap[i].merge_final) { @@ -1789,7 +1789,7 @@ static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, S /* finds the best possible flipped name. For renaming; check for unique names afterwards */ /* if strip_number: removes number extensions */ -void vertgroup_flip_name (char *name, int strip_number) +static void vertgroup_flip_name (char *name, int strip_number) { int len; char prefix[128]={""}; /* The part before the facing */ @@ -2326,7 +2326,7 @@ DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd) VECCOPY(etags[ml->e].fno, no); etags[ml->e].has_fno = 1; } else if (!etags[ml->e].tag) { - edge_angle_cos = MTC_dot3Float(etags[ml->e].fno, no); + edge_angle_cos = INPR(etags[ml->e].fno, no); if (edge_angle_cos < threshold) { etags[ml->e].tag = 1; } @@ -2593,7 +2593,7 @@ static void bevelModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tbmd->defgrp_name, bmd->defgrp_name, 32); } -CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md) { BevelModifierData *bmd = (BevelModifierData *)md; CustomDataMask dataMask = 0; @@ -2673,7 +2673,7 @@ static void displaceModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32); } -CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; CustomDataMask dataMask = 0; @@ -3017,7 +3017,7 @@ static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target) tumd->aspecty = umd->aspecty; } -CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -3243,11 +3243,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, /* find the projector which the face points at most directly * (projector normal with largest dot product is best) */ - best_dot = MTC_dot3Float(projectors[0].normal, face_no); + best_dot = Inpf(projectors[0].normal, face_no); best_projector = &projectors[0]; for(j = 1; j < num_projectors; ++j) { - float tmp_dot = MTC_dot3Float(projectors[j].normal, + float tmp_dot = Inpf(projectors[j].normal, face_no); if(tmp_dot > best_dot) { best_dot = tmp_dot; @@ -3470,7 +3470,7 @@ static void smoothModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tsmd->defgrp_name, smd->defgrp_name, 32); } -int smoothModifier_isDisabled(ModifierData *md) +static int smoothModifier_isDisabled(ModifierData *md) { SmoothModifierData *smd = (SmoothModifierData*) md; short flag; @@ -3483,7 +3483,7 @@ int smoothModifier_isDisabled(ModifierData *md) return 0; } -CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md) { SmoothModifierData *smd = (SmoothModifierData *)md; CustomDataMask dataMask = 0; @@ -3700,7 +3700,7 @@ static void castModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32); } -int castModifier_isDisabled(ModifierData *md) +static int castModifier_isDisabled(ModifierData *md) { CastModifierData *cmd = (CastModifierData*) md; short flag; @@ -3712,7 +3712,7 @@ int castModifier_isDisabled(ModifierData *md) return 0; } -CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md) { CastModifierData *cmd = (CastModifierData *)md; CustomDataMask dataMask = 0; @@ -4343,7 +4343,7 @@ static void waveModifier_updateDepgraph( } } -CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md) { WaveModifierData *wmd = (WaveModifierData *)md; CustomDataMask dataMask = 0; @@ -4679,7 +4679,7 @@ static void armatureModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tamd->defgrp_name, amd->defgrp_name, 32); } -CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -4794,7 +4794,7 @@ static void hookModifier_copyData(ModifierData *md, ModifierData *target) strncpy(thmd->subtarget, hmd->subtarget, 32); } -CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md) { HookModifierData *hmd = (HookModifierData *)md; CustomDataMask dataMask = 0; @@ -5139,7 +5139,7 @@ static void clothModifier_updateDepgraph( } } -CustomDataMask clothModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask clothModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -5563,7 +5563,7 @@ static DerivedMesh *booleanModifier_applyModifier( return derivedData; } -CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE); @@ -5611,7 +5611,7 @@ static void particleSystemModifier_copyData(ModifierData *md, ModifierData *targ tpsmd->psys = psmd->psys; } -CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData *md) { ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; CustomDataMask dataMask = 0; @@ -5888,10 +5888,8 @@ static DerivedMesh * particleInstanceModifier_applyModifier( if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){ float ran = 0.0f; if(pimd->random_position != 0.0f) { - /* just use some static collection of random numbers */ - /* TODO: use something else that's unique to each instanced object */ - pa = psys->particles + (i/totvert)%totpart; - ran = pimd->random_position * 0.5 * (1.0f + pa->r_ave[0]); + BLI_srandom(psys->seed + (i/totvert)%totpart); + ran = pimd->random_position * BLI_frand(); } if(pimd->flag & eParticleInstanceFlag_KeepShape) { @@ -6027,7 +6025,7 @@ static int explodeModifier_dependsOnTime(ModifierData *md) { return 1; } -CustomDataMask explodeModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask explodeModifier_requiredDataMask(Object *ob, ModifierData *md) { ExplodeModifierData *emd= (ExplodeModifierData*) md; CustomDataMask dataMask = 0; @@ -6943,7 +6941,7 @@ static void meshdeformModifier_copyData(ModifierData *md, ModifierData *target) tmmd->object = mmd->object; } -CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierData *md) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; CustomDataMask dataMask = 0; @@ -7322,7 +7320,7 @@ static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target) tsmd->subsurfLevels = smd->subsurfLevels; } -CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierData *md) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; CustomDataMask dataMask = 0; @@ -8333,7 +8331,7 @@ int modifiers_indexInObject(Object *ob, ModifierData *md_seek) return i; } -int modifiers_usesPointCache(Object *ob) +static int modifiers_usesPointCache(Object *ob) { ModifierData *md = ob->modifiers.first; diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 3cf1785f3ef..b502c21188f 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -67,9 +67,6 @@ #include "BLI_editVert.h" -#include "MTC_matrixops.h" -#include "MTC_vectorops.h" - #include "BKE_main.h" #include "BKE_anim.h" #include "BKE_bmesh.h" @@ -230,8 +227,136 @@ BMEditMesh *CDDM_To_BMesh(DerivedMesh *dm, BMEditMesh *existing) return em; } -float vertarray_size(MVert *mvert, int numVerts, int axis); +static float vertarray_size(MVert *mvert, int numVerts, int axis) +{ + int i; + float min_co, max_co; + + /* if there are no vertices, width is 0 */ + if(numVerts == 0) return 0; + + /* find the minimum and maximum coordinates on the desired axis */ + min_co = max_co = mvert->co[axis]; + ++mvert; + for(i = 1; i < numVerts; ++i, ++mvert) { + if(mvert->co[axis] < min_co) min_co = mvert->co[axis]; + if(mvert->co[axis] > max_co) max_co = mvert->co[axis]; + } + + return max_co - min_co; +} + +/* finds the best possible flipped name. For renaming; check for unique names afterwards */ +/* if strip_number: removes number extensions */ +static void vertgroup_flip_name (char *name, int strip_number) +{ + int len; + char prefix[128]={""}; /* The part before the facing */ + char suffix[128]={""}; /* The part after the facing */ + char replace[128]={""}; /* The replacement string */ + char number[128]={""}; /* The number extension string */ + char *index=NULL; + + len= strlen(name); + if(len<3) return; // we don't do names like .R or .L + + /* We first check the case with a .### extension, let's find the last period */ + if(isdigit(name[len-1])) { + index= strrchr(name, '.'); // last occurrance + if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever! + if(strip_number==0) + strcpy(number, index); + *index= 0; + len= strlen(name); + } + } + + strcpy (prefix, name); + +#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_') + + /* first case; separator . - _ with extensions r R l L */ + if( IS_SEPARATOR(name[len-2]) ) { + switch(name[len-1]) { + case 'l': + prefix[len-1]= 0; + strcpy(replace, "r"); + break; + case 'r': + prefix[len-1]= 0; + strcpy(replace, "l"); + break; + case 'L': + prefix[len-1]= 0; + strcpy(replace, "R"); + break; + case 'R': + prefix[len-1]= 0; + strcpy(replace, "L"); + break; + } + } + /* case; beginning with r R l L , with separator after it */ + else if( IS_SEPARATOR(name[1]) ) { + switch(name[0]) { + case 'l': + strcpy(replace, "r"); + strcpy(suffix, name+1); + prefix[0]= 0; + break; + case 'r': + strcpy(replace, "l"); + strcpy(suffix, name+1); + prefix[0]= 0; + break; + case 'L': + strcpy(replace, "R"); + strcpy(suffix, name+1); + prefix[0]= 0; + break; + case 'R': + strcpy(replace, "L"); + strcpy(suffix, name+1); + prefix[0]= 0; + break; + } + } + else if(len > 5) { + /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */ + index = BLI_strcasestr(prefix, "right"); + if (index==prefix || index==prefix+len-5) { + if(index[0]=='r') + strcpy (replace, "left"); + else { + if(index[1]=='I') + strcpy (replace, "LEFT"); + else + strcpy (replace, "Left"); + } + *index= 0; + strcpy (suffix, index+5); + } + else { + index = BLI_strcasestr(prefix, "left"); + if (index==prefix || index==prefix+len-4) { + if(index[0]=='l') + strcpy (replace, "right"); + else { + if(index[1]=='E') + strcpy (replace, "RIGHT"); + else + strcpy (replace, "Right"); + } + *index= 0; + strcpy (suffix, index+4); + } + } + } + +#undef IS_SEPARATOR + sprintf (name, "%s%s%s%s", prefix, replace, suffix, number); +} typedef struct IndexMapEntry { /* the new vert index that this old vert index maps to */ @@ -296,7 +421,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->end_cap && amd->end_cap != ob) end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH); - MTC_Mat4One(offset); + Mat4One(offset); src_mvert = cddm->getVertArray(dm); maxVerts = cddm->getNumVerts(dm); @@ -314,14 +439,14 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, float result_mat[4][4]; if(ob) - MTC_Mat4Invert(obinv, ob->obmat); + Mat4Invert(obinv, ob->obmat); else - MTC_Mat4One(obinv); + Mat4One(obinv); - MTC_Mat4MulSerie(result_mat, offset, + Mat4MulSerie(result_mat, offset, obinv, amd->offset_ob->obmat, NULL, NULL, NULL, NULL, NULL); - MTC_Mat4CpyMat4(offset, result_mat); + Mat4CpyMat4(offset, result_mat); } if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { @@ -347,7 +472,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) { - float dist = sqrt(MTC_dot3Float(offset[3], offset[3])); + float dist = sqrt(INPR(offset[3], offset[3])); if(dist > 1e-6f) /* this gives length = first copy start to last copy end @@ -379,11 +504,11 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, } /* calculate the offset matrix of the final copy (for merging) */ - MTC_Mat4One(final_offset); + Mat4One(final_offset); for(j=0; j < count - 1; j++) { - MTC_Mat4MulMat4(tmp_mat, final_offset, offset); - MTC_Mat4CpyMat4(final_offset, tmp_mat); + Mat4MulMat4(tmp_mat, final_offset, offset); + Mat4CpyMat4(final_offset, tmp_mat); } BMO_Init_Op(&weldop, "weldverts"); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 2555bc6de27..f38b36d47b3 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -83,7 +83,7 @@ int multiresModifier_switch_level(Object *ob, const int distance) mmd->lvl += distance; if(mmd->lvl < 1) mmd->lvl = 1; else if(mmd->lvl > mmd->totlvl) mmd->lvl = mmd->totlvl; - /* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + /* XXX: DAG_id_flush_update(&ob->id, OB_RECALC_DATA); object_handle_update(ob);*/ return 1; } @@ -596,7 +596,7 @@ static void find_displacer_edges(MultiresDisplacer *d, DerivedMesh *dm, Displace } /* Returns in out the corners [0-3] that use v1 and v2 */ -void find_face_corners(MFace *f, int v1, int v2, int out[2]) +static void find_face_corners(MFace *f, int v1, int v2, int out[2]) { int i, end = f->v4 ? 4 : 3; @@ -1259,7 +1259,7 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i ***************************/ /* Does not actually free lvl itself */ -void multires_free_level(MultiresLevel *lvl) +static void multires_free_level(MultiresLevel *lvl) { if(lvl) { if(lvl->faces) MEM_freeN(lvl->faces); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 480c79fbc1a..83ee71bfe40 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1048,7 +1048,7 @@ short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max) /* Is the given NLA-strip the first one to occur for the given AnimData block */ // TODO: make this an api method if necesary, but need to add prefix first -short nlastrip_is_first (AnimData *adt, NlaStrip *strip) +static short nlastrip_is_first (AnimData *adt, NlaStrip *strip) { NlaTrack *nlt; NlaStrip *ns; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index bd6919dc115..90ea53d4364 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Bob Holcomb. * * ***** END GPL LICENSE BLOCK ***** */ @@ -2597,7 +2597,7 @@ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) if(outsocket_exists(lnode->new_node, lsock->new_sock)) { lsock->new_sock->ns.data= lsock->ns.data; lsock->ns.data= NULL; - lsock->new_sock= NULL; + lsock->new_sock= NULL; } } } @@ -2932,6 +2932,7 @@ static void registerCompositNodes(ListBase *ntypelist) nodeRegisterType(ntypelist, &cmp_node_viewer); nodeRegisterType(ntypelist, &cmp_node_splitviewer); nodeRegisterType(ntypelist, &cmp_node_output_file); + nodeRegisterType(ntypelist, &cmp_node_view_levels); nodeRegisterType(ntypelist, &cmp_node_curve_rgb); nodeRegisterType(ntypelist, &cmp_node_mix_rgb); @@ -2971,7 +2972,9 @@ static void registerCompositNodes(ListBase *ntypelist) nodeRegisterType(ntypelist, &cmp_node_premulkey); nodeRegisterType(ntypelist, &cmp_node_diff_matte); - nodeRegisterType(ntypelist, &cmp_node_chroma); + nodeRegisterType(ntypelist, &cmp_node_distance_matte); + nodeRegisterType(ntypelist, &cmp_node_chroma_matte); + nodeRegisterType(ntypelist, &cmp_node_color_matte); nodeRegisterType(ntypelist, &cmp_node_channel_matte); nodeRegisterType(ntypelist, &cmp_node_color_spill); nodeRegisterType(ntypelist, &cmp_node_luma_matte); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index cdcd90b6ebf..54c9293fd57 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -102,13 +102,13 @@ #include "BKE_mball.h" #include "BKE_modifier.h" #include "BKE_object.h" +#include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_property.h" #include "BKE_sca.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_sculpt.h" #include "BKE_softbody.h" #include "LBM_fluidsim.h" @@ -285,6 +285,7 @@ void free_object(Object *ob) if(ob->adt) BKE_free_animdata((ID *)ob); if(ob->poselib) ob->poselib->id.us--; if(ob->dup_group) ob->dup_group->id.us--; + if(ob->gpd) ob->gpd->id.us--; if(ob->defbase.first) BLI_freelistN(&ob->defbase); if(ob->pose) @@ -481,15 +482,15 @@ void unlink_object(Scene *scene, Object *ob) if(tpsys->part->dup_ob==ob) tpsys->part->dup_ob= NULL; - if(tpsys->part->flag&PART_STICKY) { + if(tpsys->part->phystype==PART_PHYS_BOIDS) { ParticleData *pa; + BoidParticle *bpa; int p; for(p=0,pa=tpsys->particles; p<tpsys->totpart; p++,pa++) { - if(pa->stick_ob==ob) { - pa->stick_ob= 0; - pa->flag &= ~PARS_STICKY; - } + bpa = pa->boid; + if(bpa->ground == ob) + bpa->ground = NULL; } } if(tpsys->part->boids) { @@ -1082,34 +1083,44 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys) { ParticleSystem *psysn; ParticleData *pa; - int a; + int p; psysn= MEM_dupallocN(psys); psysn->particles= MEM_dupallocN(psys->particles); psysn->child= MEM_dupallocN(psys->child); - if(psysn->particles->keys) - psysn->particles->keys = MEM_dupallocN(psys->particles->keys); - for(a=0, pa=psysn->particles; a<psysn->totpart; a++, pa++) { - if(pa->hair) - pa->hair= MEM_dupallocN(pa->hair); - if(a) - pa->keys= (pa-1)->keys + (pa-1)->totkey; + if(psys->part->type == PART_HAIR) { + for(p=0, pa=psysn->particles; p<psysn->totpart; p++, pa++) + pa->hair = MEM_dupallocN(pa->hair); } - if(psys->soft) { - psysn->soft= copy_softbody(psys->soft); - psysn->soft->particles = psysn; + if(psysn->particles->keys || psysn->particles->boid) { + ParticleKey *key = psysn->particles->keys; + BoidParticle *boid = psysn->particles->boid; + + if(key) + key = MEM_dupallocN(key); + + if(boid) + boid = MEM_dupallocN(boid); + + for(p=0, pa=psysn->particles; p<psysn->totpart; p++, pa++) { + if(boid) + pa->boid = boid++; + if(key) { + pa->keys = key; + key += pa->totkey; + } + } } - if(psys->particles->boid) { - psysn->particles->boid = MEM_dupallocN(psys->particles->boid); - for(a=1, pa=psysn->particles+1; a<psysn->totpart; a++, pa++) - pa->boid = (pa-1)->boid + 1; + if(psys->clmd) { + ClothModifierData *nclmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); + modifier_copyData((ModifierData*)psys->clmd, (ModifierData*)nclmd); + psys->hair_in_dm = psys->hair_out_dm = NULL; } - if(psys->targets.first) - BLI_duplicatelist(&psysn->targets, &psys->targets); + BLI_duplicatelist(&psysn->targets, &psys->targets); psysn->pathcache= NULL; psysn->childcache= NULL; @@ -1396,7 +1407,7 @@ int object_data_is_libdata(Object *ob) /* *************** PROXY **************** */ /* when you make proxy, ensure the exposed layers are extern */ -void armature_set_id_extern(Object *ob) +static void armature_set_id_extern(Object *ob) { bArmature *arm= ob->data; bPoseChannel *pchan; @@ -1636,7 +1647,7 @@ int enable_cu_speed= 1; static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) { Curve *cu; - float q[4], vec[4], dir[3], quat[4], x1, ctime; + float q[4], vec[4], dir[3], quat[4], radius, x1, ctime; float timeoffs = 0.0, sf_orig = 0.0; Mat4One(mat); @@ -1684,7 +1695,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) /* vec: 4 items! */ - if( where_on_path(par, ctime, vec, dir) ) { + if( where_on_path(par, ctime, vec, dir, NULL, &radius) ) { if(cu->flag & CU_FOLLOW) { vectoquat(dir, ob->trackflag, ob->upflag, quat); @@ -1701,6 +1712,13 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) QuatToMat4(quat, mat); } + if(cu->flag & CU_PATH_RADIUS) { + float tmat[4][4], rmat[4][4]; + Mat4Scale(tmat, radius); + Mat4MulMat4(rmat, mat, tmat); + Mat4CpyMat4(mat, rmat); + } + VECCOPY(mat[3], vec); } @@ -1798,7 +1816,7 @@ static void give_parvert(Object *par, int nr, float *vec) count= 0; while(nu && !found) { - if((nu->type & 7)==CU_BEZIER) { + if(nu->type == CU_BEZIER) { bezt= nu->bezt; a= nu->pntsu; while(a--) { diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 3e47c1006e5..0de97b9c703 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -63,6 +63,14 @@ #include "BKE_packedFile.h" #include "BKE_report.h" +#ifdef _WIN32 +#define open _open +#define close _close +#define read _read +#define write _write +#endif + + int seekPackedFile(PackedFile *pf, int offset, int whence) { int oldseek = -1, seek = 0; @@ -228,7 +236,7 @@ void packAll(Main *bmain, ReportList *reports) // attempt to create a function that generates an unique filename // this will work when all funtions in fileops.c understand relative filenames... -char *find_new_name(char *name) +static char *find_new_name(char *name) { char tempname[FILE_MAXDIR + FILE_MAXFILE]; char *newname; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 47b37c10689..954097d3a25 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -61,6 +61,7 @@ #include "BKE_anim.h" #include "BKE_boids.h" +#include "BKE_cloth.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_lattice.h" @@ -93,10 +94,10 @@ static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, P /* few helpers for countall etc. */ int count_particles(ParticleSystem *psys){ ParticleSettings *part=psys->part; - ParticleData *pa; - int tot=0,p; + PARTICLE_P; + int tot=0; - for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++){ + LOOP_PARTICLES { if(pa->alive == PARS_KILLED); else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); @@ -107,10 +108,10 @@ int count_particles(ParticleSystem *psys){ } int count_particles_mod(ParticleSystem *psys, int totgr, int cur){ ParticleSettings *part=psys->part; - ParticleData *pa; - int tot=0,p; + PARTICLE_P; + int tot=0; - for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++){ + LOOP_PARTICLES { if(pa->alive == PARS_KILLED); else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); @@ -121,10 +122,10 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){ } int psys_count_keys(ParticleSystem *psys) { - ParticleData *pa; - int i, totpart=psys->totpart, totkey=0; + PARTICLE_P; + int totkey=0; - for(i=0, pa=psys->particles; i<totpart; i++, pa++) + LOOP_PARTICLES totkey += pa->totkey; return totkey; @@ -322,7 +323,7 @@ int psys_ob_has_hair(Object *ob) } int psys_in_edit_mode(Scene *scene, ParticleSystem *psys) { - return ((scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys==psys_get_current((scene->basact)->object) && psys->edit); + return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys==psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit)); } int psys_check_enabled(Object *ob, ParticleSystem *psys) { @@ -367,33 +368,56 @@ void psys_free_settings(ParticleSettings *part) boid_free_settings(part->boids); } -void free_hair(ParticleSystem *psys, int softbody) +void free_hair(Object *ob, ParticleSystem *psys, int dynamics) { - ParticleData *pa; - int i, totpart=psys->totpart; + PARTICLE_P; - for(i=0, pa=psys->particles; i<totpart; i++, pa++) { + if(psys->part->type != PART_HAIR) + return; + + LOOP_PARTICLES { if(pa->hair) MEM_freeN(pa->hair); pa->hair = NULL; + pa->totkey = 0; } psys->flag &= ~PSYS_HAIR_DONE; - if(softbody && psys->soft) { - sbFree(psys->soft); - psys->soft = NULL; + if(psys->clmd) { + if(dynamics) { + BKE_ptcache_free_list(&psys->ptcaches); + psys->clmd->point_cache = psys->pointcache = NULL; + psys->clmd->ptcaches.first = psys->clmd->ptcaches.first = NULL; + + modifier_free((ModifierData*)psys->clmd); + + psys->clmd = NULL; + } + else { + cloth_free_modifier(ob, psys->clmd); + } } + + if(psys->hair_in_dm) + psys->hair_in_dm->release(psys->hair_in_dm); + psys->hair_in_dm = NULL; + + if(psys->hair_out_dm) + psys->hair_out_dm->release(psys->hair_out_dm); + psys->hair_out_dm = NULL; } void free_keyed_keys(ParticleSystem *psys) { - ParticleData *pa; - int i; + PARTICLE_P; + + if(psys->part->type == PART_HAIR) + return; if(psys->particles && psys->particles->keys) { MEM_freeN(psys->particles->keys); - for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) { + LOOP_PARTICLES { if(pa->keys) { pa->keys= NULL; pa->totkey= 0; @@ -407,13 +431,20 @@ void free_child_path_cache(ParticleSystem *psys) psys->childcache = NULL; psys->totchildcache = 0; } -void psys_free_path_cache(ParticleSystem *psys) +void psys_free_path_cache(ParticleSystem *psys, PTCacheEdit *edit) { - psys_free_path_cache_buffers(psys->pathcache, &psys->pathcachebufs); - psys->pathcache= NULL; - psys->totcached= 0; + if(edit) { + psys_free_path_cache_buffers(edit->pathcache, &edit->pathcachebufs); + edit->pathcache= NULL; + edit->totcached= 0; + } + if(psys) { + psys_free_path_cache_buffers(psys->pathcache, &psys->pathcachebufs); + psys->pathcache= NULL; + psys->totcached= 0; - free_child_path_cache(psys); + free_child_path_cache(psys); + } } void psys_free_children(ParticleSystem *psys) { @@ -425,6 +456,29 @@ void psys_free_children(ParticleSystem *psys) free_child_path_cache(psys); } +void psys_free_particles(ParticleSystem *psys) +{ + PARTICLE_P; + + if(psys->particles) { + if(psys->part->type==PART_HAIR) { + LOOP_PARTICLES { + if(pa->hair) + MEM_freeN(pa->hair); + } + } + + if(psys->particles->keys) + MEM_freeN(psys->particles->keys); + + if(psys->particles->boid) + MEM_freeN(psys->particles->boid); + + MEM_freeN(psys->particles); + psys->particles= NULL; + psys->totpart= 0; + } +} /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) { @@ -432,23 +486,14 @@ void psys_free(Object *ob, ParticleSystem * psys) int nr = 0; ParticleSystem * tpsys; - psys_free_path_cache(psys); + psys_free_path_cache(psys, NULL); - free_hair(psys, 1); + free_hair(ob, psys, 1); - free_keyed_keys(psys); + psys_free_particles(psys); if(psys->edit && psys->free_edit) - psys->free_edit(psys); - - if(psys->particles){ - if(psys->particles->boid) - MEM_freeN(psys->particles->boid); - - MEM_freeN(psys->particles); - psys->particles = 0; - psys->totpart = 0; - } + psys->free_edit(psys->edit); if(psys->child){ MEM_freeN(psys->child); @@ -479,14 +524,11 @@ void psys_free(Object *ob, ParticleSystem * psys) psys->part=0; } - if(psys->reactevents.first) - BLI_freelistN(&psys->reactevents); - BKE_ptcache_free_list(&psys->ptcaches); psys->pointcache = NULL; - if(psys->targets.first) - BLI_freelistN(&psys->targets); + BLI_freelistN(&psys->targets); + BLI_freelistN(&psys->reactevents); BLI_kdtree_free(psys->tree); @@ -646,7 +688,7 @@ void psys_render_restore(Object *ob, ParticleSystem *psys) psmd->dm->release(psmd->dm); } - psys_free_path_cache(psys); + psys_free_path_cache(psys, NULL); if(psys->child){ MEM_freeN(psys->child); @@ -930,7 +972,7 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic VecfCubicInterpol(keys[1].co, keys[1].vel, keys[2].co, keys[2].vel, dt, result->co, result->vel); } else { - set_four_ipo(dt, t, type); + key_curve_position_weights(dt, t, type); weighted_particle_vector(keys[0].co, keys[1].co, keys[2].co, keys[3].co, t, result->co); @@ -938,12 +980,12 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic float temp[3]; if(dt>0.999f){ - set_four_ipo(dt-0.001f, t, type); + key_curve_position_weights(dt-0.001f, t, type); weighted_particle_vector(keys[0].co, keys[1].co, keys[2].co, keys[3].co, t, temp); VECSUB(result->vel, result->co, temp); } else{ - set_four_ipo(dt+0.001f, t, type); + key_curve_position_weights(dt+0.001f, t, type); weighted_particle_vector(keys[0].co, keys[1].co, keys[2].co, keys[3].co, t, temp); VECSUB(result->vel, temp, result->co); } @@ -954,17 +996,25 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic typedef struct ParticleInterpolationData { - ParticleKey *kkey[2]; HairKey *hkey[2]; - BodyPoint *bp[2]; - SoftBody *soft; - int keyed, cached; + + DerivedMesh *dm; + MVert *mvert[2]; + + int keyed; + ParticleKey *kkey[2]; + + PointCache *cache; + + PTCacheEditPoint *epoint; + PTCacheEditKey *ekey[2]; + float birthtime, dietime; + int bspline; } ParticleInterpolationData; /* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */ -static void get_pointcache_keys_for_time(Object *ob, ParticleSystem *psys, int index, float t, ParticleKey *key1, ParticleKey *key2) +static void get_pointcache_keys_for_time(Object *ob, PointCache *cache, int index, float t, ParticleKey *key1, ParticleKey *key2) { - PointCache *cache = psys->pointcache; static PTCacheMem *pm = NULL; /* not thread safe */ if(index < 0) { /* initialize */ @@ -991,54 +1041,83 @@ static void get_pointcache_keys_for_time(Object *ob, ParticleSystem *psys, int i static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind) { - if(pind->keyed) { - pind->kkey[0] = pa->keys; + if(pind->epoint) { + PTCacheEditPoint *point = pind->epoint; - if(pa->totkey > 1) - pind->kkey[1] = pa->keys + 1; - else - pind->kkey[1] = NULL; + pind->ekey[0] = point->keys; + pind->ekey[1] = point->totkey > 1 ? point->keys + 1 : NULL; - pind->birthtime = pa->keys->time; - pind->dietime = (pa->keys + pa->totkey - 1)->time; + pind->birthtime = *(point->keys->time); + pind->dietime = *((point->keys + point->totkey - 1)->time); } - else if(pind->cached) { - get_pointcache_keys_for_time(ob, psys, -1, 0.0f, NULL, NULL); + else if(pind->keyed) { + ParticleKey *key = pa->keys; + pind->kkey[0] = key; + pind->kkey[1] = pa->totkey > 1 ? key + 1 : NULL; - pind->birthtime = pa->time; - pind->dietime = pa->dietime; + pind->birthtime = key->time; + pind->dietime = (key + pa->totkey - 1)->time; } - else { - pind->hkey[0] = pa->hair; - pind->hkey[1] = pa->hair + 1; + else if(pind->cache) { + get_pointcache_keys_for_time(ob, pind->cache, -1, 0.0f, NULL, NULL); - pind->birthtime = pa->hair->time; - pind->dietime = (pa->hair + pa->totkey - 1)->time; + pind->birthtime = pa ? pa->time : pind->cache->startframe; + pind->dietime = pa ? pa->dietime : pind->cache->endframe; } + else { + HairKey *key = pa->hair; + pind->hkey[0] = key; + pind->hkey[1] = key + 1; - if(pind->soft) { - pind->bp[0] = pind->soft->bpoint + pa->bpi; - pind->bp[1] = pind->soft->bpoint + pa->bpi + 1; + pind->birthtime = key->time; + pind->dietime = (key + pa->totkey - 1)->time; + + if(pind->dm) { + pind->mvert[0] = CDDM_get_vert(pind->dm, pa->hair_index); + pind->mvert[1] = pind->mvert[0] + 1; + } + } +} +static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey) +{ + VECCOPY(key->co, ekey->co); + if(ekey->vel) { + VECCOPY(key->vel, ekey->vel); } + key->time = *(ekey->time); } static void hair_to_particle(ParticleKey *key, HairKey *hkey) { VECCOPY(key->co, hkey->co); key->time = hkey->time; } -static void bp_to_particle(ParticleKey *key, BodyPoint *bp, HairKey *hkey) + +static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey) { - VECCOPY(key->co, bp->pos); + VECCOPY(key->co, mvert->co); key->time = hkey->time; } static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, float frs_sec, ParticleInterpolationData *pind, ParticleKey *result) { + PTCacheEditPoint *point = pind->epoint; ParticleKey keys[4]; + int point_vel = (point && point->keys->vel); float real_t, dfra, keytime; /* interpret timing and find keys */ - if(pind->keyed) { + if(point) { + if(result->time < 0.0f) + real_t = -result->time; + else + real_t = *(pind->ekey[0]->time) + t * (*(pind->ekey[0][point->totkey-1].time) - *(pind->ekey[0]->time)); + + while(*(pind->ekey[1]->time) < real_t) + pind->ekey[1]++; + + pind->ekey[0] = pind->ekey[1] - 1; + } + else if(pind->keyed) { /* we have only one key, so let's use that */ if(pind->kkey[1]==NULL) { copy_particle_key(result, pind->kkey[0], 1); @@ -1075,7 +1154,7 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData pind->kkey[0] = pind->kkey[1] - 1; } - else if(pind->cached) { + else if(pind->cache) { if(result->time < 0.0f) /* flag for time in frames */ real_t = -result->time; else @@ -1089,24 +1168,28 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData while(pind->hkey[1]->time < real_t) { pind->hkey[1]++; - pind->bp[1]++; + pind->mvert[1]++; } pind->hkey[0] = pind->hkey[1] - 1; } /* set actual interpolation keys */ - if(pind->soft) { - pind->bp[0] = pind->bp[1] - 1; - bp_to_particle(keys + 1, pind->bp[0], pind->hkey[0]); - bp_to_particle(keys + 2, pind->bp[1], pind->hkey[1]); + if(point) { + edit_to_particle(keys + 1, pind->ekey[0]); + edit_to_particle(keys + 2, pind->ekey[1]); + } + else if(pind->dm) { + pind->mvert[0] = pind->mvert[1] - 1; + mvert_to_particle(keys + 1, pind->mvert[0], pind->hkey[0]); + mvert_to_particle(keys + 2, pind->mvert[1], pind->hkey[1]); } else if(pind->keyed) { memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey)); memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey)); } - else if(pind->cached) { - get_pointcache_keys_for_time(NULL, psys, p, real_t, keys+1, keys+2); + else if(pind->cache) { + get_pointcache_keys_for_time(NULL, pind->cache, p, real_t, keys+1, keys+2); } else { hair_to_particle(keys + 1, pind->hkey[0]); @@ -1114,12 +1197,18 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData } /* set secondary interpolation keys for hair */ - if(!pind->keyed && !pind->cached) { - if(pind->soft) { + if(!pind->keyed && !pind->cache && !point_vel) { + if(point) { + if(pind->ekey[0] != point->keys) + edit_to_particle(keys, pind->ekey[0] - 1); + else + edit_to_particle(keys, pind->ekey[0]); + } + else if(pind->dm) { if(pind->hkey[0] != pa->hair) - bp_to_particle(keys, pind->bp[0] - 1, pind->hkey[0] - 1); + mvert_to_particle(keys, pind->mvert[0] - 1, pind->hkey[0] - 1); else - bp_to_particle(keys, pind->bp[0], pind->hkey[0]); + mvert_to_particle(keys, pind->mvert[0], pind->hkey[0]); } else { if(pind->hkey[0] != pa->hair) @@ -1128,11 +1217,17 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData hair_to_particle(keys, pind->hkey[0]); } - if(pind->soft) { + if(point) { + if(pind->ekey[1] != point->keys + point->totkey - 1) + edit_to_particle(keys + 3, pind->ekey[1] + 1); + else + edit_to_particle(keys + 3, pind->ekey[1]); + } + else if(pind->dm) { if(pind->hkey[1] != pa->hair + pa->totkey - 1) - bp_to_particle(keys + 3, pind->bp[1] + 1, pind->hkey[1] + 1); + mvert_to_particle(keys + 3, pind->mvert[1] + 1, pind->hkey[1] + 1); else - bp_to_particle(keys + 3, pind->bp[1], pind->hkey[1]); + mvert_to_particle(keys + 3, pind->mvert[1], pind->hkey[1]); } else { if(pind->hkey[1] != pa->hair + pa->totkey - 1) @@ -1146,19 +1241,19 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData keytime = (real_t - keys[1].time) / dfra; /* convert velocity to timestep size */ - if(pind->keyed || pind->cached){ + if(pind->keyed || pind->cache || point_vel){ VecMulf(keys[1].vel, dfra / frs_sec); VecMulf(keys[2].vel, dfra / frs_sec); QuatInterpol(result->rot,keys[1].rot,keys[2].rot,keytime); } /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/ - psys_interpolate_particle((pind->keyed || pind->cached) ? -1 /* signal for cubic interpolation */ - : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) + psys_interpolate_particle((pind->keyed || pind->cache || point_vel) ? -1 /* signal for cubic interpolation */ + : (pind->bspline ? KEY_BSPLINE : KEY_CARDINAL) ,keys, keytime, result, 1); /* the velocity needs to be converted back from cubic interpolation */ - if(pind->keyed || pind->cached) + if(pind->keyed || pind->cache || point_vel) VecMulf(result->vel, frs_sec / dfra); } /************************************************/ @@ -1611,7 +1706,7 @@ ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys) } } } - return 0; + return NULL; } /************************************************/ /* Particles on a shape */ @@ -1838,7 +1933,7 @@ int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase ParticleKey key, par; float effect[3]={0.0,0.0,0.0}, distance, f_force, mindist, totforce=0.0; - float guidevec[4], guidedir[3], rot2[4], temp[3], angle, pa_loc[3], pa_zero[3]={0.0f,0.0f,0.0f}; + float guidevec[4], guidedir[3], rot2[4], radius, temp[3], angle, pa_loc[3], pa_zero[3]={0.0f,0.0f,0.0f}; float veffect[3]={0.0,0.0,0.0}, guidetime; effect[0]=effect[1]=effect[2]=0.0; @@ -1881,9 +1976,9 @@ int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase } if(pd->flag & PFIELD_GUIDE_PATH_ADD) - where_on_path(eob, f_force*guidetime, guidevec, guidedir); + where_on_path(eob, f_force*guidetime, guidevec, guidedir, NULL, &radius); else - where_on_path(eob, guidetime, guidevec, guidedir); + where_on_path(eob, guidetime, guidevec, guidedir, NULL, &radius); Mat4MulVecfl(ec->ob->obmat,guidevec); Mat4Mul3Vecfl(ec->ob->obmat,guidedir); @@ -1913,10 +2008,12 @@ int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase /* curve taper */ if(cu->taperobj) VecMulf(pa_loc, calc_taper(scene, cu->taperobj, (int)(f_force*guidetime*100.0), 100)); - /* TODO */ - //else{ - ///* curve size*/ - //} + + else{ /* curve size*/ + if(cu->flag & CU_PATH_RADIUS) { + VecMulf(pa_loc, radius); + } + } par.co[0]=par.co[1]=par.co[2]=0.0f; VECCOPY(key.co,pa_loc); do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0); @@ -2038,7 +2135,11 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup) { float *vg=0; - if(psys->vgroup[vgroup]){ + if(vgroup < 0) { + /* hair dynamics pinning vgroup */ + + } + else if(psys->vgroup[vgroup]){ MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); if(dvert){ int totvert=dm->getNumVerts(dm), i; @@ -2130,7 +2231,7 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in /*---start figuring out what is actually wanted---*/ if(psys_in_edit_mode(scene, psys)) - if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0) + if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0) totchild=0; if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ @@ -2246,7 +2347,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, needupdate= 0; w= 0; while(w<4 && cpa->pa[w]>=0) { - if(psys->particles[cpa->pa[w]].flag & PARS_EDIT_RECALC) { + if(psys->edit->points[cpa->pa[w]].flag & PEP_EDIT_RECALC) { needupdate= 1; break; } @@ -2289,7 +2390,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, } else{ if(ctx->editupdate && !(part->flag & PART_BRANCHING)) { - if(!(psys->particles[cpa->parent].flag & PARS_EDIT_RECALC)) + if(!(psys->edit->points[cpa->parent].flag & PEP_EDIT_RECALC)) return; memset(keys, 0, sizeof(*keys)*(ctx->steps+1)); @@ -2502,6 +2603,9 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa ListBase threads; int i, totchild, totparent, totthread; + if(psys->flag & PSYS_GLOBAL_HAIR) + return; + pthreads= psys_threads_create(scene, ob, psys); if(!psys_threads_init_path(pthreads, scene, cfra, editupdate)) { @@ -2558,158 +2662,111 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ /* -Cached path data is also used to determine cut position for the editmode tool. */ -void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate) +void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra) { - ParticleCacheKey *ca, **cache=psys->pathcache; + ParticleCacheKey *ca, **cache= psys->pathcache; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - ParticleEditSettings *pset = &scene->toolsettings->particle; ParticleSettings *part = psys->part; + ParticleEditSettings *pset = &scene->toolsettings->particle; + + DerivedMesh *hair_dm = psys->hair_out_dm; - ParticleData *pa; + ParticleData *pa = psys->particles; ParticleKey result; - - ParticleEdit *edit = 0; - ParticleEditKey *ekey = 0; - - SoftBody *soft = 0; - BodyPoint *bp[2] = {NULL, NULL}; Material *ma; - ParticleInterpolationData pind; float birthtime = 0.0, dietime = 0.0; - float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; + float t, time = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}; float prev_tangent[3], hairmat[4][4]; float rotmat[3][3]; int k,i; - int steps = (int)pow(2.0, (double)psys->part->draw_step); + int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step)); int totpart = psys->totpart; - float sel_col[3]; - float nosel_col[3]; float length, vec[3]; float *vg_effector= NULL, effector=0.0f; float *vg_length= NULL, pa_length=1.0f; int keyed, baked; /* 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 && (psys->pointcache->flag & PTCACHE_BAKED)==0) + if((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) return; + if(psys_in_edit_mode(scene, psys)) + if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0) + return; + BLI_srandom(psys->seed); keyed = psys->flag & PSYS_KEYED; - baked = psys->pointcache->flag & PTCACHE_BAKED; + baked = !hair_dm && psys->pointcache->flag & PTCACHE_BAKED; - if(psys->renderdata) { - steps = (int)pow(2.0, (double)psys->part->ren_step); - } - else if(psys_in_edit_mode(scene, psys)) { - edit=psys->edit; - - //timed = edit->draw_timed; - - if(pset->brushtype == PE_BRUSH_WEIGHT) { - sel_col[0] = sel_col[1] = sel_col[2] = 1.0f; - nosel_col[0] = nosel_col[1] = nosel_col[2] = 0.0f; - } - else{ - sel_col[0] = (float)edit->sel_col[0] / 255.0f; - sel_col[1] = (float)edit->sel_col[1] / 255.0f; - sel_col[2] = (float)edit->sel_col[2] / 255.0f; - nosel_col[0] = (float)edit->nosel_col[0] / 255.0f; - nosel_col[1] = (float)edit->nosel_col[1] / 255.0f; - nosel_col[2] = (float)edit->nosel_col[2] / 255.0f; - } - } + /* clear out old and create new empty path cache */ + psys_free_path_cache(psys, psys->edit); + cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1); - if(editupdate && psys->pathcache && totpart == psys->totcached) { - cache = psys->pathcache; - } - else { - /* clear out old and create new empty path cache */ - psys_free_path_cache(psys); - cache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1); - psys->pathcache= cache; - } - - if(edit==NULL && psys->soft && psys->softflag & OB_SB_ENABLE) { - soft = psys->soft; - if(!soft->bpoint) - soft= NULL; - } - psys->lattice = psys_get_lattice(scene, ob, psys); 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) { + + if(psys->part->from!=PART_FROM_PARTICLE && !(psys->flag & PSYS_GLOBAL_HAIR)) { if(!(psys->part->flag & PART_CHILD_EFFECT)) vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR); - if(!edit && !psys->totchild) + if(!psys->totchild) vg_length = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_LENGTH); } /*---first main loop: create all actual particles' paths---*/ - for(i=0,pa=psys->particles; i<totpart; i++, pa++){ - if(psys && edit==NULL && (pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST)) { - if(soft) - bp[0] += pa->totkey; /* TODO use of initialized value? */ + for(i=0; i<totpart; i++, pa++){ + if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue; - } - if(editupdate && !(pa->flag & PARS_EDIT_RECALC)) continue; - else memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); - - if(!edit && !psys->totchild) { - pa_length = 1.0f - part->randlength * 0.5 * (1.0f + pa->r_ave[0]); + if(!psys->totchild) { + BLI_srandom(psys->seed + i); + pa_length = 1.0f - part->randlength * BLI_frand(); if(vg_length) pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); } - cache[i]->steps = steps; + pind.keyed = keyed; + pind.cache = baked ? psys->pointcache : NULL; + pind.epoint = NULL; + pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE); + pind.dm = hair_dm; + + memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); - if(edit) - ekey = edit->keys[i]; + cache[i]->steps = steps; /*--get the first data points--*/ - pind.keyed = keyed; - pind.cached = baked; - pind.soft = soft; init_particle_interpolation(ob, psys, pa, &pind); - /* hairmat is needed for for non-hair particle too so we get proper rotations */ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); VECCOPY(rotmat[0], hairmat[2]); VECCOPY(rotmat[1], hairmat[1]); VECCOPY(rotmat[2], hairmat[0]); - if(!edit) { - if(part->draw & PART_ABS_PATH_TIME) { - birthtime = MAX2(pind.birthtime, part->path_start); - dietime = MIN2(pind.dietime, part->path_end); - } - else { - float tb = pind.birthtime; - birthtime = tb + part->path_start * (pind.dietime - tb); - dietime = tb + part->path_end * (pind.dietime - tb); - } - - if(birthtime >= dietime) { - cache[i]->steps = -1; - continue; - } + if(part->draw & PART_ABS_PATH_TIME) { + birthtime = MAX2(pind.birthtime, part->path_start); + dietime = MIN2(pind.dietime, part->path_end); + } + else { + float tb = pind.birthtime; + birthtime = tb + part->path_start * (pind.dietime - tb); + dietime = tb + part->path_end * (pind.dietime - tb); + } - dietime = birthtime + pa_length * (dietime - birthtime); + if(birthtime >= dietime) { + cache[i]->steps = -1; + continue; } - else - /* XXX brecht: don't know if this code from 2.4 is correct - * still, but makes hair appear again in particle mode */ - dietime= pind.hkey[0][pa->totkey-1].time; + + dietime = birthtime + pa_length * (dietime - birthtime); /*--interpolate actual path from data points--*/ for(k=0, ca=cache[i]; k<=steps; k++, ca++){ @@ -2721,46 +2778,16 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); - /* keyed, baked and softbody are allready in global space */ - if(!keyed && !baked && !soft) { + /* dynamic hair is in object space */ + /* keyed and baked are allready in global space */ + if(hair_dm) + Mat4MulVecfl(ob->obmat, result.co); + else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) Mat4MulVecfl(hairmat, result.co); - } VECCOPY(ca->co, result.co); - - /* selection coloring in edit mode */ - if(edit){ - if(pset->brushtype==PE_BRUSH_WEIGHT){ - if(k==steps) - VecLerpf(ca->col, nosel_col, sel_col, pind.hkey[0]->weight); - else - VecLerpf(ca->col, nosel_col, sel_col, - (1.0f - keytime) * pind.hkey[0]->weight + keytime * pind.hkey[1]->weight); - } - else{ - if((ekey + (pind.hkey[0] - pa->hair))->flag & PEK_SELECT){ - if((ekey + (pind.hkey[1] - pa->hair))->flag & PEK_SELECT){ - VECCOPY(ca->col, sel_col); - } - else{ - VecLerpf(ca->col, sel_col, nosel_col, keytime); - } - } - else{ - if((ekey + (pind.hkey[1] - pa->hair))->flag & PEK_SELECT){ - VecLerpf(ca->col, nosel_col, sel_col, keytime); - } - else{ - VECCOPY(ca->col, nosel_col); - } - } - } - } - else{ - VECCOPY(ca->col, col); - } + VECCOPY(ca->col, col); } - /*--modify paths and calculate rotation & velocity--*/ @@ -2772,64 +2799,66 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra effector*= psys_particle_value_from_verts(psmd->dm,psys->part->from,pa,vg_effector); for(k=0, ca=cache[i]; k<=steps; k++, ca++) { + if(!(psys->flag & PSYS_GLOBAL_HAIR)) { /* apply effectors */ - if(!(psys->part->flag & PART_CHILD_EFFECT) && edit==0 && k) - do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); + if(!(psys->part->flag & PART_CHILD_EFFECT) && k) + do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); - /* apply guide curves to path data */ - if(edit==0 && psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) - /* ca is safe to cast, since only co and vel are used */ - do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); + /* apply guide curves to path data */ + if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) + /* ca is safe to cast, since only co and vel are used */ + do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); - /* apply lattice */ - if(psys->lattice && edit==0) - calc_latt_deform(psys->lattice, ca->co, 1.0f); + /* apply lattice */ + if(psys->lattice) + calc_latt_deform(psys->lattice, ca->co, 1.0f); - /* figure out rotation */ - - if(k) { - float cosangle, angle, tangent[3], normal[3], q[4]; - - if(k == 1) { - /* calculate initial tangent for incremental rotations */ - VECSUB(tangent, ca->co, (ca - 1)->co); - VECCOPY(prev_tangent, tangent); - Normalize(prev_tangent); - - /* First rotation is based on emitting face orientation. */ - /* This is way better than having flipping rotations resulting */ - /* from using a global axis as a rotation pole (vec_to_quat()). */ - /* It's not an ideal solution though since it disregards the */ - /* initial tangent, but taking that in to account will allow */ - /* the possibility of flipping again. -jahka */ - Mat3ToQuat_is_ok(rotmat, (ca-1)->rot); - } - else { - VECSUB(tangent, ca->co, (ca - 1)->co); - Normalize(tangent); - - cosangle= Inpf(tangent, prev_tangent); - - /* note we do the comparison on cosangle instead of - * angle, since floating point accuracy makes it give - * different results across platforms */ - if(cosangle > 0.999999f) { - QUATCOPY((ca - 1)->rot, (ca - 2)->rot); + /* figure out rotation */ + + if(k) { + float cosangle, angle, tangent[3], normal[3], q[4]; + + if(k == 1) { + /* calculate initial tangent for incremental rotations */ + VECSUB(tangent, ca->co, (ca - 1)->co); + VECCOPY(prev_tangent, tangent); + Normalize(prev_tangent); + + /* First rotation is based on emitting face orientation. */ + /* This is way better than having flipping rotations resulting */ + /* from using a global axis as a rotation pole (vec_to_quat()). */ + /* It's not an ideal solution though since it disregards the */ + /* initial tangent, but taking that in to account will allow */ + /* the possibility of flipping again. -jahka */ + Mat3ToQuat_is_ok(rotmat, (ca-1)->rot); } else { - angle= saacos(cosangle); - Crossf(normal, prev_tangent, tangent); - VecRotToQuat(normal, angle, q); - QuatMul((ca - 1)->rot, q, (ca - 2)->rot); + VECSUB(tangent, ca->co, (ca - 1)->co); + Normalize(tangent); + + cosangle= Inpf(tangent, prev_tangent); + + /* note we do the comparison on cosangle instead of + * angle, since floating point accuracy makes it give + * different results across platforms */ + if(cosangle > 0.999999f) { + QUATCOPY((ca - 1)->rot, (ca - 2)->rot); + } + else { + angle= saacos(cosangle); + Crossf(normal, prev_tangent, tangent); + VecRotToQuat(normal, angle, q); + QuatMul((ca - 1)->rot, q, (ca - 2)->rot); + } + + VECCOPY(prev_tangent, tangent); } - VECCOPY(prev_tangent, tangent); + if(k == steps) + QUATCOPY(ca->rot, (ca - 1)->rot); } - if(k == steps) - QUATCOPY(ca->rot, (ca - 1)->rot); } - /* set velocity */ @@ -2857,6 +2886,123 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra if(vg_length) MEM_freeN(vg_length); } +void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cfra) +{ + ParticleCacheKey *ca, **cache= edit->pathcache; + ParticleEditSettings *pset = &scene->toolsettings->particle; + + PTCacheEditPoint *point = edit->points; + PTCacheEditKey *ekey = NULL; + + ParticleSystem *psys = edit->psys; + ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + ParticleData *pa = psys ? psys->particles : NULL; + + ParticleInterpolationData pind; + ParticleKey result; + + float birthtime = 0.0, dietime = 0.0; + float t, time = 0.0, keytime = 0.0, frs_sec; + float hairmat[4][4]; + int k,i; + int steps = (int)pow(2.0, (double)pset->draw_step); + int totpart = edit->totpoint; + float sel_col[3]; + float nosel_col[3]; + + steps = MAX2(steps, 4); + + if(!cache || edit->totpoint != edit->totcached) { + /* clear out old and create new empty path cache */ + psys_free_path_cache(edit->psys, edit); + cache= edit->pathcache= psys_alloc_path_cache_buffers(&edit->pathcachebufs, totpart, steps+1); + } + + frs_sec = (psys || edit->pid.flag & PTCACHE_VEL_PER_SEC) ? 25.0f : 1.0f; + + sel_col[0] = (float)edit->sel_col[0] / 255.0f; + sel_col[1] = (float)edit->sel_col[1] / 255.0f; + sel_col[2] = (float)edit->sel_col[2] / 255.0f; + nosel_col[0] = (float)edit->nosel_col[0] / 255.0f; + nosel_col[1] = (float)edit->nosel_col[1] / 255.0f; + nosel_col[2] = (float)edit->nosel_col[2] / 255.0f; + + /*---first main loop: create all actual particles' paths---*/ + for(i=0; i<totpart; i++, pa+=pa?1:0, point++){ + if(edit->totcached && !(point->flag & PEP_EDIT_RECALC)) + continue; + + ekey = point->keys; + + pind.keyed = 0; + pind.cache = NULL; + pind.epoint = point; + pind.bspline = psys ? (psys->part->flag & PART_HAIR_BSPLINE) : 0; + pind.dm = NULL; + + memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); + + cache[i]->steps = steps; + + /*--get the first data points--*/ + init_particle_interpolation(ob, psys, pa, &pind); + + if(psys) + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + + birthtime = pind.birthtime; + dietime = pind.dietime; + + if(birthtime >= dietime) { + cache[i]->steps = -1; + continue; + } + + /*--interpolate actual path from data points--*/ + for(k=0, ca=cache[i]; k<=steps; k++, ca++){ + time = (float)k / (float)steps; + + t = birthtime + time * (dietime - birthtime); + + result.time = -t; + + do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); + + /* non-hair points are allready in global space */ + if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) + Mat4MulVecfl(hairmat, result.co); + + VECCOPY(ca->co, result.co); + + ca->vel[0] = ca->vel[1] = 0.0f; + ca->vel[1] = 1.0f; + + /* selection coloring in edit mode */ + if((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT){ + if((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT){ + VECCOPY(ca->col, sel_col); + } + else{ + keytime = (t - (*pind.ekey[0]->time))/((*pind.ekey[1]->time) - (*pind.ekey[0]->time)); + VecLerpf(ca->col, sel_col, nosel_col, keytime); + } + } + else{ + if((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT){ + keytime = (t - (*pind.ekey[0]->time))/((*pind.ekey[1]->time) - (*pind.ekey[0]->time)); + VecLerpf(ca->col, nosel_col, sel_col, keytime); + } + else{ + VECCOPY(ca->col, nosel_col); + } + } + + ca->time = t; + } + } + + edit->totcached = totpart; +} /************************************************/ /* Particle Key handling */ /************************************************/ @@ -3057,7 +3203,7 @@ void object_add_particle_system(Scene *scene, Object *ob) psys->cfra=bsystem_time(scene,ob,scene->r.cfra+1,0.0); DAG_scene_sort(scene); - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } void object_remove_particle_system(Scene *scene, Object *ob) { @@ -3080,7 +3226,7 @@ void object_remove_particle_system(Scene *scene, Object *ob) ((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT; DAG_scene_sort(scene); - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } static void default_particle_settings(ParticleSettings *part) { @@ -3260,7 +3406,7 @@ void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int reca } } if(flush) - DAG_object_flush_update(scene, base->object, OB_RECALC_DATA); + DAG_id_flush_update(&base->object->id, OB_RECALC_DATA); } } @@ -3292,7 +3438,7 @@ LinkNode *psys_using_settings(struct Scene *scene, ParticleSettings *part, int f } if(flush_update && found) - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } return node; @@ -3471,6 +3617,8 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, { ParticleTexture ptex; float size=1.0f; + + BLI_srandom(psys->seed + (pa - psys->particles) + 100); if(ma && part->from!=PART_FROM_PARTICLE){ ptex.size=size; @@ -3489,7 +3637,7 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, size*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_size); if(part->randsize!=0.0) - size*= 1.0f - part->randsize*pa->sizemul; + size*= 1.0f - part->randsize * BLI_frand(); return size*part->size; } @@ -3656,16 +3804,10 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i if(p<totpart){ pa = psys->particles + p; - - if(pa->alive==PARS_DEAD && part->flag & PART_STICKY && pa->flag & PARS_STICKY && pa->stick_ob){ - copy_particle_key(state,&pa->state,0); - key_from_object(pa->stick_ob,state); - return; - } - pind.keyed = keyed; - pind.cached = cached; - pind.soft = NULL; + pind.cache = cached ? psys->pointcache : NULL; + pind.epoint = NULL; + pind.dm = psys->hair_out_dm; init_particle_interpolation(ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state); @@ -3877,20 +4019,11 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy return 0; /* currently not supported */ else if(psys->totchild && p>=psys->totpart){ ChildParticle *cpa=psys->child+p-psys->totpart; - ParticleKey *key1, skey; + ParticleKey *key1; float t = (cfra - pa->time + pa->loop * pa->lifetime) / pa->lifetime; pa = psys->particles + cpa->parent; - - if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob) { - key1 = &skey; - copy_particle_key(key1,&pa->state,0); - key_from_object(pa->stick_ob,key1); - } - else { - key1=&pa->state; - } - + key1=&pa->state; offset_child(cpa, key1, state, part->childflat, part->childrad); CLAMP(t,0.0,1.0); @@ -3947,10 +4080,6 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy } } - if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob){ - key_from_object(pa->stick_ob,state); - } - if(psys->lattice) calc_latt_deform(psys->lattice, state->co,1.0f); } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 8db4656239b..663d5c6ee03 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -73,7 +73,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_object.h" #include "BKE_material.h" -#include "BKE_softbody.h" +#include "BKE_cloth.h" #include "BKE_depsgraph.h" #include "BKE_lattice.h" #include "BKE_pointcache.h" @@ -123,21 +123,11 @@ static int get_current_display_percentage(ParticleSystem *psys) void psys_reset(ParticleSystem *psys, int mode) { ParticleSettings *part= psys->part; - ParticleData *pa; - int i; + PARTICLE_P; if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { - if(mode == PSYS_RESET_ALL || !(part->type == PART_HAIR && (psys->flag & PSYS_EDITED))) { - if(psys->particles) { - if(psys->particles->keys) - MEM_freeN(psys->particles->keys); - - for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) - if(pa->hair) MEM_freeN(pa->hair); - - MEM_freeN(psys->particles); - psys->particles= NULL; - } + if(mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) { + psys_free_particles(psys); psys->totpart= 0; psys->totkeyed= 0; @@ -145,14 +135,17 @@ void psys_reset(ParticleSystem *psys, int mode) if(psys->reactevents.first) BLI_freelistN(&psys->reactevents); + + if(psys->edit && psys->free_edit) { + psys->free_edit(psys->edit); + psys->edit = NULL; + psys->free_edit = NULL; + } } } else if(mode == PSYS_RESET_CACHE_MISS) { /* set all particles to be skipped */ - ParticleData *pa = psys->particles; - int p=0; - - for(; p<psys->totpart; p++, pa++) + LOOP_PARTICLES pa->flag |= PARS_NO_DISP; } @@ -165,7 +158,7 @@ void psys_reset(ParticleSystem *psys, int mode) psys->totchild= 0; /* reset path cache */ - psys_free_path_cache(psys); + psys_free_path_cache(psys, psys->edit); /* reset point cache */ psys->pointcache->flag &= ~PTCACHE_SIMULATION_VALID; @@ -174,9 +167,10 @@ void psys_reset(ParticleSystem *psys, int mode) static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) { - ParticleData *newpars = 0, *pa; - BoidData *newboids = 0; - int i, totpart, totsaved = 0; + ParticleData *newpars = NULL; + BoidParticle *newboids = NULL; + PARTICLE_P; + int totpart, totsaved = 0; if(new_totpart<0) { if(psys->part->distr==PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) { @@ -189,47 +183,46 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) else totpart=new_totpart; - if(totpart) { + if(totpart && totpart != psys->totpart) { newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); + + if(psys->particles) { + totsaved=MIN2(psys->totpart,totpart); + /*save old pars*/ + if(totsaved) { + memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData)); + + if(psys->particles->boid) + memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidParticle)); + } - if(psys->part->phystype == PART_PHYS_BOIDS) - newboids = MEM_callocN(totpart*sizeof(BoidData), "Boid Data"); - } - if(psys->particles) { - totsaved=MIN2(psys->totpart,totpart); - /*save old pars*/ - if(totsaved) { - memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData)); - - if(newboids) - memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidData)); - } - - if(psys->particles->keys) - MEM_freeN(psys->particles->keys); + if(psys->particles->keys) + MEM_freeN(psys->particles->keys); - if(psys->particles->boid) - MEM_freeN(psys->particles->boid); + if(psys->particles->boid) + MEM_freeN(psys->particles->boid); - for(i=0, pa=newpars; i<totsaved; i++, pa++) { - if(pa->keys) { - pa->keys= NULL; - pa->totkey= 0; + for(p=0, pa=newpars; p<totsaved; p++, pa++) { + if(pa->keys) { + pa->keys= NULL; + pa->totkey= 0; + } } - } - for(i=totsaved, pa=psys->particles+totsaved; i<psys->totpart; i++, pa++) - if(pa->hair) MEM_freeN(pa->hair); + for(p=totsaved, pa=psys->particles+totsaved; p<psys->totpart; p++, pa++) + if(pa->hair) MEM_freeN(pa->hair); - MEM_freeN(psys->particles); - } - psys->particles=newpars; + MEM_freeN(psys->particles); + } + + psys->particles=newpars; - if(newboids) { - pa = psys->particles; - pa->boid = newboids; - for(i=1, pa++; i<totpart; i++,pa++) - pa->boid = (pa-1)->boid + 1; + if(newboids) { + LOOP_PARTICLES + pa->boid = newboids++; + } + + psys->totpart=totpart; } if(psys->child) { @@ -237,8 +230,6 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) psys->child=0; psys->totchild=0; } - - psys->totpart=totpart; } static int get_psys_child_number(struct Scene *scene, ParticleSystem *psys) @@ -285,8 +276,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) each original elements can reference its derived elements */ Mesh *me= (Mesh*)ob->data; - ParticleData *pa= 0; - int p; + PARTICLE_P; /* CACHE LOCATIONS */ if(!dm->deformedOnly) { @@ -323,7 +313,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) } /* cache the verts/faces! */ - for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++) { + LOOP_PARTICLES { if(psys->part->from == PART_FROM_VERT) { if(nodearray[pa->num]) pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link); @@ -343,7 +333,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) * should know to use the num or num_dmcache, set the num_dmcache to * an invalid value, just incase */ - for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++) + LOOP_PARTICLES pa->num_dmcache = -1; } } @@ -1443,12 +1433,11 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Objec /* ready for future use, to emit particles without geometry */ static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int from) { - ParticleData *pa; - int totpart=psys->totpart, p; + PARTICLE_P; fprintf(stderr,"Shape emission not yet possible!\n"); - for(p=0,pa=psys->particles; p<totpart; p++,pa++){ + LOOP_PARTICLES { pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0; pa->foffset= 0.0f; pa->num= -1; @@ -1470,12 +1459,11 @@ static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, distribute_particles_on_shape(ob,psys,from); if(distr_error){ - ParticleData *pa; - int totpart=psys->totpart, p; + PARTICLE_P; fprintf(stderr,"Particle distribution error!\n"); - for(p=0,pa=psys->particles; p<totpart; p++,pa++){ + LOOP_PARTICLES { pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0; pa->foffset= 0.0f; pa->num= -1; @@ -1570,7 +1558,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps Material *ma=0; //IpoCurve *icu=0; // XXX old animation system int totpart; - float rand,length; + float rand; part=psys->part; @@ -1625,40 +1613,8 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps pa->dietime= pa->time+pa->lifetime; - pa->sizemul= BLI_frand(); - - rand= BLI_frand(); - - /* while loops are to have a spherical distribution (avoid cubic distribution) */ - if(part->phystype != PART_PHYS_BOIDS) { - /* boids store gravity in r_ve, so skip here */ - length=2.0f; - while(length>1.0){ - pa->r_ve[0]=2.0f*(BLI_frand()-0.5f); - pa->r_ve[1]=2.0f*(BLI_frand()-0.5f); - pa->r_ve[2]=2.0f*(BLI_frand()-0.5f); - length=VecLength(pa->r_ve); - } - } - - length=2.0f; - while(length>1.0){ - pa->r_ave[0]=2.0f*(BLI_frand()-0.5f); - pa->r_ave[1]=2.0f*(BLI_frand()-0.5f); - pa->r_ave[2]=2.0f*(BLI_frand()-0.5f); - length=VecLength(pa->r_ave); - } - - pa->r_rot[0]=2.0f*(BLI_frand()-0.5f); - pa->r_rot[1]=2.0f*(BLI_frand()-0.5f); - pa->r_rot[2]=2.0f*(BLI_frand()-0.5f); - pa->r_rot[3]=2.0f*(BLI_frand()-0.5f); - - NormalQuat(pa->r_rot); - if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){ - /* any unique random number will do (r_ave[0]) */ - if(ptex.exist < 0.5*(1.0+pa->r_ave[0])) + if(ptex.exist < BLI_frand()) pa->flag |= PARS_UNEXIST; else pa->flag &= ~PARS_UNEXIST; @@ -1672,10 +1628,9 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) { //IpoCurve *icu=0; // XXX old animation system - ParticleData *pa; - int p, totpart=psys->totpart; + PARTICLE_P; - for(p=0, pa=psys->particles; p<totpart; p++, pa++) + LOOP_PARTICLES initialize_particle(pa,p,ob,psys,psmd); if(psys->part->type != PART_FLUID) { @@ -1743,10 +1698,39 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; - float q_phase[4]; + float q_phase[4], length, r_phase; part=psys->part; ptex.ivel=1.0; + + BLI_srandom(psys->seed + (pa - psys->particles)); + + /* we need to get every random even if they're not used so that they don't effect eachother */ + /* while loops are to have a spherical distribution (avoid cubic distribution) */ + length=2.0f; + while(length>1.0){ + r_vel[0]=2.0f*(BLI_frand()-0.5f); + r_vel[1]=2.0f*(BLI_frand()-0.5f); + r_vel[2]=2.0f*(BLI_frand()-0.5f); + length=VecLength(r_vel); + } + + length=2.0f; + while(length>1.0){ + r_ave[0]=2.0f*(BLI_frand()-0.5f); + r_ave[1]=2.0f*(BLI_frand()-0.5f); + r_ave[2]=2.0f*(BLI_frand()-0.5f); + length=VecLength(r_ave); + } + + r_rot[0]=2.0f*(BLI_frand()-0.5f); + r_rot[1]=2.0f*(BLI_frand()-0.5f); + r_rot[2]=2.0f*(BLI_frand()-0.5f); + r_rot[3]=2.0f*(BLI_frand()-0.5f); + + NormalQuat(r_rot); + + r_phase = BLI_frand(); if(part->from==PART_FROM_PARTICLE){ Object *tob; @@ -1757,29 +1741,26 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic if(tob==0) tob=ob; - tpsys=BLI_findlink(&tob->particlesystem,psys->target_psys-1); + tpsys=BLI_findlink(&tob->particlesystem, psys->target_psys-1); state.time = pa->time; if(pa->num == -1) memset(&state, 0, sizeof(state)); else psys_get_particle_state(scene, tob,tpsys,pa->num,&state,1); - psys_get_from_key(&state,loc,nor,rot,0); + psys_get_from_key(&state, loc, nor, rot, 0); - QuatMulVecf(rot,vtan); - QuatMulVecf(rot,utan); - VECCOPY(r_vel,pa->r_ve); - VECCOPY(r_rot,pa->r_rot); - VECCOPY(r_ave,pa->r_ave); + QuatMulVecf(rot, vtan); + QuatMulVecf(rot, utan); - VECCOPY(p_vel,state.vel); + VECCOPY(p_vel, state.vel); speed=Normalize(p_vel); - VecMulf(p_vel,Inpf(pa->r_ve,p_vel)); - VECSUB(p_vel,pa->r_ve,p_vel); + VecMulf(p_vel, Inpf(r_vel, p_vel)); + VECSUB(p_vel, r_vel, p_vel); Normalize(p_vel); - VecMulf(p_vel,speed); + VecMulf(p_vel, speed); - VECCOPY(pa->fuv,loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */ + VECCOPY(pa->fuv, loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */ } else{ /* get precise emitter matrix if particle is born */ @@ -1833,29 +1814,25 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic /* -velocity */ if(part->randfac!=0.0){ - VECADD(r_vel,tloc,pa->r_ve); - Mat4MulVecfl(ob->obmat,r_vel); - VECSUB(r_vel,r_vel,loc); + Mat4Mul3Vecfl(ob->obmat,r_vel); Normalize(r_vel); } /* -angular velocity */ if(part->avemode==PART_AVE_RAND){ - VECADD(r_ave,tloc,pa->r_ave); - Mat4MulVecfl(ob->obmat,r_ave); - VECSUB(r_ave,r_ave,loc); + Mat4Mul3Vecfl(ob->obmat,r_ave); Normalize(r_ave); } /* -rotation */ if(part->randrotfac != 0.0f){ - QUATCOPY(r_rot,pa->r_rot); Mat4ToQuat(ob->obmat,rot); QuatMul(r_rot,r_rot,rot); } } if(part->phystype==PART_PHYS_BOIDS) { + BoidParticle *bpa = pa->boid; float dvec[3], q[4], mat[3][3]; VECCOPY(pa->state.co,loc); @@ -1872,16 +1849,21 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic VECCOPY(pa->state.ave, nor); } /* and gravity in r_ve */ - pa->r_ve[0] = pa->r_ve[1] = 0.0f; - pa->r_ve[2] = -1.0f; + bpa->gravity[0] = bpa->gravity[1] = 0.0f; + bpa->gravity[2] = -1.0f; if(part->acc[2]!=0.0f) - pa->r_ve[2] = part->acc[2]; + bpa->gravity[2] = part->acc[2]; + + //pa->r_ve[0] = pa->r_ve[1] = 0.0f; + //pa->r_ve[2] = -1.0f; + //if(part->acc[2]!=0.0f) + // pa->r_ve[2] = part->acc[2]; /* calculate rotation matrix */ - Projf(dvec, pa->r_ve, pa->state.ave); + Projf(dvec, r_vel, pa->state.ave); VecSubf(mat[0], pa->state.ave, dvec); Normalize(mat[0]); - VECCOPY(mat[2], pa->r_ve); + VECCOPY(mat[2], r_vel); VecMulf(mat[2], -1.0f); Normalize(mat[2]); Crossf(mat[1], mat[2], mat[0]); @@ -1890,10 +1872,10 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic Mat3ToQuat_is_ok(mat, q); QuatCopy(pa->state.rot, q); - pa->boid->health = part->boids->health; - pa->boid->mode = eBoidMode_InAir; - pa->boid->state_id = ((BoidState*)part->boids->states.first)->id; - pa->boid->acc[0]=pa->boid->acc[1]=pa->boid->acc[2]=0.0f; + bpa->data.health = part->boids->health; + bpa->data.mode = eBoidMode_InAir; + bpa->data.state_id = ((BoidState*)part->boids->states.first)->id; + bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f; } else { /* conversion done so now we apply new: */ @@ -1982,8 +1964,8 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic /* rotation phase */ phasefac = part->phasefac; - if(part->randphasefac != 0.0f) /* abuse r_ave[0] as a random number */ - phasefac += part->randphasefac * pa->r_ave[0]; + if(part->randphasefac != 0.0f) + phasefac += part->randphasefac * r_phase; VecRotToQuat(x_vec, phasefac*(float)M_PI, q_phase); /* combine base rotation & phase */ @@ -2021,8 +2003,7 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic pa->state.time = cfra; - pa->stick_ob = 0; - pa->flag &= ~PARS_STICKY; +// pa->flag &= ~PARS_STICKY; } static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from) { @@ -2088,8 +2069,9 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSystem *kpsys = psys; ParticleTarget *pt; - ParticleData *pa; - int totpart = psys->totpart, i, k, totkeys = psys->totkeyed; + PARTICLE_P; + ParticleKey *key; + int totpart = psys->totpart, k, totkeys = psys->totkeyed; /* no proper targets so let's clear and bail out */ if(psys->totkeyed==0) { @@ -2101,12 +2083,12 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) if(totpart && psys->particles->totkey != totkeys) { free_keyed_keys(psys); - psys->particles->keys = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys"); - psys->particles->totkey = totkeys; + key = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys"); - for(i=1, pa=psys->particles+1; i<totpart; i++,pa++){ - pa->keys = (pa-1)->keys + totkeys; + LOOP_PARTICLES { + pa->keys = key; pa->totkey = totkeys; + key += totkeys; } } @@ -2120,22 +2102,23 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) else kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1); - for(i=0,pa=psys->particles; i<totpart; i++, pa++) { - (pa->keys + k)->time = -1.0; /* use current time */ + LOOP_PARTICLES { + key = pa->keys + k; + key->time = -1.0; /* use current time */ - psys_get_particle_state(scene, pt->ob, kpsys, i%kpsys->totpart, pa->keys + k, 1); + psys_get_particle_state(scene, pt->ob, kpsys, p%kpsys->totpart, key, 1); if(psys->flag & PSYS_KEYED_TIMING){ - (pa->keys+k)->time = pa->time + pt->time; + key->time = pa->time + pt->time; if(pt->duration != 0.0f && k+1 < totkeys) { - copy_particle_key(pa->keys+k+1, pa->keys+k, 1); - (pa->keys+k+1)->time = pa->time + pt->time + pt->duration; + copy_particle_key(key+1, key, 1); + (key+1)->time = pa->time + pt->time + pt->duration; } } else if(totkeys > 1) - (pa->keys+k)->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime; + key->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime; else - pa->keys->time = pa->time; + key->time = pa->time; } if(psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f) @@ -2269,12 +2252,12 @@ void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) BKE_ptcache_disk_to_mem(&pid); } -void psys_clear_temp_pointcache(ParticleSystem *psys) +static void psys_clear_temp_pointcache(ParticleSystem *psys) { if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0) return; - BKE_ptache_free_mem(psys->pointcache); + BKE_ptcache_free_mem(&psys->pointcache->mem_cache); } void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra) { @@ -2290,16 +2273,15 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra static void update_particle_tree(ParticleSystem *psys) { if(psys) { - ParticleData *pa = psys->particles; - int p, totpart = psys->totpart; + PARTICLE_P; if(!psys->tree || psys->tree_frame != psys->cfra) { BLI_kdtree_free(psys->tree); - psys->tree = BLI_kdtree_new(totpart); + psys->tree = BLI_kdtree_new(psys->totpart); - for(p=0, pa=psys->particles; p<totpart; p++,pa++){ + LOOP_PARTICLES { if(pa->flag & (PARS_NO_DISP+PARS_UNEXIST) || pa->alive != PARS_ALIVE) continue; @@ -2542,9 +2524,9 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; ParticleSettings *part=psys->part; - ParticleData *pa; - float vec2[3],loc[3],*co=0; - int p,totpart; + PARTICLE_P; + int totpart; + float vec2[3],loc[3],radius,*co=0; for(ec= lb->first; ec; ec= ec->next) { PartDeflect *pd= ec->ob->pd; @@ -2554,7 +2536,7 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa && part->phystype!=PART_PHYS_BOIDS) { float vec[4]; - where_on_path(ec->ob, 0.0, vec, vec2); + where_on_path(ec->ob, 0.0, vec, vec2, NULL, &radius); Mat4MulVecfl(ec->ob->obmat,vec); Mat4Mul3Vecfl(ec->ob->obmat,vec2); @@ -2562,13 +2544,15 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa QUATCOPY(ec->firstloc,vec); VECCOPY(ec->firstdir,vec2); + /* TODO - use 'radius' to adjust the effector */ + totpart=psys->totpart; if(totpart){ ec->distances=MEM_callocN(totpart*sizeof(float),"particle distances"); ec->locations=MEM_callocN(totpart*3*sizeof(float),"particle locations"); - for(p=0,pa=psys->particles; p<totpart; p++, pa++){ + LOOP_PARTICLES { if(part->from == PART_FROM_PARTICLE) { VECCOPY(loc, pa->fuv); } @@ -3247,9 +3231,10 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /* override for boids */ if(part->phystype == PART_PHYS_BOIDS) { + BoidParticle *bpa = pa->boid; radius = pa->size; boid_z = pa->state.co[2]; - skip_ob = pa->stick_ob; + skip_ob = bpa->ground; } /* 10 iterations to catch multiple deflections */ @@ -3319,12 +3304,7 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa deflections=max_deflections; /* store for reactors */ - copy_particle_key(&reaction_state,&pa->state,0); - - if(part->flag & PART_STICKY){ - pa->stick_ob=ob; - pa->flag |= PARS_STICKY; - } + copy_particle_key(&reaction_state, &pa->state, 0); } else { float nor_vec[3], tan_vec[3], tan_vel[3], vel[3]; @@ -3412,7 +3392,8 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); if(part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) { - if(pa->boid->mode == eBoidMode_OnLand || co[2] <= boid_z) { + BoidParticle *bpa = pa->boid; + if(bpa->data.mode == eBoidMode_OnLand || co[2] <= boid_z) { co[2] = boid_z; vel[2] = 0.0f; } @@ -3453,11 +3434,194 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /************************************************/ /* Hair */ /************************************************/ -static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ - ParticleData *pa; +/* check if path cache or children need updating and do it if needed */ +static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +{ + ParticleSettings *part=psys->part; + ParticleEditSettings *pset=&scene->toolsettings->particle; + int distr=0,alloc=0,skip=0; + + if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) + alloc=1; + + if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))) + distr=1; + + if(distr){ + if(alloc) + realloc_particles(ob,psys,psys->totpart); + + if(get_psys_tot_child(scene, psys)) { + /* don't generate children while computing the hair keys */ + if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { + distribute_particles(scene, ob, psys, PART_FROM_CHILD); + + if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0) + psys_find_parents(ob,psmd,psys); + } + } + } + + if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) + skip = 1; /* only hair, keyed and baked stuff can have paths */ + else if(part->ren_as != PART_DRAW_PATH) + skip = 1; /* particle visualization must be set as path */ + else if(!psys->renderdata) { + if(part->draw_as != PART_DRAW_REND) + skip = 1; /* draw visualization */ + else if(psys->pointcache->flag & PTCACHE_BAKING) + skip = 1; /* no need to cache paths while baking dynamics */ + else if(psys_in_edit_mode(scene, psys)) { + if((pset->flag & PE_DRAW_PART)==0) + skip = 1; + else if(part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) + skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */ + } + } + + if(!skip) { + psys_cache_paths(scene, ob, psys, cfra); + + /* for render, child particle paths are computed on the fly */ + if(part->childtype) { + if(!psys->totchild) + skip = 1; + else if((psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DONE)==0) + skip = 1; + + if(!skip) + psys_cache_child_paths(scene, ob, psys, cfra, 0); + } + } + else if(psys->pathcache) + psys_free_path_cache(psys, NULL); +} + +static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +{ + DerivedMesh *dm = psys->hair_in_dm; + MVert *mvert = NULL; + MEdge *medge = NULL; + MDeformVert *dvert = NULL; HairKey *key; + PARTICLE_P; + int totpoint = 0; + int totedge; + int k; + float hairmat[4][4]; + + if(!psys->clmd) { + psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth); + psys->clmd->sim_parms->goalspring = 0.0f; + psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; + psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; + } + + /* create a dm from hair vertices */ + LOOP_PARTICLES + totpoint += pa->totkey; + + totedge = totpoint - psys->totpart; + + if(dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) { + dm->release(dm); + dm = psys->hair_in_dm = NULL; + } + + if(!dm) { + dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0, 0, 0); + DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL); + } + + mvert = CDDM_get_verts(dm); + medge = CDDM_get_edges(dm); + dvert = DM_get_vert_data_layer(dm, CD_MDEFORMVERT); + + psys->clmd->sim_parms->vgroup_mass = 1; + + /* make vgroup for pin roots etc.. */ + psys->particles->hair_index = 0; + LOOP_PARTICLES { + if(p) + pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey; + + psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat); + + for(k=0, key=pa->hair; k<pa->totkey; k++,key++) { + VECCOPY(mvert->co, key->co); + Mat4MulVecfl(hairmat, mvert->co); + mvert++; + + if(k) { + medge->v1 = pa->hair_index + k - 1; + medge->v2 = pa->hair_index + k; + medge++; + } + + if(dvert) { + if(!dvert->totweight) { + dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->totweight = 1; + } + + /* no special reason for the 0.5 */ + /* just seems like a nice value from experiments */ + dvert->dw->weight = k ? 0.5f : 1.0f; + dvert++; + } + } + } + + if(psys->hair_out_dm) + psys->hair_out_dm->release(psys->hair_out_dm); + + psys->clmd->point_cache = psys->pointcache; + + psys->hair_out_dm = clothModifier_do(psys->clmd, scene, ob, dm, 0, 0); +} +static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +{ + ParticleSettings *part = psys->part; + PARTICLE_P; + float disp = (float)get_current_display_percentage(psys)/100.0f; + + BLI_srandom(psys->seed); + + LOOP_PARTICLES { + if(BLI_frand() > disp) + pa->flag |= PARS_NO_DISP; + else + pa->flag &= ~PARS_NO_DISP; + } + + if(psys->recalc & PSYS_RECALC_RESET) { + /* need this for changing subsurf levels */ + psys_calc_dmcache(ob, psmd->dm, psys); + + if(psys->clmd) + cloth_free_modifier(ob, psys->clmd); + } + + if(psys->effectors.first) + psys_end_effectors(psys); + + /* dynamics with cloth simulation */ + if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) + do_hair_dynamics(scene, ob, psys, psmd); + + psys_init_effectors(scene, ob, part->eff_group, psys); + if(psys->effectors.first) + precalc_effectors(scene, ob,psys,psmd,cfra); + + psys_update_path_cache(scene, ob,psmd,psys,cfra); + + psys->flag |= PSYS_HAIR_UPDATED; +} + +static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ + HairKey *key, *root; + PARTICLE_P; int totpart; - int i; Mat4Invert(ob->imat,ob->obmat); @@ -3468,21 +3632,22 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy totpart=psys->totpart; /* save new keys for elements if needed */ - for(i=0,pa=psys->particles; i<totpart; i++,pa++) { + LOOP_PARTICLES { /* first time alloc */ if(pa->totkey==0 || pa->hair==NULL) { pa->hair = MEM_callocN((psys->part->hair_step + 1) * sizeof(HairKey), "HairKeys"); pa->totkey = 0; } - key = pa->hair + pa->totkey; + key = root = pa->hair; + key += pa->totkey; /* convert from global to geometry space */ VecCopyf(key->co, pa->state.co); Mat4MulVecfl(ob->imat, key->co); if(pa->totkey) { - VECSUB(key->co, key->co, pa->hair->co); + VECSUB(key->co, key->co, root->co); psys_vec_rot_to_face(psmd->dm, pa, key->co); } @@ -3494,7 +3659,7 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy /* root is always in the origin of hair space so we set it to be so after the last key is saved*/ if(pa->totkey == psys->part->hair_step + 1) - pa->hair->co[0] = pa->hair->co[1] = pa->hair->co[2] = 0.0f; + root->co[0] = root->co[1] = root->co[2] = 0.0f; } } /************************************************/ @@ -3504,14 +3669,14 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra, float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size) { - ParticleData *pa; ParticleSettings *part=psys->part; KDTree *tree=0; IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system Material *ma=give_current_material(ob,part->omat); BoidBrainData bbd; + PARTICLE_P; float timestep; - int p, totpart; + int totpart; /* current time */ float ctime, ipotime; // XXX old animation system /* frame & time changes */ @@ -3540,7 +3705,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic if(part->type==PART_REACTOR) vg_size=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); - for(p=0, pa=psys->particles; p<totpart; p++,pa++){ + LOOP_PARTICLES { if(pa->flag & PARS_UNEXIST) continue; /* set correct ipo timing */ @@ -3609,7 +3774,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } /* main loop: calculate physics for all particles */ - for(p=0, pa=psys->particles; p<totpart; p++,pa++){ + LOOP_PARTICLES { if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; copy_particle_key(&pa->prev_state,&pa->state,1); @@ -3697,9 +3862,6 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic else{ pa->alive=PARS_DEAD; pa->state.time=pa->dietime; - - if(pa->flag&PARS_STICKY) - psys_key_to_object(pa->stick_ob,&pa->state,0); } } else @@ -3716,116 +3878,18 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic BLI_kdtree_free(tree); } -/* check if path cache or children need updating and do it if needed */ -static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) -{ - ParticleSettings *part=psys->part; - ParticleEditSettings *pset=&scene->toolsettings->particle; - int distr=0,alloc=0; - - if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) - alloc=1; - - if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))) - distr=1; - - if(distr){ - if(alloc) - realloc_particles(ob,psys,psys->totpart); - - if(get_psys_tot_child(scene, psys)) { - /* don't generate children while computing the hair keys */ - if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { - distribute_particles(scene, ob, psys, PART_FROM_CHILD); - - if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0) - psys_find_parents(ob,psmd,psys); - } - } - } - - if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR - || (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){ - - psys_cache_paths(scene, ob, psys, cfra, 0); - - /* for render, child particle paths are computed on the fly */ - if(part->childtype) { - if(((psys->totchild!=0)) || (psys_in_edit_mode(scene, psys) && (pset->flag&PE_SHOW_CHILD))) - if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) - psys_cache_child_paths(scene, ob, psys, cfra, 0); - } - } - else if(psys->pathcache) - psys_free_path_cache(psys); -} - -/* calculate and store key locations in world coordinates */ -void psys_update_world_cos(Object *ob, ParticleSystem *psys) -{ - ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); - ParticleData *pa; - ParticleEditKey *key; - int i, k, totpart; - float hairmat[4][4]; - - if(psys==0 || psys->edit==0) - return; - - totpart= psys->totpart; - - for(i=0, pa=psys->particles; i<totpart; i++, pa++) { - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); - - for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) { - VECCOPY(key->world_co,key->co); - Mat4MulVecfl(hairmat, key->world_co); - } - } -} - -static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) -{ - ParticleSettings *part = psys->part; - ParticleData *pa; - int p; - float disp = (float)get_current_display_percentage(psys)/50.0f-1.0f; - - for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){ - if(pa->r_rot[0] > disp) - pa->flag |= PARS_NO_DISP; - else - pa->flag &= ~PARS_NO_DISP; - } - - if(psys->recalc & PSYS_RECALC_RESET) - /* need this for changing subsurf levels */ - psys_calc_dmcache(ob, psmd->dm, psys); - - if(psys->effectors.first) - psys_end_effectors(psys); - - psys_init_effectors(scene, ob, part->eff_group, psys); - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); - - if(psys_in_edit_mode(scene, psys)) - psys_update_world_cos(ob, psys); - - psys_update_path_cache(scene, ob,psmd,psys,cfra); -} - /* updates cached particles' alive & other flags etc..*/ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) { ParticleSettings *part=psys->part; - ParticleData *pa; ParticleKey state; IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system Material *ma=give_current_material(ob,part->omat); - int p; + PARTICLE_P; float disp, birthtime, dietime, *vg_size= NULL; // XXX ipotime=cfra + BLI_srandom(psys->seed); + if(part->from!=PART_FROM_PARTICLE) vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); @@ -3838,9 +3902,9 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps precalc_effectors(scene, ob,psys,psmd,cfra); //} - disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; + disp= (float)get_current_display_percentage(psys)/100.0f; - for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){ + LOOP_PARTICLES { #if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ ipotime=100.0f*(cfra-pa->time)/pa->lifetime; @@ -3887,7 +3951,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps psys->lattice= NULL; } - if(pa->r_rot[0] > disp) + if(BLI_frand() > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -3938,35 +4002,35 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys) BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { - free_hair(psys, 1); + free_hair(ob, psys, 1); - CLAMP(part->path_start, part->sta, part->end + part->lifetime); - CLAMP(part->path_end, part->sta, part->end + part->lifetime); + CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime)); + CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime)); } - psys->softflag= 0; - psys_reset(psys, PSYS_RESET_ALL); } void psys_check_boid_data(ParticleSystem *psys) { - ParticleData *pa = psys->particles; - int p = 1; + BoidParticle *bpa; + PARTICLE_P; + + pa = psys->particles; if(!pa) return; if(psys->part && psys->part->phystype==PART_PHYS_BOIDS) { if(!pa->boid) { - pa->boid = MEM_callocN(psys->totpart * sizeof(BoidData), "Boid Data"); + bpa = MEM_callocN(psys->totpart * sizeof(BoidParticle), "Boid Data"); - for(pa++; p<psys->totpart; p++, pa++) - pa->boid = (pa-1)->boid + 1; + LOOP_PARTICLES + pa->boid = bpa++; } } else if(pa->boid){ MEM_freeN(pa->boid); - for(; p<psys->totpart; p++, pa++) + LOOP_PARTICLES pa->boid = NULL; } } @@ -4114,10 +4178,10 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) { ParticleSettings *part; - ParticleData *pa; PointCache *cache; PTCacheID pid; - int totpart, oldtotpart, totchild, oldtotchild, p; + PARTICLE_P; + int totpart, oldtotpart, totchild, oldtotchild; float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0; int framenr, framedelta, startframe, endframe; @@ -4129,7 +4193,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle framedelta= framenr - cache->simframe; /* set suitable cache range automatically */ - if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0) + if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0 && !(psys->flag & PSYS_HAIR_DYNAMICS)) psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe); BKE_ptcache_id_from_particles(&pid, ob, psys); @@ -4260,7 +4324,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle } else if(result==PTCACHE_READ_OLD) { psys->cfra = (float)cache->simframe; - for(p=0, pa=psys->particles; p<totpart; p++, pa++) { + LOOP_PARTICLES { /* update alive status */ if(pa->time > psys->cfra) pa->alive = PARS_UNBORN; @@ -4299,10 +4363,11 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle } /* set particles to be not calculated TODO: can't work with pointcache */ - disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; + disp= (float)get_current_display_percentage(psys)/100.0f; - for(p=0, pa=psys->particles; p<totpart; p++,pa++){ - if(pa->r_rot[0] > disp) + BLI_srandom(psys->seed); + LOOP_PARTICLES { + if(BLI_frand() > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -4339,7 +4404,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle psys_update_path_cache(scene, ob, psmd, psys,(int)cfra); } else if(psys->pathcache) - psys_free_path_cache(psys); + psys_free_path_cache(psys, NULL); /* cleanup */ if(vg_vel) MEM_freeN(vg_vel); @@ -4353,39 +4418,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle } } -static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys) -{ - SoftBody *sb; - short softflag; - - if(!(psys->softflag & OB_SB_ENABLE)) - return; - - /* let's replace the object's own softbody with the particle softbody */ - /* a temporary solution before cloth simulation is implemented, jahka */ - - /* save these */ - sb= ob->soft; - softflag= ob->softflag; - - /* swich to new ones */ - ob->soft= psys->soft; - ob->softflag= psys->softflag; - - /* do softbody */ - sbObjectStep(scene, ob, (float)scene->r.cfra, NULL, psys_count_keys(psys)); - - /* return things back to normal */ - psys->soft= ob->soft; - psys->softflag= ob->softflag; - - ob->soft= sb; - ob->softflag= softflag; -} - static int hair_needs_recalc(ParticleSystem *psys) { - if((psys->flag & PSYS_EDITED)==0 && + if(!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) && ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) { return 1; } @@ -4426,7 +4461,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) float hcfra=0.0f; int i; - free_hair(psys, 0); + free_hair(ob, psys, 0); /* first step is negative so particles get killed and reset */ psys->cfra= 1.0f; @@ -4440,10 +4475,6 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) psys->flag |= PSYS_HAIR_DONE; } - /* handle softbody hair */ - if(psys->part->type==PART_HAIR && psys->soft) - psys_to_softbody(scene, ob, psys); - /* the main particle system step */ system_step(scene, ob, psys, psmd, cfra); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 69da8f19d8c..d685bc29568 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -67,23 +67,13 @@ /* needed for directory lookup */ +/* untitled blend's need getpid for a unique name */ #ifndef WIN32 #include <dirent.h> +#include <unistd.h> #else - #include "BLI_winstuff.h" -#endif - -/* untitled blend's need getpid for a unique name */ -#ifdef WIN32 #include <process.h> -#else -#include <unistd.h> -#endif - -#ifdef _WIN32 -#ifndef snprintf -#define snprintf _snprintf -#endif + #include "BLI_winstuff.h" #endif static void ptcache_data_to(void **data, int type, int index, void *to); @@ -181,6 +171,7 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) { ParticleSystem *psys= psys_v; ParticleData *pa = psys->particles + index; + BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; float times[3] = {pa->time, pa->dietime, pa->lifetime}; if(data[BPHYS_DATA_INDEX]) { @@ -198,8 +189,8 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size); ptcache_data_from(data, BPHYS_DATA_TIMES, times); - if(pa->boid) - ptcache_data_from(data, BPHYS_DATA_TIMES, &pa->boid); + if(boid) + ptcache_data_from(data, BPHYS_DATA_BOIDS, &boid->data); return 1; } @@ -215,6 +206,7 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr { ParticleSystem *psys= psys_v; ParticleData *pa = psys->particles + index; + BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; if(cfra > pa->state.time) memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey)); @@ -238,8 +230,8 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr pa->lifetime = times[2]; } - if(pa->boid) - ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &pa->boid); + if(boid) + ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &boid->data); /* determine velocity from previous location */ if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { @@ -390,8 +382,6 @@ static int ptcache_totpoint_cloth(void *cloth_v) /* Creating ID's */ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { - ParticleSystemModifierData *psmd; - memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; @@ -414,12 +404,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); pid->info_types= 0; - if(sb->particles) { - psmd= psys_get_modifier(ob, sb->particles); - // pid->stack_index= modifiers_indexInObject(ob, (ModifierData*)psmd); XXX TODO - get other index DG - } - else - pid->stack_index = pid->cache->index; + pid->stack_index = pid->cache->index; } void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) @@ -434,6 +419,9 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p pid->cache_ptr= &psys->pointcache; pid->ptcaches= &psys->ptcaches; + if(psys->part->type != PART_HAIR) + pid->flag |= PTCACHE_VEL_PER_SEC; + pid->write_elem= ptcache_write_particle; pid->write_stream = NULL; pid->read_stream = NULL; @@ -477,6 +465,19 @@ static int ptcache_totpoint_smoke(void *smoke_v) return 0; } +/* Smoke functions */ +static int ptcache_totpoint_smoke_turbulence(void *smoke_v) +{ + SmokeModifierData *smd= (SmokeModifierData *)smoke_v; + SmokeDomainSettings *sds = smd->domain; + + if(sds->wt) { + return sds->res_wt[0]*sds->res_wt[1]*sds->res_wt[2]; + } + else + return 0; +} + // forward decleration static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size); @@ -527,7 +528,7 @@ static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned i } static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) -{ +{ SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; @@ -541,7 +542,7 @@ static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); - ptcache_compress_write(pf, (unsigned char *)sds->view3d, in_len*4, out, mode); + ptcache_compress_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); ptcache_compress_write(pf, (unsigned char *)dens, in_len, out, mode); ptcache_compress_write(pf, (unsigned char *)densold, in_len, out, mode); ptcache_compress_write(pf, (unsigned char *)heat, in_len, out, mode); @@ -560,36 +561,36 @@ static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) return 1; } - return 0; } -/* static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; if(sds->wt) { - unsigned int res_big[3]; - size_t res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big_array[3]; + int res_big; + int res = sds->res[0]*sds->res[1]*sds->res[2]; float *dens, *densold, *tcu, *tcv, *tcw; unsigned int in_len = sizeof(float)*(unsigned int)res; - unsigned int in_len_big = sizeof(float) * (unsigned int)res_big; + unsigned int in_len_big; unsigned char *out; int mode; - smoke_turbulence_get_res(sds->wt, res_big); - mode = res_big[0]*res_big[1]*res_big[2] >= 1000000 ? 2 : 1; + smoke_turbulence_get_res(sds->wt, res_big_array); + res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; + mode = res_big >= 1000000 ? 2 : 1; + in_len_big = sizeof(float) * (unsigned int)res_big; smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer"); - ptcache_compress_write(pf, (unsigned char *)dens, in_len_big, out, mode); ptcache_compress_write(pf, (unsigned char *)densold, in_len_big, out, mode); - MEM_freeN(out); + out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer"); ptcache_compress_write(pf, (unsigned char *)tcu, in_len, out, mode); ptcache_compress_write(pf, (unsigned char *)tcv, in_len, out, mode); @@ -600,7 +601,6 @@ static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) } return 0; } -*/ // forward decleration static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size); @@ -655,7 +655,7 @@ static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v) smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); - ptcache_compress_read(pf, (unsigned char *)sds->view3d, out_len*4); + ptcache_compress_read(pf, (unsigned char *)sds->shadow, out_len); ptcache_compress_read(pf, (unsigned char*)dens, out_len); ptcache_compress_read(pf, (unsigned char*)densold, out_len); ptcache_compress_read(pf, (unsigned char*)heat, out_len); @@ -672,26 +672,32 @@ static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v) } } -/* static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; if(sds->fluid) { - unsigned int res[3]; + int res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big, res_big_array[3]; float *dens, *densold, *tcu, *tcv, *tcw; unsigned int out_len = sizeof(float)*(unsigned int)res; + unsigned int out_len_big; - smoke_turbulence_get_res(sds->wt, res); + smoke_turbulence_get_res(sds->wt, res_big_array); + res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; + out_len_big = sizeof(float) * (unsigned int)res_big; smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); - ptcache_compress_read(pf, (unsigned char*)dens, out_len); - + ptcache_compress_read(pf, (unsigned char*)dens, out_len_big); + ptcache_compress_read(pf, (unsigned char*)densold, out_len_big); + + ptcache_compress_read(pf, (unsigned char*)tcu, out_len); + ptcache_compress_read(pf, (unsigned char*)tcv, out_len); + ptcache_compress_read(pf, (unsigned char*)tcw, out_len); } } -*/ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) { @@ -722,7 +728,7 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo pid->write_header= ptcache_write_basic_header; pid->read_header= ptcache_read_basic_header; - pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy + pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values to make pointcache happy pid->info_types= 0; } @@ -742,13 +748,13 @@ void BKE_ptcache_id_from_smoke_turbulence(PTCacheID *pid, struct Object *ob, str pid->cache_ptr= &sds->point_cache[1]; pid->ptcaches= &sds->ptcaches[1]; - pid->totpoint= pid->totwrite= ptcache_totpoint_smoke; + pid->totpoint= pid->totwrite= ptcache_totpoint_smoke_turbulence; pid->write_elem= NULL; pid->read_elem= NULL; - pid->read_stream = ptcache_read_smoke; - pid->write_stream = ptcache_write_smoke; + pid->read_stream = ptcache_read_smoke_turbulence; + pid->write_stream = ptcache_write_smoke_turbulence; pid->interpolate_elem= NULL; @@ -800,13 +806,9 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob) } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_particles(pid, ob, psys); - BLI_addtail(lb, pid); - - if(psys->soft) { + if(psys->part) { pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_softbody(pid, ob, psys->soft); + BKE_ptcache_id_from_particles(pid, ob, psys); BLI_addtail(lb, pid); } } @@ -824,6 +826,10 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob) pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md); BLI_addtail(lb, pid); + + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_smoke_turbulence(pid, ob, (SmokeModifierData*)md); + BLI_addtail(lb, pid); } } } @@ -1087,7 +1093,7 @@ static void ptcache_file_init_pointers(PTCacheFile *pf) pf->cur[BPHYS_DATA_BOIDS] = data_types & (1<<BPHYS_DATA_BOIDS) ? &pf->data.boids : NULL; } -static void ptcache_mem_init_pointers(PTCacheMem *pm) +void BKE_ptcache_mem_init_pointers(PTCacheMem *pm) { int data_types = pm->data_types; int i; @@ -1096,7 +1102,7 @@ static void ptcache_mem_init_pointers(PTCacheMem *pm) pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL; } -static void ptcache_mem_incr_pointers(PTCacheMem *pm) +void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) { int i; @@ -1249,12 +1255,12 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) return 0; if(pm) { - ptcache_mem_init_pointers(pm); + BKE_ptcache_mem_init_pointers(pm); totpoint = pm->totpoint; index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i; } if(pm2) { - ptcache_mem_init_pointers(pm2); + BKE_ptcache_mem_init_pointers(pm2); totpoint2 = pm2->totpoint; index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i; } @@ -1336,7 +1342,7 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) } if(pm) { - ptcache_mem_incr_pointers(pm); + BKE_ptcache_mem_incr_pointers(pm); index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i; } } @@ -1387,7 +1393,7 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) } if(pm2) { - ptcache_mem_incr_pointers(pm2); + BKE_ptcache_mem_incr_pointers(pm2); index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i; } } @@ -1559,11 +1565,11 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) pm->data_types = cfra ? pid->data_types : pid->info_types; ptcache_alloc_data(pm); - ptcache_mem_init_pointers(pm); + BKE_ptcache_mem_init_pointers(pm); for(i=0; i<totpoint; i++) { if(pid->write_elem && pid->write_elem(i, pid->calldata, pm->cur)) - ptcache_mem_incr_pointers(pm); + BKE_ptcache_mem_incr_pointers(pm); } //ptcache_make_index_array(pm, pid->totpoint(pid->calldata)); @@ -1664,6 +1670,8 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) PTCacheMem *pm= pid->cache->mem_cache.first; PTCacheMem *link= NULL; + pm= pid->cache->mem_cache.first; + if(mode == PTCACHE_CLEAR_ALL) { pid->cache->last_exact = 0; for(; pm; pm=pm->next) @@ -1808,9 +1816,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) else if(mode == PTCACHE_RESET_OUTDATED) { reset = 1; - if(cache->flag & PTCACHE_OUTDATED) - if(!(cache->flag & PTCACHE_BAKED)) - clear= 1; + if(cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) { + clear= 1; + cache->flag &= ~PTCACHE_OUTDATED; + } } if(reset) { @@ -1826,6 +1835,8 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) smokeModifier_reset(pid->calldata); + else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) + smokeModifier_reset_turbulence(pid->calldata); } if(clear) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); @@ -1851,10 +1862,10 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - /* Baked softbody hair has to be checked first, because we don't want to reset */ - /* particles or softbody in that case -jahka */ - if(psys->soft) { - BKE_ptcache_id_from_softbody(&pid, ob, psys->soft); + /* Baked cloth hair has to be checked first, because we don't want to reset */ + /* particles or cloth in that case -jahka */ + if(psys->clmd) { + BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd); if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) reset |= BKE_ptcache_id_reset(scene, &pid, mode); else @@ -1863,7 +1874,7 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) skip = 1; - if(skip == 0) { + if(skip == 0 && psys->part) { BKE_ptcache_id_from_particles(&pid, ob, psys); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } @@ -1880,6 +1891,9 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) { BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md); reset |= BKE_ptcache_id_reset(scene, &pid, mode); + + BKE_ptcache_id_from_smoke_turbulence(&pid, ob, (SmokeModifierData*)md); + reset |= BKE_ptcache_id_reset(scene, &pid, mode); } } } @@ -1941,7 +1955,7 @@ void BKE_ptcache_set_continue_physics(Scene *scene, int enable) if(CONTINUE_PHYSICS == 0) { for(ob=G.main->object.first; ob; ob=ob->id.next) if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } } } @@ -1968,9 +1982,9 @@ PointCache *BKE_ptcache_add(ListBase *ptcaches) return cache; } -void BKE_ptache_free_mem(PointCache *cache) +void BKE_ptcache_free_mem(ListBase *mem_cache) { - PTCacheMem *pm = cache->mem_cache.first; + PTCacheMem *pm = mem_cache->first; if(pm) { for(; pm; pm=pm->next) { @@ -1979,22 +1993,25 @@ void BKE_ptache_free_mem(PointCache *cache) MEM_freeN(pm->index_array); } - BLI_freelistN(&cache->mem_cache); + BLI_freelistN(mem_cache); } } void BKE_ptcache_free(PointCache *cache) { - BKE_ptache_free_mem(cache); + BKE_ptcache_free_mem(&cache->mem_cache); + if(cache->edit && cache->free_edit) + cache->free_edit(cache->edit); MEM_freeN(cache); } void BKE_ptcache_free_list(ListBase *ptcaches) { PointCache *cache = ptcaches->first; - for(; cache; cache=cache->next) - BKE_ptache_free_mem(cache); - - BLI_freelistN(ptcaches); + while(cache) { + BLI_remlink(ptcaches, cache); + BKE_ptcache_free(cache); + cache = ptcaches->first; + } } static PointCache *ptcache_copy(PointCache *cache) @@ -2102,6 +2119,25 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if((cache->flag & PTCACHE_BAKED)==0) { if(pid->type==PTCACHE_TYPE_PARTICLES) psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); + else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) { + /* get all pids from the object and search for smoke low res */ + ListBase pidlist2; + PTCacheID *pid2; + BKE_ptcache_ids_from_object(&pidlist2, pid->ob); + for(pid2=pidlist2.first; pid2; pid2=pid2->next) { + if(pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) + { + if(pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) { + if(bake || pid2->cache->flag & PTCACHE_REDO_NEEDED) + BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0); + if(bake) { + pid2->cache->flag |= PTCACHE_BAKING; + pid2->cache->flag &= ~PTCACHE_BAKED; + } + } + } + } + } if(bake || cache->flag & PTCACHE_REDO_NEEDED) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); @@ -2258,7 +2294,7 @@ void BKE_ptcache_disk_to_mem(PTCacheID *pid) pm->frame = cfra; ptcache_alloc_data(pm); - ptcache_mem_init_pointers(pm); + BKE_ptcache_mem_init_pointers(pm); ptcache_file_init_pointers(pf); for(i=0; i<pm->totpoint; i++) { @@ -2274,7 +2310,7 @@ void BKE_ptcache_disk_to_mem(PTCacheID *pid) return; } ptcache_copy_data(pf->cur, pm->cur); - ptcache_mem_incr_pointers(pm); + BKE_ptcache_mem_incr_pointers(pm); } //ptcache_make_index_array(pm, pid->totpoint(pid->calldata)); @@ -2305,7 +2341,7 @@ void BKE_ptcache_mem_to_disk(PTCacheID *pid) pf->totpoint = pm->totpoint; pf->type = pid->type; - ptcache_mem_init_pointers(pm); + BKE_ptcache_mem_init_pointers(pm); ptcache_file_init_pointers(pf); if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) { @@ -2325,7 +2361,7 @@ void BKE_ptcache_mem_to_disk(PTCacheID *pid) ptcache_file_close(pf); return; } - ptcache_mem_incr_pointers(pm); + BKE_ptcache_mem_incr_pointers(pm); } ptcache_file_close(pf); diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 139895bbdaf..de2118af202 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -52,30 +52,6 @@ #include "BKE_blender.h" #include "BKE_sca.h" -//#include "wm_event_types.h" - -void free_text_controllers(Text *txt) -{ - Object *ob; - bController *cont; - - ob= G.main->object.first; - while(ob) { - cont= ob->controllers.first; - while(cont) { - if(cont->type==CONT_PYTHON) { - bPythonCont *pc; - - pc= cont->data; - if(pc->text==txt) pc->text= NULL; - } - cont= cont->next; - } - ob= ob->id.next; - } -} - - /* ******************* SENSORS ************************ */ void free_sensor(bSensor *sens) @@ -418,12 +394,10 @@ void init_actuator(bActuator *act) act->data= 0; switch(act->type) { -#ifdef __NLA case ACT_ACTION: case ACT_SHAPEACTION: act->data= MEM_callocN(sizeof(bActionActuator), "actionact"); break; -#endif case ACT_SOUND: sa = act->data= MEM_callocN(sizeof(bSoundActuator), "soundact"); sa->volume = 1.0f; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 6dd362d15a8..6f9ed3e0978 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -245,6 +245,11 @@ void free_scene(Scene *sce) base= base->next; } /* do not free objects! */ + + if(sce->gpd) { + sce->gpd->id.us--; + sce->gpd= NULL; + } BLI_freelistN(&sce->base); seq_free_editing(sce); @@ -399,11 +404,13 @@ Scene *add_scene(char *name) sce->unit.scale_length = 1.0f; pset= &sce->toolsettings->particle; - pset->flag= PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER; + pset->flag= PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER|PE_AUTO_VELOCITY; pset->emitterdist= 0.25f; pset->totrekey= 5; pset->totaddkey= 5; pset->brushtype= PE_BRUSH_NONE; + pset->draw_step= 2; + pset->fade_frames= 2; for(a=0; a<PE_TOT_BRUSH; a++) { pset->brush[a].strength= 50; pset->brush[a].size= 50; @@ -853,14 +860,3 @@ float get_render_aosss_error(RenderData *r, float error) return error; } -void free_dome_warp_text(struct Text *txt) -{ - Scene *scene; - - scene = G.main->scene.first; - while(scene) { - if (scene->r.dometext == txt) - scene->r.dometext = NULL; - scene = scene->id.next; - } -} diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index cc740d7fb3d..661d0da1550 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -33,8 +33,10 @@ #include "MEM_guardedalloc.h" +#include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "DNA_view3d_types.h" #include "BLI_blenlib.h" @@ -321,4 +323,23 @@ void free_screen(bScreen *sc) BLI_freelistN(&sc->areabase); } +/* for depsgraph */ +unsigned int BKE_screen_visible_layers(bScreen *screen) +{ + ScrArea *sa; + unsigned int layer= 0; + + if(!screen) + return layer; + + /* get all used view3d layers */ + for(sa= screen->areabase.first; sa; sa= sa->next) + if(sa->spacetype==SPACE_VIEW3D) + layer |= ((View3D *)sa->spacedata.first)->lay; + + if(!layer) + return screen->scene->lay; + + return layer; +} diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index 159a60ad3af..7f3e2789232 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -127,7 +127,7 @@ void new_tstripdata(Sequence *seq) /* free */ -void free_proxy_seq(Sequence *seq) +static void free_proxy_seq(Sequence *seq) { if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { IMB_free_anim(seq->strip->proxy->anim); @@ -570,7 +570,7 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq) } seq->strip->len = seq->len; } else if (seq->type == SEQ_SOUND) { - seq->len = AUD_getInfo(seq->sound->snd_sound).length * FPS; + seq->len = AUD_getInfo(seq->sound->handle).length * FPS; seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; if (seq->len < 0) { @@ -682,7 +682,7 @@ void clear_scene_in_allseqs(Scene *sce) } } -char *give_seqname_by_type(int type) +static char *give_seqname_by_type(int type) { switch(type) { case SEQ_META: return "Meta"; @@ -949,7 +949,7 @@ static TStripElem* alloc_tstripdata(int len, const char * name) return se; } -TStripElem *give_tstripelem(Sequence *seq, int cfra) +static TStripElem *give_tstripelem(Sequence *seq, int cfra) { TStripElem *se; int nr; @@ -1297,7 +1297,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re se->ibuf = 0; } -void seq_proxy_rebuild(Scene *scene, Sequence * seq) +static void seq_proxy_rebuild(Scene *scene, Sequence * seq) { int cfra; float rsize = seq->strip->proxy->size; @@ -2623,7 +2623,7 @@ ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown } /* check used when we need to change seq->blend_mode but not to effect or audio strips */ -int seq_can_blend(Sequence *seq) +static int seq_can_blend(Sequence *seq) { if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { return 1; @@ -2749,7 +2749,7 @@ static void *seq_prefetch_thread(void * This_) return 0; } -void seq_start_threads(Scene *scene) +static void seq_start_threads(Scene *scene) { int i; @@ -2782,7 +2782,7 @@ void seq_start_threads(Scene *scene) BLI_init_threads(0, 0, 0); } -void seq_stop_threads() +static void seq_stop_threads() { PrefetchThread *tslot; PrefetchQueueElem *e; @@ -2850,7 +2850,7 @@ void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, pthread_mutex_unlock(&wakeup_lock); } -void seq_wait_for_prefetch_ready() +static void seq_wait_for_prefetch_ready() { PrefetchThread *tslot; @@ -2984,7 +2984,7 @@ static void free_anim_seq(Sequence *seq) } } -void free_imbuf_seq_except(Scene *scene, int cfra) +static void free_imbuf_seq_except(Scene *scene, int cfra) { Editing *ed= seq_give_editing(scene, FALSE); Sequence *seq; @@ -3178,7 +3178,7 @@ void free_imbuf_seq() } #endif -void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) +static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) { /* force update of all sequences with this ipo, on ipo changes */ Editing *ed= seq_give_editing(scene, FALSE); diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 577156ef453..92c586f0001 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -575,7 +575,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object } } - //Just to make sure we are not letting any memory behind + //Just to make sure we are not leaving any memory behind assert(ssmd.emCache == NULL); assert(ssmd.mCache == NULL); } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 91de57024e6..fea62ea1f21 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -38,6 +38,7 @@ #include <float.h> #include <math.h> #include "stdio.h" +#include "string.h" /* memset */ #include "BLI_linklist.h" #include "BLI_rand.h" @@ -92,10 +93,10 @@ static void tend ( void ) { QueryPerformanceCounter ( &liCurrentTime ); } -//static double tval() -//{ -// return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart)* (double)1000.0/(double)liFrequency.QuadPart )); -//} +static double tval() +{ + return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart)* (double)1000.0/(double)liFrequency.QuadPart )); +} #else #include <sys/time.h> static struct timeval _tstart, _tend; @@ -125,7 +126,6 @@ struct SmokeModifierData; // forward declerations static void get_cell(float *p0, int res[3], float dx, float *pos, int *cell, int correct); void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *tris, int numfaces, int numtris, int **tridivs, float cell_len); -void smoke_prepare_View(SmokeModifierData *smd, float framenr, float *light, int have_light); #define TRI_UVOFFSET (1./4.) @@ -167,6 +167,9 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive // calc other res with max_res provided VECSUB(size, max, min); + // printf("size: %f, %f, %f\n", size[0], size[1], size[2]); + + // prevent crash when initializing a plane as domain if((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON)) return 0; @@ -209,28 +212,36 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive } } + // printf("smd->domain->dx: %f\n", smd->domain->dx); + // TODO: put in failsafe if res<=0 - dg // printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]); // dt max is 0.1 smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, 0.1); smd->time = scene->r.cfra; - smd->domain->firstframe = smd->time; - - if(!smd->domain->wt && (smd->domain->flags & MOD_SMOKE_HIGHRES)) - { - smd->domain->wt = smoke_turbulence_init(smd->domain->res, smd->domain->amplify + 1, smd->domain->noise); - smoke_turbulence_initBlenderRNA(smd->domain->wt, &smd->domain->strength); - } - if(!smd->domain->view3d) + if(smd->domain->flags & MOD_SMOKE_HIGHRES) { - // TVox is for transparency - smd->domain->view3d = MEM_callocN(sizeof(float)*smd->domain->res[0]*smd->domain->res[1]*smd->domain->res[2]*4, "Smoke_tVox"); + smd->domain->wt = smoke_turbulence_init(smd->domain->res, smd->domain->amplify + 1, smd->domain->noise); + smd->domain->res_wt[0] = smd->domain->res[0] * (smd->domain->amplify + 1); + smd->domain->res_wt[1] = smd->domain->res[1] * (smd->domain->amplify + 1); + smd->domain->res_wt[2] = smd->domain->res[2] * (smd->domain->amplify + 1); + smd->domain->dx_wt = smd->domain->dx / (smd->domain->amplify + 1); + // printf("smd->domain->amplify: %d\n", smd->domain->amplify); + // printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n"); } + if(!smd->domain->shadow) + smd->domain->shadow = MEM_callocN(sizeof(float) * smd->domain->res[0] * smd->domain->res[1] * smd->domain->res[2], "SmokeDomainShadow"); + smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta)); + if(smd->domain->wt) + { + smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength)); + // printf("smoke_initWaveletBlenderRNA\n"); + } return 1; } else if((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) @@ -270,13 +281,11 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive SmokeCollSettings *scs = smd->coll; MVert *mvert = dm->getVertArray(dm); MFace *mface = dm->getTessFaceArray(dm); - size_t i = 0; - int divs = 0; + int i = 0, divs = 0; int *tridivs = NULL; float cell_len = 1.0 / 50.0; // for res = 50 - size_t newdivs = 0; - //size_t max_points = 0; - size_t quads = 0, facecounter = 0; + int newdivs = 0; + int quads = 0, facecounter = 0; // copy obmat Mat4CpyMat4(scs->mat, ob->obmat); @@ -314,7 +323,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive int again = 0; do { - size_t j, k; + int j, k; int divs1 = tridivs[3 * facecounter + 0]; int divs2 = tridivs[3 * facecounter + 1]; //int divs3 = tridivs[3 * facecounter + 2]; @@ -409,7 +418,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive if(!smd->coll->bvhtree) { - smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getFaceArray(dm), dm->getNumFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 ); + smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 ); } return 1; } @@ -517,13 +526,13 @@ void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *faces, int } } -void smokeModifier_freeDomain(SmokeModifierData *smd) +static void smokeModifier_freeDomain(SmokeModifierData *smd) { if(smd->domain) { - // free visualisation buffers - if(smd->domain->view3d) - MEM_freeN(smd->domain->view3d); + if(smd->domain->shadow) + MEM_freeN(smd->domain->shadow); + smd->domain->shadow = NULL; if(smd->domain->fluid) smoke_free(smd->domain->fluid); @@ -541,7 +550,7 @@ void smokeModifier_freeDomain(SmokeModifierData *smd) } } -void smokeModifier_freeFlow(SmokeModifierData *smd) +static void smokeModifier_freeFlow(SmokeModifierData *smd) { if(smd->flow) { @@ -558,7 +567,7 @@ void smokeModifier_freeFlow(SmokeModifierData *smd) } } -void smokeModifier_freeCollision(SmokeModifierData *smd) +static void smokeModifier_freeCollision(SmokeModifierData *smd) { if(smd->coll) { @@ -583,17 +592,24 @@ void smokeModifier_freeCollision(SmokeModifierData *smd) } } +void smokeModifier_reset_turbulence(struct SmokeModifierData *smd) +{ + if(smd && smd->domain && smd->domain->wt) + { + smoke_turbulence_free(smd->domain->wt); + smd->domain->wt = NULL; + } +} + void smokeModifier_reset(struct SmokeModifierData *smd) { if(smd) { if(smd->domain) { - if(smd->domain->view3d) - MEM_freeN(smd->domain->view3d); - smd->domain->view3d = NULL; - - smd->domain->tex = NULL; + if(smd->domain->shadow) + MEM_freeN(smd->domain->shadow); + smd->domain->shadow = NULL; if(smd->domain->fluid) { @@ -601,23 +617,14 @@ void smokeModifier_reset(struct SmokeModifierData *smd) smd->domain->fluid = NULL; } - if(smd->domain->wt) - { - smoke_turbulence_free(smd->domain->wt); - smd->domain->wt = NULL; - } - - smd->domain->point_cache[0]->flag &= ~PTCACHE_SIMULATION_VALID; smd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED; - smd->domain->point_cache[0]->simframe= 0; - smd->domain->point_cache[0]->last_exact= 0; - - smd->domain->point_cache[1]->flag &= ~PTCACHE_SIMULATION_VALID; smd->domain->point_cache[1]->flag |= PTCACHE_OUTDATED; - smd->domain->point_cache[1]->simframe= 0; - smd->domain->point_cache[1]->last_exact= 0; - // printf("reset_domain\n"); + smokeModifier_reset_turbulence(smd); + + smd->time = -1; + + // printf("reset domain end\n"); } else if(smd->flow) { @@ -626,7 +633,7 @@ void smokeModifier_reset(struct SmokeModifierData *smd) { free_bvhtree_from_mesh(smd->flow->bvh); MEM_freeN(smd->flow->bvh); - } + } smd->flow->bvh = NULL; */ } @@ -685,22 +692,21 @@ void smokeModifier_createType(struct SmokeModifierData *smd) /* set some standard values */ smd->domain->fluid = NULL; + smd->domain->wt = NULL; smd->domain->eff_group = NULL; smd->domain->fluid_group = NULL; smd->domain->coll_group = NULL; smd->domain->maxres = 32; + smd->domain->amplify = 1; + smd->domain->omega = 1.0; smd->domain->alpha = -0.001; smd->domain->beta = 0.1; smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG; - smd->domain->diss_speed = 5; - smd->domain->strength = 2.0f; - smd->domain->amplify = 1; + smd->domain->strength = 2.0; smd->domain->noise = MOD_SMOKE_NOISEWAVE; - smd->domain->wt = NULL; - + smd->domain->diss_speed = 5; // init 3dview buffer - smd->domain->view3d = NULL; - smd->domain->tex = NULL; + smd->domain->viewsettings = 0; } else if(smd->type & MOD_SMOKE_TYPE_FLOW) { @@ -734,15 +740,320 @@ void smokeModifier_createType(struct SmokeModifierData *smd) } } -// forward declaration -void smoke_simulate_domain(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm); +// forward decleration +static void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct); +static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct); +static int get_lamp(Scene *scene, float *light) +{ + Base *base_tmp = NULL; + for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) + { + if(base_tmp->object->type == OB_LAMP) + { + Lamp *la = (Lamp *)base_tmp->object->data; + + if(la->type == LA_LOCAL) + { + VECCOPY(light, base_tmp->object->obmat[3]); + return 1; + } + } + } + return 0; +} +static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) +{ + SmokeDomainSettings *sds = smd->domain; + GroupObject *go = NULL; + Base *base = NULL; + + // do flows and fluids + if(1) + { + Object *otherobj = NULL; + ModifierData *md = NULL; + if(sds->fluid_group) // we use groups since we have 2 domains + go = sds->fluid_group->gobject.first; + else + base = scene->base.first; + while(base || go) + { + otherobj = NULL; + if(sds->fluid_group) + { + if(go->ob) + otherobj = go->ob; + } + else + otherobj = base->object; + if(!otherobj) + { + if(sds->fluid_group) + go = go->next; + else + base= base->next; + + continue; + } + + md = modifiers_findByType(otherobj, eModifierType_Smoke); + + // check for active smoke modifier + if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) + { + SmokeModifierData *smd2 = (SmokeModifierData *)md; + + // check for initialized smoke object + if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) + { + // we got nice flow object + SmokeFlowSettings *sfs = smd2->flow; + + if(sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected + { + ParticleSystem *psys = sfs->psys; + ParticleSettings *part=psys->part; + ParticleData *pa = NULL; + int p = 0; + float *density = smoke_get_density(sds->fluid); + float *bigdensity = smoke_turbulence_get_density(sds->wt); + float *heat = smoke_get_heat(sds->fluid); + float *velocity_x = smoke_get_velocity_x(sds->fluid); + float *velocity_y = smoke_get_velocity_y(sds->fluid); + float *velocity_z = smoke_get_velocity_z(sds->fluid); + unsigned char *obstacle = smoke_get_obstacle(sds->fluid); + int bigres[3]; + + // mostly copied from particle code + for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) + { + int cell[3]; + size_t i = 0; + size_t index = 0; + int badcell = 0; + if(pa->alive == PARS_KILLED) continue; + else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; + else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; + else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; + // VECCOPY(pos, pa->state.co); + // Mat4MulVecfl (ob->imat, pos); + // 1. get corresponding cell + get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, pa->state.co, cell, 0); + // check if cell is valid (in the domain boundary) + for(i = 0; i < 3; i++) + { + if((cell[i] > sds->res[i] - 1) || (cell[i] < 0)) + { + badcell = 1; + break; + } + } + if(badcell) + continue; + // 2. set cell values (heat, density and velocity) + index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); + if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index] & 2)) // this is inflow + { + // heat[index] += sfs->temp * 0.1; + // density[index] += sfs->density * 0.1; + heat[index] = sfs->temp; + density[index] = sfs->density; + + /* + velocity_x[index] = pa->state.vel[0]; + velocity_y[index] = pa->state.vel[1]; + velocity_z[index] = pa->state.vel[2]; + */ + + // obstacle[index] |= 2; + // we need different handling for the high-res feature + if(bigdensity) + { + // init all surrounding cells according to amplification, too + int i, j, k; + + smoke_turbulence_get_res(smd->domain->wt, bigres); + + for(i = 0; i < smd->domain->amplify + 1; i++) + for(j = 0; j < smd->domain->amplify + 1; j++) + for(k = 0; k < smd->domain->amplify + 1; k++) + { + index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k); + bigdensity[index] = sfs->density; + } + } + } + else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow + { + heat[index] = 0.f; + density[index] = 0.f; + velocity_x[index] = 0.f; + velocity_y[index] = 0.f; + velocity_z[index] = 0.f; + // we need different handling for the high-res feature + if(bigdensity) + { + // init all surrounding cells according to amplification, too + int i, j, k; + smoke_turbulence_get_res(smd->domain->wt, bigres); + + for(i = 0; i < smd->domain->amplify + 1; i++) + for(j = 0; j < smd->domain->amplify + 1; j++) + for(k = 0; k < smd->domain->amplify + 1; k++) + { + index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k); + bigdensity[index] = 0.f; + } + } + } // particles loop + } + } + else + { + /* + for() + { + // no psys + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist = FLT_MAX; + + BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh); + }*/ + } + } + } + if(sds->fluid_group) + go = go->next; + else + base= base->next; + } + } + + // do effectors + /* + if(sds->eff_group) + { + for(go = sds->eff_group->gobject.first; go; go = go->next) + { + if(go->ob) + { + if(ob->pd) + { + + } + } + } + } + */ + + // do collisions + if(1) + { + Object *otherobj = NULL; + ModifierData *md = NULL; + + if(sds->coll_group) // we use groups since we have 2 domains + go = sds->coll_group->gobject.first; + else + base = scene->base.first; + + while(base || go) + { + otherobj = NULL; + if(sds->coll_group) + { + if(go->ob) + otherobj = go->ob; + } + else + otherobj = base->object; + if(!otherobj) + { + if(sds->coll_group) + go = go->next; + else + base= base->next; + continue; + } + md = modifiers_findByType(otherobj, eModifierType_Smoke); + + // check for active smoke modifier + if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) + { + SmokeModifierData *smd2 = (SmokeModifierData *)md; + + if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) + { + // we got nice collision object + SmokeCollSettings *scs = smd2->coll; + size_t i, j; + unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid); + + for(i = 0; i < scs->numpoints; i++) + { + int badcell = 0; + size_t index = 0; + int cell[3]; + + // 1. get corresponding cell + get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, &scs->points[3 * i], cell, 0); + + // check if cell is valid (in the domain boundary) + for(j = 0; j < 3; j++) + if((cell[j] > sds->res[j] - 1) || (cell[j] < 0)) + { + badcell = 1; + break; + } + + if(badcell) + continue; + // 2. set cell values (heat, density and velocity) + index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); + + // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]); + // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index); + obstacles[index] = 1; + // for moving gobstacles + /* + const LbmFloat maxVelVal = 0.1666; + const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5; + + LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); + { + const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; + USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); + if(usqr>maxusqr) { + // cutoff at maxVelVal + for(int jj=0; jj<3; jj++) { + if(objvel[jj]>0.) objvel[jj] = maxVelVal; + if(objvel[jj]<0.) objvel[jj] = -maxVelVal; + } + } + } + const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); + const LbmVec oldov=objvel; // debug + objvel = vec2L((*pNormals)[n]) *dp; + */ + } + } + } + + if(sds->coll_group) + go = go->next; + else + base= base->next; + } + } +} void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { if((smd->type & MOD_SMOKE_TYPE_FLOW)) { - if(scene->r.cfra >= smd->time) - smokeModifier_init(smd, ob, scene, dm); + if(scene->r.cfra >= smd->time) + smokeModifier_init(smd, ob, scene, dm); if(scene->r.cfra > smd->time) { @@ -774,7 +1085,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM if(smd->coll->dm) smd->coll->dm->release(smd->coll->dm); - smd->coll->dm = CDDM_copy(dm, 0); + smd->coll->dm = CDDM_copy(dm, 1); // rigid movement support Mat4CpyMat4(smd->coll->mat_old, smd->coll->mat); @@ -788,515 +1099,128 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } else if(smd->type & MOD_SMOKE_TYPE_DOMAIN) { - PointCache *cache; + SmokeDomainSettings *sds = smd->domain; + float light[3]; + PointCache *cache = NULL; PTCacheID pid; - float timescale; - int cache_result = 0; + PointCache *cache_wt = NULL; + PTCacheID pid_wt; int startframe, endframe, framenr; - SmokeDomainSettings *sds = smd->domain; - float light[3] = {0.0,0.0,0.0}; - int have_lamp = 0; - - // printf("smd->type & MOD_SMOKE_TYPE_DOMAIN\n"); + float timescale; + int cache_result = 0, cache_result_wt = 0; framenr = scene->r.cfra; - cache = sds->point_cache[0]; + // printf("time: %d\n", scene->r.cfra); + if(framenr == smd->time) + return; + + cache = sds->point_cache[0]; BKE_ptcache_id_from_smoke(&pid, ob, smd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); - /* handle continuous simulation with the play button */ - if(BKE_ptcache_get_continue_physics()) - { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; - - if(!smokeModifier_init(smd, ob, scene, dm)) - return; - - if(!smd->domain->fluid) - return; - - smoke_simulate_domain(smd, scene, ob, dm); + cache_wt = sds->point_cache[1]; + BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd); - { - Base *base_tmp = NULL; - - for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) - { - if(base_tmp->object->type == OB_LAMP) - { - Lamp *la = (Lamp *)base_tmp->object->data; - - if(la->type == LA_LOCAL) - { - VECCOPY(light, base_tmp->object->obmat[3]); - have_lamp = 1; - break; - } - } - } - } - - smoke_prepare_View(smd, (float)framenr, light, have_lamp); - - return; + if(!smd->domain->fluid) + { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED); } - + if(framenr < startframe) - { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; + return; - // we got back in time, reset smoke in this case (TODO: use cache later) - // smd->time = scene->r.cfra; - // smokeModifier_reset(smd); + if(framenr > endframe) + return; + if(!smd->domain->fluid && (framenr != startframe)) return; - } - else if(framenr > endframe) - { - framenr = endframe; - } - if(!(cache->flag & PTCACHE_SIMULATION_VALID)) - { - // printf("reseting\n"); - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - } - + // printf("startframe: %d, framenr: %d\n", startframe, framenr); + if(!smokeModifier_init(smd, ob, scene, dm)) + { + printf("bad smokeModifier_init\n"); return; - - if(!smd->domain->fluid) - return; + } /* try to read from cache */ - cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); + cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); // printf("cache_result: %d\n", cache_result); if(cache_result == PTCACHE_READ_EXACT) { - SmokeDomainSettings *sds = smd->domain; - cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; - sds->v3dnum = framenr; - // printf("PTCACHE_READ_EXACT\n"); - return; + if(sds->wt) + { + cache_result_wt = BKE_ptcache_read_cache(&pid_wt, (float)framenr, scene->r.frs_sec); + + if(cache_result_wt == PTCACHE_READ_EXACT) + { + cache_wt->flag |= PTCACHE_SIMULATION_VALID; + cache_wt->simframe= framenr; + } } - else if(cache_result==PTCACHE_READ_OLD) - { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); - - // printf("PTCACHE_READ_OLD\n"); - - cache->flag |= PTCACHE_SIMULATION_VALID; - } - else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) - { - /* if baked and nothing in cache, do nothing */ - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; - - // printf("PTCACHE_BAKED\n"); return; } - else if((cache_result==0) && (startframe!=framenr) && !(cache->flag & PTCACHE_SIMULATION_VALID)) - { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; - return; - } + tstart(); + + smoke_calc_domain(scene, ob, smd); + // set new time + smd->time = scene->r.cfra; + /* do simulation */ // low res cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; - smoke_simulate_domain(smd, scene, ob, dm); + // simulate the actual smoke (c++ code in intern/smoke) + // DG: interesting commenting this line + deactivating loading of noise files + if(framenr!=startframe) + smoke_step(sds->fluid, smd->time); - if(sds->wt) - smoke_turbulence_step(sds->wt, sds->fluid); + // create shadows before writing cache so we get nice shadows for sstartframe, too + if(get_lamp(scene, light)) + smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); + + BKE_ptcache_write_cache(&pid, framenr); + if(sds->wt) { - Base *base_tmp = NULL; + if(framenr!=startframe) + smoke_turbulence_step(sds->wt, sds->fluid); - for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) - { - if(base_tmp->object->type == OB_LAMP) - { - Lamp *la = (Lamp *)base_tmp->object->data; - - if(la->type == LA_LOCAL) - { - VECCOPY(light, base_tmp->object->obmat[3]); - have_lamp = 1; - break; - } - } - } + cache_wt->flag |= PTCACHE_SIMULATION_VALID; + cache_wt->simframe= framenr; + BKE_ptcache_write_cache(&pid_wt, framenr); } - smoke_prepare_View(smd, (float)framenr, light, have_lamp); - - BKE_ptcache_write_cache(&pid, framenr); - - // printf("Writing cache_low, %d\n", framenr); - - tend(); - // printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); + printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); } } -void smoke_simulate_domain(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) +static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct) { - GroupObject *go = NULL; - Base *base = NULL; - SmokeDomainSettings *sds = smd->domain; - - tstart(); - - if(sds->flags & MOD_SMOKE_DISSOLVE) - smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); - - // do flows and fluids - if(1) - { - Object *otherobj = NULL; - ModifierData *md = NULL; - - if(sds->fluid_group) // we use groups since we have 2 domains - go = sds->fluid_group->gobject.first; - else - base = scene->base.first; - - while(base || go) - { - otherobj = NULL; - - if(sds->fluid_group) - { - if(go->ob) - otherobj = go->ob; - } - else - otherobj = base->object; - - if(!otherobj) - { - if(sds->fluid_group) - go = go->next; - else - base= base->next; - - continue; - } - - md = modifiers_findByType(otherobj, eModifierType_Smoke); - - // check for active smoke modifier - if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) - { - SmokeModifierData *smd2 = (SmokeModifierData *)md; - - // check for initialized smoke object - if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) - { - // we got nice flow object - SmokeFlowSettings *sfs = smd2->flow; - - if(sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected - { - ParticleSystem *psys = sfs->psys; - ParticleSettings *part=psys->part; - ParticleData *pa = NULL; - int p = 0; - float *density = smoke_get_density(sds->fluid); - // float *bigdensity = smoke_turbulence_get_density(sds->wt); - float *heat = smoke_get_heat(sds->fluid); - float *velocity_x = smoke_get_velocity_x(sds->fluid); - float *velocity_y = smoke_get_velocity_y(sds->fluid); - float *velocity_z = smoke_get_velocity_z(sds->fluid); - unsigned char *obstacle = smoke_get_obstacle(sds->fluid); - - // debug printf("found flow psys\n"); - - // mostly copied from particle code - for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) - { - int cell[3]; - size_t i = 0; - size_t index = 0; - int badcell = 0; - - if(pa->alive == PARS_KILLED) continue; - else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; - else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; - - // VECCOPY(pos, pa->state.co); - // Mat4MulVecfl (ob->imat, pos); - - // 1. get corresponding cell - get_cell(sds->p0, sds->res, sds->dx, pa->state.co, cell, 0); - - // check if cell is valid (in the domain boundary) - for(i = 0; i < 3; i++) - { - if((cell[i] > sds->res[i] - 1) || (cell[i] < 0)) - { - badcell = 1; - break; - } - } - - if(badcell) - continue; - - // 2. set cell values (heat, density and velocity) - index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - - if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index] & 2)) // this is inflow - { - // heat[index] += sfs->temp * 0.1; - // density[index] += sfs->density * 0.1; - - heat[index] = sfs->temp; - density[index] = sfs->density; - - /* - velocity_x[index] = pa->state.vel[0]; - velocity_y[index] = pa->state.vel[1]; - velocity_z[index] = pa->state.vel[2]; - */ - obstacle[index] |= 2; - } - else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow - { - heat[index] = 0.f; - density[index] = 0.f; - velocity_x[index] = 0.f; - velocity_y[index] = 0.f; - velocity_z[index] = 0.f; - } - } - } - else - { - /* - for() - { - // no psys - BVHTreeNearest nearest; - - nearest.index = -1; - nearest.dist = FLT_MAX; - - BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh); - }*/ - } - } - } - - if(sds->fluid_group) - go = go->next; - else - base= base->next; - } - } - - // do effectors - /* - if(sds->eff_group) - { - for(go = sds->eff_group->gobject.first; go; go = go->next) - { - if(go->ob) - { - if(ob->pd) - { - - } - } - } - } - */ - - // do collisions - if(1) - { - Object *otherobj = NULL; - ModifierData *md = NULL; - - if(sds->coll_group) // we use groups since we have 2 domains - go = sds->coll_group->gobject.first; - else - base = scene->base.first; - - while(base || go) - { - otherobj = NULL; - - if(sds->coll_group) - { - if(go->ob) - otherobj = go->ob; - } - else - otherobj = base->object; - - if(!otherobj) - { - if(sds->coll_group) - go = go->next; - else - base= base->next; - - continue; - } - - md = modifiers_findByType(otherobj, eModifierType_Smoke); - - // check for active smoke modifier - if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) - { - SmokeModifierData *smd2 = (SmokeModifierData *)md; - - if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) - { - // we got nice collision object - SmokeCollSettings *scs = smd2->coll; - size_t i, j; - unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid); - - for(i = 0; i < scs->numpoints; i++) - { - int badcell = 0; - size_t index = 0; - int cell[3]; - - // 1. get corresponding cell - get_cell(sds->p0, sds->res, sds->dx, &scs->points[3 * i], cell, 0); - - // check if cell is valid (in the domain boundary) - for(j = 0; j < 3; j++) - if((cell[j] > sds->res[j] - 1) || (cell[j] < 0)) - { - badcell = 1; - break; - } - - if(badcell) - continue; - - // 2. set cell values (heat, density and velocity) - index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - - // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]); - // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index); - - obstacles[index] = 1; - - // for moving gobstacles - /* - const LbmFloat maxVelVal = 0.1666; - const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5; - - LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); { - const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; - USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); - if(usqr>maxusqr) { - // cutoff at maxVelVal - for(int jj=0; jj<3; jj++) { - if(objvel[jj]>0.) objvel[jj] = maxVelVal; - if(objvel[jj]<0.) objvel[jj] = -maxVelVal; - } - } } - - const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); - const LbmVec oldov=objvel; // debug - objvel = vec2L((*pNormals)[n]) *dp; - */ - } - } - } - - if(sds->coll_group) - go = go->next; - else - base= base->next; - } - } - - // set new time - smd->time = scene->r.cfra; - - // simulate the actual smoke (c++ code in intern/smoke) - smoke_step(sds->fluid, smd->time); - } - -static int calc_voxel_transp(float *input, int res[3], int *pixel, float *tRay) - { const size_t index = smoke_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]); // T_ray *= T_vox - *tRay *= input[index*4]; - - return *tRay; - } - -// forward decleration -void smoke_calc_transparency(float *result, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb); - -// update necessary information for 3dview -void smoke_prepare_View(SmokeModifierData *smd, float framenr, float *light, int have_light) -{ - float *density = NULL; - int x, y, z; - size_t cells, i; - SmokeDomainSettings *sds = smd->domain; - - // update 3dview - density = smoke_get_density(smd->domain->fluid); - for(x = 0; x < smd->domain->res[0]; x++) - for(y = 0; y < smd->domain->res[1]; y++) - for(z = 0; z < smd->domain->res[2]; z++) - { - size_t index; - - index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z); - // Transparency computation - // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4 - // T_vox = exp(-C_ext * h) - // C_ext/sigma_t = density * C_ext - smd->domain->view3d[index * 4] = smd->domain->view3d[index * 4 + 1] = - smd->domain->view3d[index * 4 + 2] = exp(-density[index] * 7.0 * smd->domain->dx); - smd->domain->view3d[index * 4 + 3] = 1.0 - smd->domain->view3d[index * 4]; - - } - - if(have_light) + *tRay *= exp(input[index]*correct); + + if(result[index] < 0.0f) { - smoke_calc_transparency(sds->view3d, sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp); +#pragma omp critical + result[index] = *tRay; + } - cells = smd->domain->res[0]*smd->domain->res[1]*smd->domain->res[2]; - for(i = 0; i < cells; i++) -{ - smd->domain->view3d[i * 4] = smd->domain->view3d[i * 4 + 1] = - smd->domain->view3d[i * 4 + 2] = smd->domain->view3d[i * 4 + 1] * smd->domain->view3d[i * 4 + 0]; -} -} - smd->domain->v3dnum = framenr; + return *tRay; } long long smoke_get_mem_req(int xres, int yres, int zres, int amplify) @@ -1317,7 +1241,7 @@ long long smoke_get_mem_req(int xres, int yres, int zres, int amplify) return totalMB; } -static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, float *tRay, bresenham_callback cb, float *input, int res[3]) +static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, float *tRay, bresenham_callback cb, float *result, float *input, int res[3], float correct) { int dx, dy, dz, i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2; int pixel[3]; @@ -1344,8 +1268,8 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f err_1 = dy2 - l; err_2 = dz2 - l; for (i = 0; i < l; i++) { - if(cb(input, res, pixel, tRay) < 0.0) - return; + if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) + break; if (err_1 > 0) { pixel[1] += y_inc; err_1 -= dx2; @@ -1362,8 +1286,8 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f err_1 = dx2 - m; err_2 = dz2 - m; for (i = 0; i < m; i++) { - if(cb(input, res, pixel, tRay) < 0.0f) - return; + if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) + break; if (err_1 > 0) { pixel[0] += x_inc; err_1 -= dy2; @@ -1380,8 +1304,8 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f err_1 = dy2 - n; err_2 = dx2 - n; for (i = 0; i < n; i++) { - if(cb(input, res, pixel, tRay) < 0.0f) - return; + if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) + break; if (err_1 > 0) { pixel[1] += y_inc; err_1 -= dz2; @@ -1395,7 +1319,7 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f pixel[2] += z_inc; } } - cb(input, res, pixel, tRay); + cb(result, input, res, pixel, tRay, correct); } static void get_cell(float *p0, int res[3], float dx, float *pos, int *cell, int correct) @@ -1419,12 +1343,12 @@ static void get_cell(float *p0, int res[3], float dx, float *pos, int *cell, int } } -void smoke_calc_transparency(float *result, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb) +static void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct) { int x, y, z; float bv[6]; - // x + memset(result, -1, sizeof(float)*res[0]*res[1]*res[2]); // x bv[0] = p0[0]; bv[1] = p1[0]; // y @@ -1434,7 +1358,7 @@ void smoke_calc_transparency(float *result, float *p0, float *p1, int res[3], fl bv[4] = p0[2]; bv[5] = p1[2]; -// #pragma omp parallel for schedule(static) private(y, z) +#pragma omp parallel for schedule(static) private(y, z) for(x = 0; x < res[0]; x++) for(y = 0; y < res[1]; y++) for(z = 0; z < res[2]; z++) @@ -1447,6 +1371,8 @@ void smoke_calc_transparency(float *result, float *p0, float *p1, int res[3], fl index = smoke_get_index(x, res[0], y, res[1], z); + if(result[index] >= 0.0f) + continue; voxelCenter[0] = p0[0] + dx * x + dx * 0.5; voxelCenter[1] = p0[1] + dx * y + dx * 0.5; voxelCenter[2] = p0[2] + dx * z + dx * 0.5; @@ -1463,10 +1389,11 @@ void smoke_calc_transparency(float *result, float *p0, float *p1, int res[3], fl get_cell(p0, res, dx, light, cell, 1); } - bresenham_linie_3D(cell[0], cell[1], cell[2], x, y, z, &tRay, cb, result, res); + bresenham_linie_3D(cell[0], cell[1], cell[2], x, y, z, &tRay, cb, result, input, res, correct); // convention -> from a RGBA float array, use G value for tRay - result[index*4 + 1] = tRay; +// #pragma omp critical + result[index] = tRay; } } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 094ea37afff..2e62ecb8af3 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -58,7 +58,6 @@ variables on the UI for now #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" /* here is the softbody struct */ -#include "DNA_particle_types.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -77,7 +76,6 @@ variables on the UI for now #include "BKE_global.h" #include "BKE_key.h" #include "BKE_object.h" -#include "BKE_particle.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -495,32 +493,21 @@ static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *h while (base) { /*Only proceed for mesh object in same layer */ if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) { - int particles=0; ob= base->object; if((vertexowner) && (ob == vertexowner)) { - if(vertexowner->soft->particles){ - particles=1; - } - else { - /* if vertexowner is given we don't want to check collision with owner object */ - base = base->next; - continue; - } + /* if vertexowner is given we don't want to check collision with owner object */ + base = base->next; + continue; } /*+++ only with deflecting set */ if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == 0) { DerivedMesh *dm= NULL; - if(particles) { - dm = psys_get_modifier(ob,psys_get_current(ob))->dm; - } - else { - if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */ - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); - else - dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); - } + if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */ + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + else + dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); if(dm){ ccd_Mesh *ccdmesh = ccd_mesh_make(ob, dm); @@ -3572,107 +3559,6 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob) } } - -static void springs_from_particles(Object *ob) -{ - ParticleSystem *psys; - ParticleSystemModifierData *psmd=0; - ParticleData *pa=0; - HairKey *key=0; - SoftBody *sb; - BodyPoint *bp; - BodySpring *bs; - int a,k; - float hairmat[4][4]; - - if(ob && ob->soft && ob->soft->particles) { - psys= ob->soft->particles; - sb= ob->soft; - psmd = psys_get_modifier(ob, psys); - - bp= sb->bpoint; - for(a=0, pa=psys->particles; a<psys->totpart; a++, pa++) { - for(k=0, key=pa->hair; k<pa->totkey; k++, bp++, key++) { - VECCOPY(bp->origS, key->co); - - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); - - Mat4MulVecfl(hairmat, bp->origS); - } - } - - for(a=0, bs=sb->bspring; a<sb->totspring; a++, bs++) - bs->len= VecLenf(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS); - } -} - -static void particles_to_softbody(Scene *scene, Object *ob) -{ - SoftBody *sb; - BodyPoint *bp; - BodySpring *bs; - ParticleData *pa; - HairKey *key; - ParticleSystem *psys= ob->soft->particles; - float goalfac; - int a, k, curpoint; - int totpoint= psys_count_keys(psys); - int totedge= totpoint-psys->totpart; - - /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */ - renew_softbody(scene, ob, totpoint, totedge); - - /* find first BodyPoint index for each particle */ - if(psys->totpart > 0) { - psys->particles->bpi = 0; - for(a=1, pa=psys->particles+1; a<psys->totpart; a++, pa++) - pa->bpi = (pa-1)->bpi + (pa-1)->totkey; - } - - /* we always make body points */ - sb= ob->soft; - bp= sb->bpoint; - bs= sb->bspring; - goalfac= ABS(sb->maxgoal - sb->mingoal); - - if((ob->softflag & OB_SB_GOAL)) { - for(a=0, pa=psys->particles; a<psys->totpart; a++, pa++) { - for(k=0, key=pa->hair; k<pa->totkey; k++,bp++,key++) { - if(k) { - bp->goal= key->weight; - bp->goal= sb->mingoal + bp->goal*goalfac; - bp->goal= (float)pow(bp->goal, 4.0f); - } - else{ - /* hair roots are allways fixed fully to goal */ - bp->goal= 1.0f; - } - } - } - } - - bp= sb->bpoint; - curpoint=0; - for(a=0, pa=psys->particles; a<psys->totpart; a++, curpoint++, pa++) { - for(k=0; k<pa->totkey-1; k++,bs++,curpoint++) { - bs->v1=curpoint; - bs->v2=curpoint+1; - bs->strength= 1.0; - bs->order=1; - } - } - - build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */ - /* insert *other second order* springs if desired */ - if(sb->secondspring > 0.0000001f) { - add_2nd_order_springs(ob,sb->secondspring*10.0); /* exploits the the first run of build_bps_springlist(ob);*/ - build_bps_springlist(ob); /* yes we need to do it again*/ - } - springs_from_particles(ob); /* write the 'rest'-lenght of the springs */ - if(ob->softflag & OB_SB_SELF) - calculate_collision_balls(ob); -} - /* copies softbody result back in object */ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, int local) { @@ -3796,44 +3682,16 @@ void sbSetInterruptCallBack(int (*f)(void)) static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts) { - ParticleSystemModifierData *psmd= NULL; - ParticleData *pa= NULL; - HairKey *key= NULL; BodyPoint *bp; - float hairmat[4][4]; int a; - /* update the vertex locations */ - if(sb->particles && sb->particles->totpart>0) { - psmd= psys_get_modifier(ob,sb->particles); - - pa= sb->particles->particles; - key= pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { /* store where goals are now */ VECCOPY(bp->origS, bp->origE); /* copy the position of the goals at desired end time */ - if(sb->particles) { - if(key == pa->hair + pa->totkey) { - pa++; - key = pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - VECCOPY(bp->origE, key->co); - Mat4MulVecfl(hairmat,bp->origE); - - key++; - } - else{ - VECCOPY(bp->origE, vertexCos[a]); - /* vertexCos came from local world, go global */ - Mat4MulVecfl(ob->obmat, bp->origE); - } + VECCOPY(bp->origE, vertexCos[a]); + /* vertexCos came from local world, go global */ + Mat4MulVecfl(ob->obmat, bp->origE); /* just to be save give bp->origT a defined value will be calulated in interpolate_exciter()*/ VECCOPY(bp->origT, bp->origE); @@ -3842,37 +3700,12 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts) { - ParticleSystemModifierData *psmd= NULL; - HairKey *key= NULL; - ParticleData *pa= NULL; BodyPoint *bp; - float hairmat[4][4]; int a; - if(sb->particles && sb->particles->totpart>0) { - psmd= psys_get_modifier(ob, sb->particles); - pa= sb->particles->particles; - key= pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { - if(sb->particles) { - if(key == pa->hair + pa->totkey) { - pa++; - key = pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - VECCOPY(bp->pos, key->co); - Mat4MulVecfl(hairmat, bp->pos); - key++; - } - else { - VECCOPY(bp->pos, vertexCos[a]); - Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/ - } + VECCOPY(bp->pos, vertexCos[a]); + Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/ VECCOPY(bp->origS, bp->pos); VECCOPY(bp->origE, bp->pos); VECCOPY(bp->origT, bp->pos); @@ -3901,20 +3734,18 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int sb_new_scratch(sb); /* make a new */ sb->scratch->needstobuildcollider=1; - if((sb->particles)==0) { - /* copy some info to scratch */ - switch(ob->type) { - case OB_MESH: - if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob); - break; - case OB_LATTICE: - break; - case OB_CURVE: - case OB_SURF: - break; - default: - break; - } + /* copy some info to scratch */ + switch(ob->type) { + case OB_MESH: + if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob); + break; + case OB_LATTICE: + break; + case OB_CURVE: + case OB_SURF: + break; + default: + break; } } @@ -4050,8 +3881,6 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) /* simulates one step. framenr is in frames */ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts) { - ParticleSystemModifierData *psmd=0; - ParticleData *pa=0; SoftBody *sb= ob->soft; PointCache *cache; PTCacheID pid; @@ -4080,7 +3909,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i if(framenr < startframe) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; - cache->last_exact= 0; + //cache->last_exact= 0; return; } @@ -4092,25 +3921,20 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i if(sb->bpoint == NULL || ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) { - if(sb->particles){ - particles_to_softbody(scene, ob); - } - else { - switch(ob->type) { - case OB_MESH: - mesh_to_softbody(scene, ob); - break; - case OB_LATTICE: - lattice_to_softbody(scene, ob); - break; - case OB_CURVE: - case OB_SURF: - curve_surf_to_softbody(scene, ob); - break; - default: - renew_softbody(scene, ob, numVerts, 0); - break; - } + switch(ob->type) { + case OB_MESH: + mesh_to_softbody(scene, ob); + break; + case OB_LATTICE: + lattice_to_softbody(scene, ob); + break; + case OB_CURVE: + case OB_SURF: + curve_surf_to_softbody(scene, ob); + break; + default: + renew_softbody(scene, ob, numVerts, 0); + break; } softbody_update_positions(ob, sb, vertexCos, numVerts); @@ -4128,8 +3952,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i softbody_update_positions(ob, sb, vertexCos, numVerts); softbody_step(scene, ob, sb, dtime); - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, 0); + softbody_to_object(ob, vertexCos, numVerts, 0); return; } @@ -4137,25 +3960,33 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i /* still no points? go away */ if(sb->totpoint==0) return; - if(sb->particles){ - psmd= psys_get_modifier(ob, sb->particles); - pa= sb->particles->particles; + if(framenr == startframe) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + + /* first frame, no simulation to do, just set the positions */ + softbody_update_positions(ob, sb, vertexCos, numVerts); + + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->flag &= ~PTCACHE_REDO_NEEDED; + return; } /* try to read from cache */ cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { - cache->flag |= PTCACHE_SIMULATION_VALID; + softbody_to_object(ob, vertexCos, numVerts, sb->local); + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, sb->local); + if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) + BKE_ptcache_write_cache(&pid, framenr); return; } else if(cache_result==PTCACHE_READ_OLD) { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); cache->flag |= PTCACHE_SIMULATION_VALID; } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { @@ -4166,41 +3997,23 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i return; } - if(framenr == startframe) { - if(cache->flag & PTCACHE_REDO_NEEDED) { - softbody_update_positions(ob, sb, vertexCos, numVerts); - softbody_reset(ob, sb, vertexCos, numVerts); - cache->flag &= ~PTCACHE_REDO_NEEDED; - } - /* first frame, no simulation to do, just set the positions */ - softbody_update_positions(ob, sb, vertexCos, numVerts); + /* if on second frame, write cache for first frame */ + if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) + BKE_ptcache_write_cache(&pid, startframe); - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= framenr; + softbody_update_positions(ob, sb, vertexCos, numVerts); - /* don't write cache on first frame, but on second frame write - * cache for frame 1 and 2 */ - } - else { - /* if on second frame, write cache for first frame */ - if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write_cache(&pid, startframe); + /* checking time: */ + dtime = framedelta*timescale; - softbody_update_positions(ob, sb, vertexCos, numVerts); + softbody_step(scene, ob, sb, dtime); - /* do simulation */ - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= framenr; - - /* checking time: */ - dtime = framedelta*timescale; + softbody_to_object(ob, vertexCos, numVerts, 0); - softbody_step(scene, ob, sb, dtime); - - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, 0); + /* do simulation */ + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; - BKE_ptcache_write_cache(&pid, framenr); - } + BKE_ptcache_write_cache(&pid, framenr); } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index c6f9db6fda9..2d5d8dad7a8 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -34,7 +34,7 @@ void sound_init() { AUD_Specs specs; - int device, buffersize, success; + int device, buffersize; device = U.audiodevice; buffersize = U.mixbufsize; @@ -54,15 +54,8 @@ void sound_init() if(specs.channels <= AUD_CHANNELS_INVALID) specs.channels = AUD_CHANNELS_STEREO; - if(!AUD_init(device, specs, buffersize)) { - if(device == AUD_SDL_DEVICE) - success= AUD_init(AUD_OPENAL_DEVICE, specs, AUD_DEFAULT_BUFFER_SIZE*4); - else - success= AUD_init(AUD_SDL_DEVICE, specs, AUD_DEFAULT_BUFFER_SIZE*4); - - if(!success) - AUD_init(AUD_NULL_DEVICE, specs, buffersize); - } + if(!AUD_init(device, specs, buffersize)) + AUD_init(AUD_NULL_DEVICE, specs, buffersize); } void sound_exit() @@ -86,11 +79,11 @@ struct bSound* sound_new_file(struct Main *main, char* filename) sound = alloc_libblock(&main->sound, ID_SO, filename+len); strcpy(sound->name, filename); - sound->type = SOUND_TYPE_FILE; +// XXX unused currently sound->type = SOUND_TYPE_FILE; sound_load(main, sound); - if(!sound->snd_sound) + if(!sound->handle) { free_libblock(&main->sound, sound); sound = NULL; @@ -116,7 +109,7 @@ struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source) sound_load(CTX_data_main(C), sound); - if(!sound->snd_sound) + if(!sound->handle) { free_libblock(&CTX_data_main(C)->sound, sound); sound = NULL; @@ -142,7 +135,7 @@ struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, floa sound_load(CTX_data_main(C), sound); - if(!sound->snd_sound) + if(!sound->handle) { free_libblock(&CTX_data_main(C)->sound, sound); sound = NULL; @@ -169,22 +162,35 @@ void sound_cache(struct bSound* sound, int ignore) if(sound->cache && !ignore) AUD_unload(sound->cache); - sound->cache = AUD_bufferSound(sound->snd_sound); + sound->cache = AUD_bufferSound(sound->handle); + sound->changed++; +} + +void sound_delete_cache(struct bSound* sound) +{ + if(sound->cache) + { + AUD_unload(sound->cache); + sound->cache = NULL; + } } void sound_load(struct Main *main, struct bSound* sound) { if(sound) { - if(sound->snd_sound) + if(sound->handle) { - AUD_unload(sound->snd_sound); - sound->snd_sound = NULL; + AUD_unload(sound->handle); + sound->handle = NULL; } +// XXX unused currently +#if 0 switch(sound->type) { case SOUND_TYPE_FILE: +#endif { char fullpath[FILE_MAX]; char *path; @@ -198,32 +204,32 @@ void sound_load(struct Main *main, struct bSound* sound) if(sound->id.lib) path = sound->id.lib->filename; else - path = main ? main->name : NULL; + path = main ? main->name : G.sce; BLI_convertstringcode(fullpath, path); /* but we need a packed file then */ if (pf) - sound->snd_sound = AUD_loadBuffer((unsigned char*) pf->data, pf->size); + sound->handle = AUD_loadBuffer((unsigned char*) pf->data, pf->size); /* or else load it from disk */ else - sound->snd_sound = AUD_load(fullpath); + sound->handle = AUD_load(fullpath); + } // XXX +// XXX unused currently +#if 0 break; } case SOUND_TYPE_BUFFER: - if(sound->child_sound && sound->child_sound->snd_sound) - sound->snd_sound = AUD_bufferSound(sound->child_sound->snd_sound); + if(sound->child_sound && sound->child_sound->handle) + sound->handle = AUD_bufferSound(sound->child_sound->handle); break; case SOUND_TYPE_LIMITER: - if(sound->child_sound && sound->child_sound->snd_sound) - sound->snd_sound = AUD_limitSound(sound->child_sound, sound->start, sound->end); + if(sound->child_sound && sound->child_sound->handle) + sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end); break; } - - if(sound->cache) - { - - } +#endif + sound->changed++; } } @@ -235,33 +241,36 @@ void sound_free(struct bSound* sound) sound->packedfile = NULL; } - if(sound->snd_sound) + if(sound->handle) { - AUD_unload(sound->snd_sound); - sound->snd_sound = NULL; + AUD_unload(sound->handle); + sound->handle = NULL; } } void sound_unlink(struct bContext *C, struct bSound* sound) { - bSound *snd; Scene *scene; SoundHandle *handle; +// XXX unused currently +#if 0 + bSound *snd; for(snd = CTX_data_main(C)->sound.first; snd; snd = snd->id.next) { if(snd->child_sound == sound) { snd->child_sound = NULL; - if(snd->snd_sound) + if(snd->handle) { - AUD_unload(sound->snd_sound); - snd->snd_sound = NULL; + AUD_unload(sound->handle); + snd->handle = NULL; } sound_unlink(C, snd); } } +#endif for(scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) { @@ -367,7 +376,7 @@ void sound_update_playing(struct bContext *C) float diff = AUD_getPosition(handle->handle) * fps - cfra + handle->startframe; if(diff < 0.0) diff = -diff; - if(diff > 1.0f) + if(diff > FPS/2.0) { action = 2; } @@ -379,9 +388,9 @@ void sound_update_playing(struct bContext *C) { if(handle->state == AUD_STATUS_INVALID) { - if(handle->source && handle->source->snd_sound) + if(handle->source && handle->source->handle) { - AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->snd_sound, handle->frameskip / fps, (handle->frameskip + handle->endframe - handle->startframe)/fps); + AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->handle, handle->frameskip / fps, (handle->frameskip + handle->endframe - handle->startframe)/fps); handle->handle = AUD_play(limiter, 1); AUD_unload(limiter); if(handle->handle) @@ -420,10 +429,10 @@ void sound_scrub(struct bContext *C) { if(cfra >= handle->startframe && cfra < handle->endframe && !handle->mute) { - if(handle->source && handle->source->snd_sound) + if(handle->source && handle->source->handle) { int frameskip = handle->frameskip + cfra - handle->startframe; - AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->snd_sound, frameskip / fps, (frameskip + 1)/fps); + AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->handle, frameskip / fps, (frameskip + 1)/fps); AUD_play(limiter, 0); AUD_unload(limiter); } @@ -446,7 +455,7 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int e for(handle = scene->sound_handles.first; handle; handle = handle->next) { - if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->snd_sound) + if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->handle) { frameskip = handle->frameskip; s = handle->startframe - start; @@ -458,7 +467,7 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int e s = 0; } - limiter = AUD_limitSound(handle->source->snd_sound, frameskip / fps, e / fps); + limiter = AUD_limitSound(handle->source->handle, frameskip / fps, e / fps); delayer = AUD_delaySound(limiter, s / fps); AUD_playDevice(mixdown, delayer); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 8e3d59bbc58..350b0acba9d 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -37,14 +37,22 @@ #include "BLI_blenlib.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_controller_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "DNA_text_types.h" -#include "BKE_utildefines.h" -#include "BKE_text.h" -#include "BKE_library.h" +#include "BKE_depsgraph.h" #include "BKE_global.h" +#include "BKE_library.h" #include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_text.h" +#include "BKE_utildefines.h" #ifndef DISABLE_PYTHON #include "BPY_extern.h" @@ -122,8 +130,10 @@ undo position static void txt_pop_first(Text *text); static void txt_pop_last(Text *text); static void txt_undo_add_op(Text *text, int op); -static void txt_undo_add_block(Text *text, int op, char *buf); +static void txt_undo_add_block(Text *text, int op, const char *buf); static void txt_delete_line(Text *text, TextLine *line); +static void txt_delete_sel (Text *text); +static void txt_make_dirty (Text *text); /***/ @@ -451,6 +461,109 @@ Text *copy_text(Text *ta) return tan; } +void unlink_text(Main *bmain, Text *text) +{ + bScreen *scr; + ScrArea *area; + SpaceLink *sl; + Scene *scene; + Object *ob; + bController *cont; + bConstraint *con; + short update; + + /* dome */ + for(scene=bmain->scene.first; scene; scene=scene->id.next) + if(scene->r.dometext == text) + scene->r.dometext = NULL; + + for(ob=bmain->object.first; ob; ob=ob->id.next) { + /* game controllers */ + for(cont=ob->controllers.first; cont; cont=cont->next) { + if(cont->type==CONT_PYTHON) { + bPythonCont *pc; + + pc= cont->data; + if(pc->text==text) pc->text= NULL; + } + } + + /* pyconstraints */ + update = 0; + + if(ob->type==OB_ARMATURE && ob->pose) { + bPoseChannel *pchan; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + for(con = pchan->constraints.first; con; con=con->next) { + if(con->type==CONSTRAINT_TYPE_PYTHON) { + bPythonConstraint *data = con->data; + if (data->text==text) data->text = NULL; + update = 1; + + } + } + } + } + + for(con = ob->constraints.first; con; con=con->next) { + if(con->type==CONSTRAINT_TYPE_PYTHON) { + bPythonConstraint *data = con->data; + if (data->text==text) data->text = NULL; + update = 1; + } + } + + if(update) + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + } + + /* pynodes */ + // XXX nodeDynamicUnlinkText(&text->id); + + /* text space */ + for(scr= bmain->screen.first; scr; scr= scr->id.next) { + for(area= scr->areabase.first; area; area= area->next) { + for(sl= area->spacedata.first; sl; sl= sl->next) { + if(sl->spacetype==SPACE_TEXT) { + SpaceText *st= (SpaceText*) sl; + + if(st->text==text) { + st->text= NULL; + st->top= 0; + } + } + } + } + } + + text->id.us= 0; +} + +void clear_text(Text *text) /* called directly from rna */ +{ + int oldstate; + + oldstate = txt_get_undostate( ); + txt_set_undostate( 1 ); + txt_sel_all( text ); + txt_delete_sel(text); + txt_set_undostate( oldstate ); + + txt_make_dirty(text); +} + +void write_text(Text *text, char *str) /* called directly from rna */ +{ + int oldstate; + + oldstate = txt_get_undostate( ); + txt_insert_buf( text, str ); + txt_move_eof( text, 0 ); + txt_set_undostate( oldstate ); + + txt_make_dirty(text); +} + /*****************************/ /* Editing utility functions */ /*****************************/ @@ -1228,7 +1341,7 @@ char *txt_sel_to_buf (Text *text) return buf; } -void txt_insert_buf(Text *text, char *in_buffer) +void txt_insert_buf(Text *text, const char *in_buffer) { int i=0, l=0, j, u, len; TextLine *add; @@ -1457,7 +1570,7 @@ static void txt_undo_add_op(Text *text, int op) text->undo_buf[text->undo_pos+1]= 0; } -static void txt_undo_add_block(Text *text, int op, char *buf) +static void txt_undo_add_block(Text *text, int op, const char *buf) { int length; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 61f62b2222d..d7616ec8a9a 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -38,7 +38,7 @@ #include "PIL_dynlib.h" -#include "MTC_matrixops.h" + #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -368,9 +368,9 @@ int do_colorband(ColorBand *coba, float in, float out[4]) CLAMP(fac, 0.0f, 1.0f); if(coba->ipotype==3) - set_four_ipo(fac, t, KEY_CARDINAL); + key_curve_position_weights(fac, t, KEY_CARDINAL); else - set_four_ipo(fac, t, KEY_BSPLINE); + key_curve_position_weights(fac, t, KEY_BSPLINE); out[0]= t[3]*cbd3->r +t[2]*cbd2->r +t[1]*cbd1->r +t[0]*cbd0->r; out[1]= t[3]*cbd3->g +t[2]*cbd2->g +t[1]*cbd1->g +t[0]*cbd0->g; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index e7164dc4794..9e86dcbe491 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -613,7 +613,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex } /* essential functions -- start, append, end */ -void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) +static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) { /* Handle to the output file */ AVFormatContext* of; |