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