/* NOTE: this needs to be called before frame update to work correctly */ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) { RigidBodyWorld *rbw = scene->rigidbody_world; PointCache *cache; PTCacheID pid; int startframe, endframe; BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw); BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL); cache = rbw->pointcache; /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */ if (rbw->physics_world == NULL || rbw->numbodies != BLI_countlist(&rbw->group->gobject)) { cache->flag |= PTCACHE_OUTDATED; } if (ctime == startframe + 1 && rbw->ltime == startframe) { if (cache->flag & PTCACHE_OUTDATED) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); rigidbody_update_simulation(scene, rbw, true); BKE_ptcache_validate(cache, (int)ctime); cache->last_exact = 0; cache->flag &= ~PTCACHE_REDO_NEEDED; } } }
/* Run RigidBody simulation for the specified physics world */ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) { float timestep; RigidBodyWorld *rbw = scene->rigidbody_world; PointCache *cache; PTCacheID pid; int startframe, endframe; BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw); BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL); cache = rbw->pointcache; if (ctime <= startframe) { rbw->ltime = startframe; return; } /* make sure we don't go out of cache frame range */ else if (ctime > endframe) { ctime = endframe; } /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */ if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED)) return; else if (rbw->objects == NULL) rigidbody_update_ob_array(rbw); /* try to read from cache */ // RB_TODO deal with interpolated, old and baked results if (BKE_ptcache_read(&pid, ctime)) { BKE_ptcache_validate(cache, (int)ctime); rbw->ltime = ctime; return; } /* advance simulation, we can only step one frame forward */ if (ctime == rbw->ltime + 1 && !(cache->flag & PTCACHE_BAKED)) { /* write cache for first frame when on second frame */ if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { BKE_ptcache_write(&pid, startframe); } /* update and validate simulation */ rigidbody_update_simulation(scene, rbw, false); /* calculate how much time elapsed since last step in seconds */ timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale; /* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */ RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f)); rigidbody_update_simulation_post_step(rbw); /* write cache for current frame */ BKE_ptcache_validate(cache, (int)ctime); BKE_ptcache_write(&pid, (unsigned int)ctime); rbw->ltime = ctime; } }
/************************************************ * clothModifier_do - main simulation function ************************************************/ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { DerivedMesh *result; PointCache *cache; PTCacheID pid; float timescale; int framedelta, framenr, startframe, endframe; int cache_result; clmd->scene= scene; /* nice to pass on later :) */ framenr= (int)scene->r.cfra; cache= clmd->point_cache; result = CDDM_copy(dm); BKE_ptcache_id_from_cloth(&pid, ob, clmd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); clmd->sim_parms->timescale= timescale; if(!result) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; cache->last_exact= 0; return dm; } /* verify we still have the same number of vertices, if not do nothing. * note that this should only happen if the number of vertices changes * during an animation due to a preceding modifier, this should not * happen because of object changes! */ if(clmd->clothObject) { if(result->getNumVerts(result) != clmd->clothObject->numverts) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; cache->last_exact= 0; return result; } } // unused in the moment, calculated seperately in implicit.c clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; /* handle continuous simulation with the play button */ if(BKE_ptcache_get_continue_physics()) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; cache->last_exact= 0; /* do simulation */ if(!do_init_cloth(ob, clmd, result, framenr)) return result; do_step_cloth(ob, clmd, result, framenr); cloth_to_object(ob, clmd, result); return result; } /* simulation is only active during a specific period */ if(framenr < startframe) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; cache->last_exact= 0; return result; } else if(framenr > endframe) { framenr= endframe; } if(cache->flag & PTCACHE_SIMULATION_VALID) framedelta= framenr - cache->simframe; else framedelta= -1; /* initialize simulation data if it didn't exist already */ 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) { 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) { implicit_set_positions(clmd); 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; return result; } /* 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; /* do simulation */ cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; 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; }
/************************************************ * clothModifier_do - main simulation function ************************************************/ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3]) { PointCache *cache; PTCacheID pid; float timescale; int framenr, startframe, endframe; int cache_result; clmd->scene= scene; /* nice to pass on later :) */ framenr= (int)scene->r.cfra; cache= clmd->point_cache; BKE_ptcache_id_from_cloth(&pid, ob, clmd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); clmd->sim_parms->timescale= timescale; if(clmd->sim_parms->reset || (framenr == (startframe - clmd->sim_parms->preroll) && clmd->sim_parms->preroll != 0) || (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->numverts)) { clmd->sim_parms->reset = 0; cache->flag |= PTCACHE_OUTDATED; BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); BKE_ptcache_validate(cache, 0); cache->last_exact= 0; cache->flag &= ~PTCACHE_REDO_NEEDED; return; } // unused in the moment, calculated separately in implicit.c clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; /* handle continuous simulation with the play button */ if(BKE_ptcache_get_continue_physics() || ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe))) { BKE_ptcache_invalidate(cache); /* do simulation */ if(!do_init_cloth(ob, clmd, dm, framenr)) return; do_step_cloth(ob, clmd, dm, framenr); cloth_to_object(ob, clmd, vertexCos); clmd->clothObject->last_frame= framenr; return; } /* simulation is only active during a specific period */ if(framenr < startframe) { BKE_ptcache_invalidate(cache); return; } else if(framenr > endframe) { framenr= endframe; } /* initialize simulation data if it didn't exist already */ if(!do_init_cloth(ob, clmd, dm, framenr)) return; if((framenr == startframe) && (clmd->sim_parms->preroll == 0)) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); do_init_cloth(ob, clmd, dm, framenr); BKE_ptcache_validate(cache, framenr); cache->flag &= ~PTCACHE_REDO_NEEDED; clmd->clothObject->last_frame= framenr; return; } /* try to read from cache */ cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { implicit_set_positions(clmd); cloth_to_object (ob, clmd, vertexCos); BKE_ptcache_validate(cache, framenr); if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) BKE_ptcache_write(&pid, framenr); clmd->clothObject->last_frame= framenr; return; } else if(cache_result==PTCACHE_READ_OLD) { implicit_set_positions(clmd); } else if( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ /* if baked and nothing in cache, do nothing */ BKE_ptcache_invalidate(cache); return; } if(framenr!=clmd->clothObject->last_frame+1) return; /* if on second frame, write cache for first frame */ if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) BKE_ptcache_write(&pid, startframe); clmd->sim_parms->timescale *= framenr - cache->simframe; /* do simulation */ BKE_ptcache_validate(cache, framenr); if(!do_step_cloth(ob, clmd, dm, framenr)) { BKE_ptcache_invalidate(cache); } else BKE_ptcache_write(&pid, framenr); cloth_to_object (ob, clmd, vertexCos); clmd->clothObject->last_frame= framenr; }
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) { // XXX TODO smd->time = scene->r.cfra; // rigid movement support /* Mat4CpyMat4(smd->flow->mat_old, smd->flow->mat); Mat4CpyMat4(smd->flow->mat, ob->obmat); */ } else if(scene->r.cfra < smd->time) { smd->time = scene->r.cfra; smokeModifier_reset(smd); } } else if(smd->type & MOD_SMOKE_TYPE_COLL) { if(scene->r.cfra >= smd->time) smokeModifier_init(smd, ob, scene, dm); if(scene->r.cfra > smd->time) { // XXX TODO smd->time = scene->r.cfra; if(smd->coll->dm) smd->coll->dm->release(smd->coll->dm); smd->coll->dm = CDDM_copy(dm); // rigid movement support Mat4CpyMat4(smd->coll->mat_old, smd->coll->mat); Mat4CpyMat4(smd->coll->mat, ob->obmat); } else if(scene->r.cfra < smd->time) { smd->time = scene->r.cfra; smokeModifier_reset(smd); } } else if(smd->type & MOD_SMOKE_TYPE_DOMAIN) { SmokeDomainSettings *sds = smd->domain; float light[3]; PointCache *cache = NULL; PTCacheID pid; PointCache *cache_wt = NULL; PTCacheID pid_wt; int startframe, endframe, framenr; float timescale; int cache_result = 0, cache_result_wt = 0; framenr = scene->r.cfra; // 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); cache_wt = sds->point_cache[1]; BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd); 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) return; if(framenr > endframe) return; if(!smd->domain->fluid && (framenr != startframe)) return; // printf("startframe: %d, framenr: %d\n", startframe, framenr); if(!smokeModifier_init(smd, ob, scene, dm)) { printf("bad smokeModifier_init\n"); return; } /* try to read from cache */ 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) { cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; 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; } } 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; // simulate the actual smoke (c++ code in intern/smoke) // DG: interesting commenting this line + deactivating loading of noise files if(framenr!=startframe) { if(sds->flags & MOD_SMOKE_DISSOLVE) smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); smoke_step(sds->fluid, smd->time); } // 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) { if(framenr!=startframe) { if(sds->flags & MOD_SMOKE_DISSOLVE) smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); smoke_turbulence_step(sds->wt, sds->fluid); } cache_wt->flag |= PTCACHE_SIMULATION_VALID; cache_wt->simframe= framenr; BKE_ptcache_write_cache(&pid_wt, framenr); } tend(); printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); } }