/************************************************ * 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; }
static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int UNUSED(numVerts), int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) { CollisionModifierData *collmd = (CollisionModifierData*) md; DerivedMesh *dm = NULL; MVert *tempVert = NULL; /* if possible use/create DerivedMesh */ if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); if(!ob->pd) { printf("CollisionModifier deformVerts: Should not happen!\n"); return; } if(dm) { float current_time = 0; unsigned int numverts = 0; CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); current_time = BKE_curframe(md->scene); if(G.rt > 0) printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew); numverts = dm->getNumVerts ( dm ); if((current_time > collmd->time_xnew)|| (BKE_ptcache_get_continue_physics())) { unsigned int i; // check if mesh has changed if(collmd->x && (numverts != collmd->numverts)) freeData((ModifierData *)collmd); if(collmd->time_xnew == -1000) // first time { collmd->x = dm->dupVertArray(dm); // frame start position for ( i = 0; i < numverts; i++ ) { // we save global positions mul_m4_v3( ob->obmat, collmd->x[i].co ); } collmd->xnew = MEM_dupallocN(collmd->x); // frame end position collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame collmd->numverts = numverts; collmd->mfaces = dm->dupFaceArray(dm); collmd->numfaces = dm->getNumFaces(dm); // create bounding box hierarchy collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft); collmd->time_x = collmd->time_xnew = current_time; } else if(numverts == collmd->numverts) { // put positions to old positions tempVert = collmd->x; collmd->x = collmd->xnew; collmd->xnew = tempVert; collmd->time_x = collmd->time_xnew; memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); for ( i = 0; i < numverts; i++ ) { // we save global positions mul_m4_v3( ob->obmat, collmd->xnew[i].co ); } memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert)); memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert)); /* check if GUI setting has changed for bvh */ if(collmd->bvhtree) { if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree)) { BLI_bvhtree_free(collmd->bvhtree); collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); } } /* happens on file load (ONLY when i decomment changes in readfile.c) */ if(!collmd->bvhtree) { collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); } else { // recalc static bounding boxes bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 ); } collmd->time_xnew = current_time; } else if(numverts != collmd->numverts) { freeData((ModifierData *)collmd); } } else if(current_time < collmd->time_xnew) { freeData((ModifierData *)collmd); } else { if(numverts != collmd->numverts) { freeData((ModifierData *)collmd); } } } if(dm) dm->release(dm); }
/************************************************ * 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; }