/* 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 ************************************************/ 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; }