Pointcache refresh part 2
* Based on what happens during simulation the cache is marked (also in cache panel, this could possibly be extended to 3d view as well) as: - exact (not marked) - outdated (simulation is not done completely with current settings) - non-exact (frames were skipped during simulation) * The parameter "cache step" effects the number of frames between saved cache frames. - This can save a lot of memory (or disk space) if absolutely frame accurate simulation is not required. - Speeds up the "quick caching" very much. - Frames between cached frames are interpolated from the cached frames. - Current default value of 10 frames works nicely with up/down-arrows (skip 10 frames forwards/backwards on timeline), but can be changed if wanted. * The caching can work in normal or "quick" mode: [Normal cache] - Basic: Calculate what even happens (settings change, big frame steps etc.) and cache results, if possible try to use "cache step" when saving cache frames. - Becomes non-exact: After larger than 1 frame steps. - Becomes outdated: After any change effecting the simulation other than frame steps. - Pros/cons: Freedom of doing anything and playing with particles, but exact results have to calculated from the beginning. [Quick cache] - Basic: Calculate simulation up to current frame automatically on changes with cache step sized jumps in simulation. With multiple "quick cached" simulations the smallest cache step is used. - Becomes non-exact: Always from frame 1 (unless cache step = 1). - Becomes outdated: Never. - Pros/cons: Not very accurate, but super fast! - Todo: Transform of any animated (non-autokeyed) object is locked! Probably needs some tinkering with anim sys overrides. * The simulation can be run forwards or backwards even if it's cache is outdated or non-exact, the following rules apply in these situations: - step forwards (to unknown) -> simulate from last exact frame, store result - step backwards (to known) -> result is interpolated from existing frames, store result, clear cache forwards if current frame is after last exact frame * "Calculate to current frame" runs the simulation from start to current frame with a frame steps of 1. - Baking does the same, but runs the simulation all the way to the end of simulation. - Rendering does this automatically if the simulation is outdated of non-exact, so all rendered simulations will always be updated and exact. * Every cache panel also holds buttons to "Bake all dynamics", "Free all dynamics" and "Update all dynamics to current frame". * Cloth simulation supports the new cache too.
This commit is contained in:
@@ -130,11 +130,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
|
||||
cache = psys.point_cache
|
||||
|
||||
row = layout.row()
|
||||
row.itemR(cache, "name", text="")
|
||||
if cache.outdated:
|
||||
row.itemL(text="Cache is outdated.")
|
||||
else:
|
||||
row.itemL(text="")
|
||||
row.itemR(cache, "name")
|
||||
|
||||
row = layout.row()
|
||||
|
||||
@@ -142,18 +138,29 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
|
||||
row.itemO("PTCACHE_OT_free_bake_particle_system", text="Free Bake")
|
||||
else:
|
||||
row.item_booleanO("PTCACHE_OT_cache_particle_system", "bake", True, text="Bake")
|
||||
|
||||
|
||||
subrow = row.row()
|
||||
subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
|
||||
subrow.itemO("PTCACHE_OT_cache_particle_system", text="Calculate to Current Frame")
|
||||
|
||||
row = layout.row()
|
||||
row.enabled = particle_panel_enabled(psys)
|
||||
row.itemO("PTCACHE_OT_bake_from_particles_cache", text="Current Cache to Bake")
|
||||
if cache.autocache == 0:
|
||||
row.itemO("PTCACHE_OT_cache_particle_system", text="Cache to Current Frame")
|
||||
row.itemR(cache, "step");
|
||||
|
||||
row = layout.row()
|
||||
row.enabled = particle_panel_enabled(psys)
|
||||
#row.itemR(cache, "autocache")
|
||||
row.itemR(cache, "quick_cache")
|
||||
row.itemR(cache, "disk_cache")
|
||||
row.itemL(text=cache.info)
|
||||
|
||||
layout.itemL(text=cache.info)
|
||||
|
||||
layout.itemS()
|
||||
|
||||
row = layout.row()
|
||||
row.item_booleanO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
|
||||
row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
|
||||
layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
|
||||
|
||||
# for particles these are figured out automatically
|
||||
#row.itemR(cache, "start_frame")
|
||||
|
||||
@@ -43,7 +43,54 @@ class Physic_PT_cloth(PhysicButtonsPanel):
|
||||
col.itemR(cloth, "goal_spring", text="Stiffness")
|
||||
col.itemR(cloth, "goal_friction", text="Friction")
|
||||
"""
|
||||
|
||||
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
|
||||
__idname__= "PHYSICS_PT_cloth_cache"
|
||||
__label__ = "Cache"
|
||||
__default_closed__ = True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
cache = context.cloth.point_cache
|
||||
|
||||
row = layout.row()
|
||||
row.itemR(cache, "name")
|
||||
|
||||
row = layout.row()
|
||||
row.itemR(cache, "start_frame")
|
||||
row.itemR(cache, "end_frame")
|
||||
|
||||
row = layout.row()
|
||||
|
||||
if cache.baked == True:
|
||||
row.itemO("PTCACHE_OT_free_bake_cloth", text="Free Bake")
|
||||
else:
|
||||
row.item_booleanO("PTCACHE_OT_cache_cloth", "bake", True, text="Bake")
|
||||
|
||||
subrow = row.row()
|
||||
subrow.enabled = cache.frames_skipped or cache.outdated
|
||||
subrow.itemO("PTCACHE_OT_cache_cloth", text="Calculate to Current Frame")
|
||||
|
||||
row = layout.row()
|
||||
#row.enabled = particle_panel_enabled(psys)
|
||||
row.itemO("PTCACHE_OT_bake_from_cloth_cache", text="Current Cache to Bake")
|
||||
row.itemR(cache, "step");
|
||||
|
||||
row = layout.row()
|
||||
#row.enabled = particle_panel_enabled(psys)
|
||||
row.itemR(cache, "quick_cache")
|
||||
row.itemR(cache, "disk_cache")
|
||||
|
||||
layout.itemL(text=cache.info)
|
||||
|
||||
layout.itemS()
|
||||
|
||||
row = layout.row()
|
||||
row.itemO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
|
||||
row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
|
||||
layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
|
||||
|
||||
class Physic_PT_cloth_collision(PhysicButtonsPanel):
|
||||
__idname__ = "Physic_PT_clothcollision"
|
||||
__label__ = "Cloth Collision"
|
||||
@@ -102,5 +149,6 @@ class Physic_PT_cloth_stiffness(PhysicButtonsPanel):
|
||||
sub.itemR(cloth, "bending_stiffness_max", text="Max")
|
||||
|
||||
bpy.types.register(Physic_PT_cloth)
|
||||
bpy.types.register(PHYSICS_PT_cloth_cache)
|
||||
bpy.types.register(Physic_PT_cloth_collision)
|
||||
bpy.types.register(Physic_PT_cloth_stiffness)
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_collision.h"
|
||||
|
||||
@@ -245,8 +246,8 @@ void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving );
|
||||
void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving );
|
||||
|
||||
// needed for editmesh.c
|
||||
void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr );
|
||||
int cloth_read_cache ( Object *ob, ClothModifierData *clmd, float framenr );
|
||||
void cloth_write_cache( Object *ob, ClothModifierData *clmd, int framenr );
|
||||
int cloth_read_cache( Scene *scene, Object *ob, ClothModifierData *clmd, float framenr, int *old_framenr );
|
||||
|
||||
// needed for button_object.c
|
||||
void cloth_clear_cache ( Object *ob, ClothModifierData *clmd, float framenr );
|
||||
|
||||
@@ -252,7 +252,6 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P
|
||||
|
||||
struct ParticleSettings *psys_new_settings(char *name, struct Main *main);
|
||||
struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part);
|
||||
int psys_count_autocache(struct Scene *scene, struct ParticleSettings *part);
|
||||
void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc);
|
||||
void make_local_particlesettings(struct ParticleSettings *part);
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ typedef struct PTCacheWriter {
|
||||
int cfra;
|
||||
int totelem;
|
||||
|
||||
float *(*elem_ptr)(int index, void *calldata);
|
||||
void (*set_elem)(int index, void *calldata, float *data);
|
||||
void *calldata;
|
||||
} PTCacheWriter;
|
||||
|
||||
@@ -103,12 +103,10 @@ typedef struct PTCacheReader {
|
||||
float cfra;
|
||||
int totelem;
|
||||
|
||||
void (*set_elem)(int index, void *calldata, float *data);
|
||||
void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2);
|
||||
void (*set_elem)(int elem_index, void *calldata, float *data);
|
||||
void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2);
|
||||
void *calldata;
|
||||
|
||||
int allow_interpolate;
|
||||
int allow_old;
|
||||
int *old_frame;
|
||||
} PTCacheReader;
|
||||
|
||||
@@ -116,6 +114,7 @@ typedef struct PTCacheBaker {
|
||||
struct Scene *scene;
|
||||
int bake;
|
||||
int render;
|
||||
int quick_step;
|
||||
struct PTCacheID *pid;
|
||||
int (*break_test)(void *data);
|
||||
void *break_data;
|
||||
@@ -146,6 +145,8 @@ void BKE_ptcache_file_close(PTCacheFile *pf);
|
||||
int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot);
|
||||
int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot);
|
||||
|
||||
void BKE_ptcache_update_info(PTCacheID *pid);
|
||||
|
||||
/* General cache reading/writing */
|
||||
int BKE_ptcache_read_cache(PTCacheReader *reader);
|
||||
int BKE_ptcache_write_cache(PTCacheWriter *writer);
|
||||
@@ -160,7 +161,7 @@ void BKE_ptcache_free(struct PointCache *cache);
|
||||
struct PointCache *BKE_ptcache_copy(struct PointCache *cache);
|
||||
|
||||
/* Baking */
|
||||
void BKE_ptcache_autocache_all(struct Scene *scene);
|
||||
void BKE_ptcache_quick_cache_all(struct Scene *scene);
|
||||
void BKE_ptcache_make_cache(struct PTCacheBaker* baker);
|
||||
void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
@@ -42,6 +43,7 @@
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_particle.h"
|
||||
|
||||
#include "BKE_pointcache.h"
|
||||
|
||||
@@ -339,43 +341,88 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
|
||||
}
|
||||
|
||||
int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
|
||||
|
||||
int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
|
||||
static void cloth_write_state(int index, Cloth *cloth, float *data)
|
||||
{
|
||||
PTCacheID pid;
|
||||
PTCacheFile *pf;
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
unsigned int a, ret = 1;
|
||||
ClothVertex *vert = cloth->verts + index;
|
||||
|
||||
memcpy(data, vert->x, 3 * sizeof(float));
|
||||
memcpy(data + 3, vert->xconst, 3 * sizeof(float));
|
||||
memcpy(data + 6, vert->v, 3 * sizeof(float));
|
||||
}
|
||||
static void cloth_read_state(int index, Cloth *cloth, float *data)
|
||||
{
|
||||
ClothVertex *vert = cloth->verts + index;
|
||||
|
||||
if(!cloth)
|
||||
return 0;
|
||||
|
||||
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
|
||||
pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, framenr);
|
||||
if(pf) {
|
||||
for(a = 0; a < cloth->numverts; a++) {
|
||||
if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].x, 3)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].xconst, 3)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].v, 3)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BKE_ptcache_file_close(pf);
|
||||
memcpy(vert->x, data, 3 * sizeof(float));
|
||||
memcpy(vert->xconst, data + 3, 3 * sizeof(float));
|
||||
memcpy(vert->v, data + 6, 3 * sizeof(float));
|
||||
}
|
||||
static void cloth_cache_interpolate(int index, Cloth *cloth, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
|
||||
{
|
||||
ClothVertex *vert = cloth->verts + index;
|
||||
ParticleKey keys[4];
|
||||
float dfra;
|
||||
|
||||
if(cfra1 == cfra2) {
|
||||
cloth_read_state(index, cloth, data1);
|
||||
return;
|
||||
}
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
|
||||
memcpy(keys[1].co, data1, 3 * sizeof(float));
|
||||
memcpy(keys[1].vel, data1 + 6, 3 * sizeof(float));
|
||||
|
||||
memcpy(keys[2].co, data2, 3 * sizeof(float));
|
||||
memcpy(keys[2].vel, data2 + 6, 3 * sizeof(float));
|
||||
|
||||
dfra = cfra2 - cfra1;
|
||||
|
||||
VecMulf(keys[1].vel, dfra);
|
||||
VecMulf(keys[2].vel, dfra);
|
||||
|
||||
psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
|
||||
|
||||
VecMulf(keys->vel, 1.0f / dfra);
|
||||
|
||||
memcpy(vert->x, keys->co, 3 * sizeof(float));
|
||||
memcpy(vert->v, keys->vel, 3 * sizeof(float));
|
||||
|
||||
/* not sure what to do with this - jahka */
|
||||
memcpy(vert->xconst, data1 + 3, 3 * sizeof(float));
|
||||
}
|
||||
void cloth_write_cache(Object *ob, ClothModifierData *clmd, int cfra)
|
||||
{
|
||||
PTCacheWriter writer;
|
||||
PTCacheID pid;
|
||||
|
||||
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
|
||||
|
||||
writer.calldata = clmd->clothObject;
|
||||
writer.cfra = cfra;
|
||||
writer.set_elem = cloth_write_state;
|
||||
writer.pid = &pid;
|
||||
writer.totelem = clmd->clothObject->numverts;
|
||||
|
||||
BKE_ptcache_write_cache(&writer);
|
||||
}
|
||||
|
||||
int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr)
|
||||
{
|
||||
PTCacheReader reader;
|
||||
PTCacheID pid;
|
||||
|
||||
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
|
||||
|
||||
reader.calldata = clmd->clothObject;
|
||||
reader.cfra = cfra;
|
||||
reader.interpolate_elem = cloth_cache_interpolate;
|
||||
reader.old_frame = old_framenr;
|
||||
reader.pid = &pid;
|
||||
reader.scene = scene;
|
||||
reader.set_elem = cloth_read_state;
|
||||
reader.totelem = clmd->clothObject->numverts;
|
||||
|
||||
return BKE_ptcache_read_cache(&reader);
|
||||
}
|
||||
void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
|
||||
{
|
||||
PTCacheID pid;
|
||||
@@ -389,30 +436,6 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
|
||||
BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
|
||||
}
|
||||
|
||||
void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr)
|
||||
{
|
||||
Cloth *cloth = clmd->clothObject;
|
||||
PTCacheID pid;
|
||||
PTCacheFile *pf;
|
||||
unsigned int a;
|
||||
|
||||
if(!cloth)
|
||||
return;
|
||||
|
||||
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
|
||||
pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr);
|
||||
if(!pf)
|
||||
return;
|
||||
|
||||
for(a = 0; a < cloth->numverts; a++) {
|
||||
BKE_ptcache_file_write_floats(pf, cloth->verts[a].x, 3);
|
||||
BKE_ptcache_file_write_floats(pf, cloth->verts[a].xconst, 3);
|
||||
BKE_ptcache_file_write_floats(pf, cloth->verts[a].v, 3);
|
||||
}
|
||||
|
||||
BKE_ptcache_file_close(pf);
|
||||
}
|
||||
|
||||
static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
|
||||
{
|
||||
PointCache *cache;
|
||||
@@ -486,6 +509,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
|
||||
PTCacheID pid;
|
||||
float timescale;
|
||||
int framedelta, framenr, startframe, endframe;
|
||||
int cache_result, old_framenr;
|
||||
|
||||
clmd->scene= scene; /* nice to pass on later :) */
|
||||
framenr= (int)scene->r.cfra;
|
||||
@@ -499,6 +523,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
|
||||
if(!result) {
|
||||
cache->flag &= ~PTCACHE_SIMULATION_VALID;
|
||||
cache->simframe= 0;
|
||||
cache->last_exact= 0;
|
||||
return dm;
|
||||
}
|
||||
|
||||
@@ -510,6 +535,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
|
||||
if(result->getNumVerts(result) != clmd->clothObject->numverts) {
|
||||
cache->flag &= ~PTCACHE_SIMULATION_VALID;
|
||||
cache->simframe= 0;
|
||||
cache->last_exact= 0;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -521,6 +547,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
|
||||
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))
|
||||
@@ -536,6 +563,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
|
||||
if(framenr < startframe) {
|
||||
cache->flag &= ~PTCACHE_SIMULATION_VALID;
|
||||
cache->simframe= 0;
|
||||
cache->last_exact= 0;
|
||||
return result;
|
||||
}
|
||||
else if(framenr > endframe) {
|
||||
@@ -552,7 +580,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
|
||||
return result;
|
||||
|
||||
/* try to read from cache */
|
||||
if(cloth_read_cache(ob, clmd, framenr)) {
|
||||
cache_result = cloth_read_cache(scene, ob, clmd, framenr, &old_framenr);
|
||||
|
||||
if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
|
||||
cache->flag |= PTCACHE_SIMULATION_VALID;
|
||||
cache->simframe= framenr;
|
||||
|
||||
@@ -561,25 +591,40 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
|
||||
|
||||
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;
|
||||
cache->simframe= old_framenr;
|
||||
}
|
||||
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(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(framedelta == 1) {
|
||||
else {
|
||||
/* if on second frame, write cache for first frame */
|
||||
if(framenr == startframe+1)
|
||||
if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
|
||||
cloth_write_cache(ob, clmd, startframe);
|
||||
|
||||
clmd->sim_parms->timescale *= framenr - cache->simframe;
|
||||
|
||||
/* do simulation */
|
||||
cache->flag |= PTCACHE_SIMULATION_VALID;
|
||||
cache->simframe= framenr;
|
||||
@@ -587,16 +632,13 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
|
||||
if(!do_step_cloth(ob, clmd, result, framenr)) {
|
||||
cache->flag &= ~PTCACHE_SIMULATION_VALID;
|
||||
cache->simframe= 0;
|
||||
cache->last_exact= 0;
|
||||
}
|
||||
else
|
||||
cloth_write_cache(ob, clmd, framenr);
|
||||
|
||||
cloth_to_object (ob, clmd, result);
|
||||
}
|
||||
else {
|
||||
cache->flag &= ~PTCACHE_SIMULATION_VALID;
|
||||
cache->simframe= 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1600,6 +1600,10 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
|
||||
|
||||
if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED)
|
||||
{
|
||||
float temp = clmd->sim_parms->stepsPerFrame;
|
||||
/* not too nice hack, but collisions need this correction -jahka */
|
||||
clmd->sim_parms->stepsPerFrame /= clmd->sim_parms->timescale;
|
||||
|
||||
// collisions
|
||||
// itstart();
|
||||
|
||||
@@ -1614,7 +1618,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
|
||||
|
||||
// call collision function
|
||||
// TODO: check if "step" or "step+dt" is correct - dg
|
||||
result = cloth_bvh_objcollision(ob, clmd, step, dt);
|
||||
result = cloth_bvh_objcollision(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
|
||||
|
||||
// correct velocity again, just to be sure we had to change it due to adaptive collisions
|
||||
for(i = 0; i < numverts; i++)
|
||||
@@ -1637,6 +1641,9 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
|
||||
}
|
||||
}
|
||||
|
||||
/* restore original stepsPerFrame */
|
||||
clmd->sim_parms->stepsPerFrame = temp;
|
||||
|
||||
// X = Xnew;
|
||||
cp_lfvector(id->X, id->Xnew, numverts);
|
||||
|
||||
@@ -1654,7 +1661,6 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
|
||||
|
||||
simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -236,31 +236,6 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
int psys_count_autocache(Scene *scene, ParticleSettings *part)
|
||||
{
|
||||
Base *base = scene->base.first;
|
||||
ParticleSystem *psys;
|
||||
PTCacheID pid;
|
||||
int autocache_count= 0;
|
||||
|
||||
for(base = scene->base.first; base; base = base->next) {
|
||||
for(psys = base->object->particlesystem.first; psys; psys=psys->next) {
|
||||
if(part && psys->part != part)
|
||||
continue;
|
||||
|
||||
BKE_ptcache_id_from_particles(&pid, base->object, psys);
|
||||
|
||||
if((psys->pointcache->flag & PTCACHE_BAKED)
|
||||
|| (psys->pointcache->flag & PTCACHE_AUTOCACHE)==0)
|
||||
continue;
|
||||
|
||||
if((psys->pointcache->flag & PTCACHE_OUTDATED)
|
||||
|| BKE_ptcache_id_exist(&pid, CFRA)==0)
|
||||
autocache_count++;
|
||||
}
|
||||
}
|
||||
return autocache_count;
|
||||
}
|
||||
/* change object's active particle system */
|
||||
void psys_change_act(void *ob_v, void *act_v)
|
||||
{
|
||||
@@ -3740,6 +3715,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
|
||||
if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
|
||||
|| (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))
|
||||
return 0;
|
||||
|
||||
state->time = MIN2(state->time, pa->dietime);
|
||||
}
|
||||
|
||||
if(psys->flag & PSYS_KEYED){
|
||||
|
||||
@@ -2205,11 +2205,9 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra
|
||||
*sfra = MAX2(1, (int)part->sta);
|
||||
*efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra);
|
||||
}
|
||||
static float *particle_state_ptr(int index, void *psys_ptr)
|
||||
static void particle_write_state(int index, ParticleSystem *psys, float *data)
|
||||
{
|
||||
ParticleSystem *psys= psys_ptr;
|
||||
|
||||
return (float *)(&(psys->particles+index)->state);
|
||||
memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey));
|
||||
}
|
||||
static void particle_read_state(int index, void *psys_ptr, float *data)
|
||||
{
|
||||
@@ -2222,24 +2220,35 @@ static void particle_read_state(int index, void *psys_ptr, float *data)
|
||||
|
||||
copy_particle_key(&pa->state, key, 1);
|
||||
}
|
||||
static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2)
|
||||
static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
|
||||
{
|
||||
ParticleSystem *psys= psys_ptr;
|
||||
ParticleData *pa = psys->particles + index;
|
||||
ParticleKey keys[4];
|
||||
float dfra;
|
||||
float dfra, cfra1f = (float)cfra1, cfra2f(float);
|
||||
|
||||
cfra = MIN2(cfra, pa->dietime);
|
||||
cfra1 = MIN2(cfra1, pa->dietime);
|
||||
cfra2 = MIN2(cfra2, pa->dietime);
|
||||
|
||||
keys[1] = *((ParticleKey*)data1);
|
||||
keys[2] = *((ParticleKey*)data2);
|
||||
|
||||
dfra = keys[2].time - keys[1].time;
|
||||
if(cfra1 == cfra2) {
|
||||
copy_particle_key(&pa->state, &keys[1], 1);
|
||||
return;
|
||||
}
|
||||
|
||||
dfra = cfra2 - cfra1;
|
||||
|
||||
VecMulf(keys[1].vel, dfra / frs_sec);
|
||||
VecMulf(keys[2].vel, dfra / frs_sec);
|
||||
|
||||
psys_interpolate_particle(-1, keys, (keys[1].time - cfra) / dfra, &pa->state, 1);
|
||||
psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
|
||||
|
||||
VecMulf(pa->state.vel, frs_sec / dfra);
|
||||
|
||||
pa->state.time = cfra;
|
||||
}
|
||||
static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
|
||||
{
|
||||
@@ -2250,22 +2259,20 @@ static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
|
||||
|
||||
writer.calldata = psys;
|
||||
writer.cfra = cfra;
|
||||
writer.elem_ptr = particle_state_ptr;
|
||||
writer.set_elem = particle_write_state;
|
||||
writer.pid = &pid;
|
||||
writer.totelem = psys->totpart;
|
||||
|
||||
BKE_ptcache_write_cache(&writer);
|
||||
}
|
||||
|
||||
static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int allow_interpolate, int allow_old, int *old_frame)
|
||||
static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int *old_frame)
|
||||
{
|
||||
PTCacheReader reader;
|
||||
PTCacheID pid;
|
||||
|
||||
BKE_ptcache_id_from_particles(&pid, ob, psys);
|
||||
|
||||
reader.allow_interpolate = allow_interpolate;
|
||||
reader.allow_old = allow_old;
|
||||
reader.calldata = psys;
|
||||
reader.cfra = cfra;
|
||||
reader.interpolate_elem = particle_cache_interpolate;
|
||||
@@ -2402,6 +2409,8 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs
|
||||
Object *tob;
|
||||
|
||||
for(i=0; epsys; epsys=epsys->next,i++){
|
||||
if(!psys_check_enabled(ob, epsys))
|
||||
continue;
|
||||
type=0;
|
||||
if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){
|
||||
epart=epsys->part;
|
||||
@@ -4366,7 +4375,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
|
||||
pa->alive = PARS_UNBORN;
|
||||
else if(dietime <= cfra){
|
||||
if(dietime > psys->cfra){
|
||||
state.time = pa->dietime;
|
||||
state.time = dietime;
|
||||
psys_get_particle_state(scene, ob,psys,p,&state,1);
|
||||
push_reaction(ob,psys,p,PART_EVENT_DEATH,&state);
|
||||
}
|
||||
@@ -4668,9 +4677,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
|
||||
|
||||
/* try to read from the cache */
|
||||
if(usecache) {
|
||||
int result = get_particles_from_cache(scene, ob, psys, (float)framenr, 0, 1, &old_framenr);
|
||||
int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr);
|
||||
|
||||
if(result == PTCACHE_READ_EXACT) {
|
||||
if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
|
||||
//if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
|
||||
// psys_count_keyed_targets(ob,psys);
|
||||
// set_keyed_keys(scene, ob, psys);
|
||||
@@ -4687,15 +4696,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
|
||||
cache->simframe= framenr;
|
||||
cache->flag |= PTCACHE_SIMULATION_VALID;
|
||||
|
||||
if(cache->flag & PTCACHE_OUTDATED)
|
||||
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
|
||||
if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
|
||||
write_particles_to_cache(ob, psys, cfra);
|
||||
|
||||
return;
|
||||
}
|
||||
else if((cache->flag & PTCACHE_AUTOCACHE)==0 && result==PTCACHE_READ_OLD) {
|
||||
/* clear cache after current frame */
|
||||
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
|
||||
|
||||
else if(result==PTCACHE_READ_OLD) {
|
||||
/* set old cfra */
|
||||
psys->cfra = (float)old_framenr;
|
||||
|
||||
@@ -4715,15 +4721,6 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
|
||||
psys->recalc = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(framenr != startframe && framedelta != 1 && cache->flag & PTCACHE_AUTOCACHE) {
|
||||
//psys_reset(psys, PSYS_RESET_CACHE_MISS);
|
||||
/* make sure cache is recalculated */
|
||||
BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_FRAME, (int)cfra);
|
||||
psys->cfra = cfra;
|
||||
psys->recalc = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cache->flag &= ~PTCACHE_SIMULATION_VALID;
|
||||
|
||||
@@ -303,7 +303,7 @@ static int ptcache_pid_elemsize(PTCacheID *pid)
|
||||
else if(pid->type==PTCACHE_TYPE_PARTICLES)
|
||||
return sizeof(ParticleKey);
|
||||
else if(pid->type==PTCACHE_TYPE_CLOTH)
|
||||
return 0; // TODO
|
||||
return 9 * sizeof(float);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -321,10 +321,11 @@ static int ptcache_pid_totelem(PTCacheID *pid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ptcache_update_info(PTCacheID *pid)
|
||||
void BKE_ptcache_update_info(PTCacheID *pid)
|
||||
{
|
||||
PointCache *cache = pid->cache;
|
||||
int totframes = 0;
|
||||
char mem_info[64];
|
||||
|
||||
if(cache->flag & PTCACHE_DISK_CACHE) {
|
||||
int cfra = cache->startframe;
|
||||
@@ -334,7 +335,7 @@ void ptcache_update_info(PTCacheID *pid)
|
||||
totframes++;
|
||||
}
|
||||
|
||||
sprintf(cache->info, "%i frames on disk.", totframes);
|
||||
sprintf(mem_info, "%i frames on disk", totframes);
|
||||
}
|
||||
else {
|
||||
PTCacheMem *pm = cache->mem_cache.first;
|
||||
@@ -351,11 +352,20 @@ void ptcache_update_info(PTCacheID *pid)
|
||||
|
||||
mb = (bytes > 1024.0f * 1024.0f);
|
||||
|
||||
sprintf(cache->info, "%i frames in memory (%.1f %s).",
|
||||
sprintf(mem_info, "%i frames in memory (%.1f %s)",
|
||||
totframes,
|
||||
bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
|
||||
mb ? "Mb" : "kb");
|
||||
}
|
||||
|
||||
if(cache->flag & PTCACHE_OUTDATED) {
|
||||
sprintf(cache->info, "%s, cache is outdated!", mem_info);
|
||||
}
|
||||
else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
|
||||
sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
|
||||
}
|
||||
else
|
||||
sprintf(cache->info, "%s.", mem_info);
|
||||
}
|
||||
/* reads cache from disk or memory */
|
||||
/* possible to get old or interpolated result */
|
||||
@@ -370,10 +380,13 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
|
||||
int elemsize = ptcache_pid_elemsize(pid);
|
||||
int i, incr = elemsize / sizeof(float);
|
||||
float frs_sec = reader->scene->r.frs_sec;
|
||||
int cfra1=0, cfra2;
|
||||
int ret = 0;
|
||||
|
||||
if(totelem == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
/* first check if we have the actual frame cached */
|
||||
if(cfra == (float)cfrai) {
|
||||
if(pid->cache->flag & PTCACHE_DISK_CACHE) {
|
||||
@@ -419,130 +432,147 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
|
||||
MEM_freeN(data);
|
||||
}
|
||||
|
||||
return PTCACHE_READ_EXACT;
|
||||
ret = PTCACHE_READ_EXACT;
|
||||
}
|
||||
|
||||
if(ret)
|
||||
;
|
||||
/* no exact cache frame found so try to find cached frames around cfra */
|
||||
if(reader->allow_interpolate || reader->allow_old) {
|
||||
int cfra1, cfra2;
|
||||
|
||||
if(pid->cache->flag & PTCACHE_DISK_CACHE) {
|
||||
pf=NULL;
|
||||
while(cfrai > pid->cache->startframe && !pf) {
|
||||
cfrai--;
|
||||
pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
|
||||
cfra1 = cfrai;
|
||||
}
|
||||
else if(pid->cache->flag & PTCACHE_DISK_CACHE) {
|
||||
pf=NULL;
|
||||
while(cfrai > pid->cache->startframe && !pf) {
|
||||
cfrai--;
|
||||
pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
|
||||
cfra1 = cfrai;
|
||||
}
|
||||
|
||||
if(reader->old_frame)
|
||||
*(reader->old_frame) = cfrai;
|
||||
|
||||
cfrai = (int)cfra;
|
||||
while(cfrai < pid->cache->endframe && !pf2) {
|
||||
cfrai++;
|
||||
pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
|
||||
cfra2 = cfrai;
|
||||
}
|
||||
cfrai = (int)cfra;
|
||||
while(cfrai < pid->cache->endframe && !pf2) {
|
||||
cfrai++;
|
||||
pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
|
||||
cfra2 = cfrai;
|
||||
}
|
||||
else if(pid->cache->mem_cache.first){
|
||||
pm = pid->cache->mem_cache.first;
|
||||
}
|
||||
else if(pid->cache->mem_cache.first){
|
||||
pm = pid->cache->mem_cache.first;
|
||||
|
||||
while(pm->next && pm->next->frame < cfra)
|
||||
pm= pm->next;
|
||||
while(pm->next && pm->next->frame < cfra)
|
||||
pm= pm->next;
|
||||
|
||||
if(pm) {
|
||||
if(pm) {
|
||||
if(reader->old_frame)
|
||||
*(reader->old_frame) = pm->frame;
|
||||
cfra1 = pm->frame;
|
||||
}
|
||||
cfra1 = pm->frame;
|
||||
}
|
||||
|
||||
pm2 = pid->cache->mem_cache.last;
|
||||
pm2 = pid->cache->mem_cache.last;
|
||||
|
||||
while(pm2->prev && pm2->frame > cfra)
|
||||
if(pm2 && pm2->frame < cfra)
|
||||
pm2 = NULL;
|
||||
else {
|
||||
while(pm2->prev && pm2->prev->frame > cfra)
|
||||
pm2= pm2->prev;
|
||||
|
||||
if(pm2)
|
||||
cfra2 = pm2->frame;
|
||||
}
|
||||
}
|
||||
|
||||
if(reader->allow_interpolate && ((pf && pf2) || (pm && pm2))) {
|
||||
/* interpolate from nearest frames */
|
||||
float *data1, *data2;
|
||||
if(ret)
|
||||
;
|
||||
else if((pf && pf2) || (pm && pm2)) {
|
||||
/* interpolate from nearest frames if cache isn't outdated */
|
||||
float *data1, *data2;
|
||||
|
||||
if(pm) {
|
||||
data1 = pm->data;
|
||||
data2 = pm2->data;
|
||||
if(pm) {
|
||||
data1 = pm->data;
|
||||
data2 = pm2->data;
|
||||
}
|
||||
else {
|
||||
data1 = MEM_callocN(elemsize, "pointcache read data1");
|
||||
data2 = MEM_callocN(elemsize, "pointcache read data2");
|
||||
}
|
||||
|
||||
for(i=0; i<totelem; i++) {
|
||||
if(pf && pf2) {
|
||||
if(!BKE_ptcache_file_read_floats(pf, data1, incr)) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
BKE_ptcache_file_close(pf2);
|
||||
MEM_freeN(data1);
|
||||
MEM_freeN(data2);
|
||||
return 0;
|
||||
}
|
||||
if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
BKE_ptcache_file_close(pf2);
|
||||
MEM_freeN(data1);
|
||||
MEM_freeN(data2);
|
||||
return 0;
|
||||
}
|
||||
reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
|
||||
}
|
||||
else {
|
||||
data1 = MEM_callocN(elemsize, "pointcache read data1");
|
||||
data2 = MEM_callocN(elemsize, "pointcache read data2");
|
||||
reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
|
||||
data1 += incr;
|
||||
data2 += incr;
|
||||
}
|
||||
|
||||
for(i=0; i<totelem; i++) {
|
||||
if(pf && pf2) {
|
||||
if(!BKE_ptcache_file_read_floats(pf, data1, incr)) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
BKE_ptcache_file_close(pf2);
|
||||
MEM_freeN(data1);
|
||||
MEM_freeN(data2);
|
||||
return 0;
|
||||
}
|
||||
if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
BKE_ptcache_file_close(pf2);
|
||||
MEM_freeN(data1);
|
||||
MEM_freeN(data2);
|
||||
return 0;
|
||||
}
|
||||
reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2);
|
||||
}
|
||||
else {
|
||||
reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2);
|
||||
data1 += incr;
|
||||
data2 += incr;
|
||||
}
|
||||
}
|
||||
|
||||
if(pf) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
BKE_ptcache_file_close(pf2);
|
||||
MEM_freeN(data1);
|
||||
MEM_freeN(data2);
|
||||
}
|
||||
|
||||
return PTCACHE_READ_INTERPOLATED;
|
||||
}
|
||||
else if(reader->allow_old && (pf || pm)) {
|
||||
/* use last valid cache frame */
|
||||
float *data;
|
||||
|
||||
if(pm)
|
||||
data = pm->data;
|
||||
else
|
||||
data = MEM_callocN(elemsize, "pointcache read data");
|
||||
if(pf) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
BKE_ptcache_file_close(pf2);
|
||||
MEM_freeN(data1);
|
||||
MEM_freeN(data2);
|
||||
}
|
||||
|
||||
for(i=0; i<totelem; i++) {
|
||||
if(pf) {
|
||||
if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
if(pf2)
|
||||
BKE_ptcache_file_close(pf2);
|
||||
return 0;
|
||||
}
|
||||
reader->set_elem(i, reader->calldata, data);
|
||||
}
|
||||
else {
|
||||
reader->set_elem(i, reader->calldata, data);
|
||||
data += incr;
|
||||
}
|
||||
}
|
||||
ret = PTCACHE_READ_INTERPOLATED;
|
||||
}
|
||||
else if(pf || pm) {
|
||||
/* use last valid cache frame */
|
||||
float *data;
|
||||
|
||||
if(pf) {
|
||||
/* don't read cache if allready simulated past cached frame */
|
||||
if(cfra1 && cfra1 <= pid->cache->simframe) {
|
||||
if(pf)
|
||||
BKE_ptcache_file_close(pf);
|
||||
MEM_freeN(data);
|
||||
}
|
||||
if(pf2)
|
||||
BKE_ptcache_file_close(pf2);
|
||||
|
||||
return PTCACHE_READ_OLD;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(pm)
|
||||
data = pm->data;
|
||||
else
|
||||
data = MEM_callocN(elemsize, "pointcache read data");
|
||||
|
||||
for(i=0; i<totelem; i++) {
|
||||
if(pf) {
|
||||
if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
if(pf2)
|
||||
BKE_ptcache_file_close(pf2);
|
||||
return 0;
|
||||
}
|
||||
reader->set_elem(i, reader->calldata, data);
|
||||
}
|
||||
else {
|
||||
reader->set_elem(i, reader->calldata, data);
|
||||
data += incr;
|
||||
}
|
||||
}
|
||||
|
||||
if(pf) {
|
||||
BKE_ptcache_file_close(pf);
|
||||
MEM_freeN(data);
|
||||
}
|
||||
if(pf2)
|
||||
BKE_ptcache_file_close(pf2);
|
||||
|
||||
ret = PTCACHE_READ_OLD;
|
||||
}
|
||||
|
||||
if(pf)
|
||||
@@ -550,7 +580,20 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
|
||||
if(pf2)
|
||||
BKE_ptcache_file_close(pf2);
|
||||
|
||||
return 0;
|
||||
if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
|
||||
/* clear invalid cache frames so that better stuff can be simulated */
|
||||
if(pid->cache->flag & PTCACHE_OUTDATED) {
|
||||
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
|
||||
}
|
||||
else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
|
||||
if(cfra <= pid->cache->last_exact)
|
||||
pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
|
||||
|
||||
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfra,pid->cache->last_exact));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* writes cache to disk or memory */
|
||||
int BKE_ptcache_write_cache(PTCacheWriter *writer)
|
||||
@@ -559,57 +602,118 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
|
||||
PTCacheFile *pf= NULL;
|
||||
int elemsize = ptcache_pid_elemsize(writer->pid);
|
||||
int i, incr = elemsize / sizeof(float);
|
||||
int add = 0, overwrite = 0, ocfra;
|
||||
float temp[14];
|
||||
|
||||
if(writer->totelem == 0 || writer->cfra <= 0)
|
||||
return 0;
|
||||
|
||||
if(cache->flag & PTCACHE_DISK_CACHE) {
|
||||
pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
|
||||
if(!pf)
|
||||
return 0;
|
||||
/* allways start from scratch on the first frame */
|
||||
if(writer->cfra == cache->startframe) {
|
||||
BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
|
||||
cache->flag &= ~PTCACHE_REDO_NEEDED;
|
||||
add = 1;
|
||||
}
|
||||
else {
|
||||
int cfra = cache->endframe;
|
||||
/* find last cached frame */
|
||||
while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra))
|
||||
cfra--;
|
||||
|
||||
for(i=0; i<writer->totelem; i++)
|
||||
BKE_ptcache_file_write_floats(pf, writer->elem_ptr(i, writer->calldata), incr);
|
||||
/* find second last cached frame */
|
||||
ocfra = cfra-1;
|
||||
while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra))
|
||||
ocfra--;
|
||||
|
||||
if(writer->cfra > cfra) {
|
||||
if(ocfra >= cache->startframe && cfra - ocfra < cache->step)
|
||||
overwrite = 1;
|
||||
else
|
||||
add = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(add || overwrite) {
|
||||
if(overwrite)
|
||||
BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, ocfra);
|
||||
|
||||
pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
|
||||
if(!pf)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<writer->totelem; i++) {
|
||||
writer->set_elem(i, writer->calldata, &temp);
|
||||
BKE_ptcache_file_write_floats(pf, &temp, incr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PTCacheMem *pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
|
||||
PTCacheMem *pm;
|
||||
PTCacheMem *pm2;
|
||||
float *pmdata;
|
||||
|
||||
pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
|
||||
pmdata = pm->data;
|
||||
|
||||
for(i=0; i<writer->totelem; i++, pmdata+=incr)
|
||||
memcpy(pmdata, writer->elem_ptr(i, writer->calldata), elemsize);
|
||||
|
||||
pm->frame = writer->cfra;
|
||||
pm->totpoint = writer->totelem;
|
||||
|
||||
/* find add location */
|
||||
pm2 = cache->mem_cache.first;
|
||||
if(!pm2)
|
||||
BLI_addtail(&cache->mem_cache, pm);
|
||||
else if(pm2->frame == writer->cfra) {
|
||||
/* overwrite same frame */
|
||||
MEM_freeN(pm2->data);
|
||||
pm2->data = pm->data;
|
||||
MEM_freeN(pm);
|
||||
|
||||
/* allways start from scratch on the first frame */
|
||||
if(writer->cfra == cache->startframe) {
|
||||
BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
|
||||
cache->flag &= ~PTCACHE_REDO_NEEDED;
|
||||
add = 1;
|
||||
}
|
||||
else {
|
||||
while(pm2->next && pm2->next->frame < writer->cfra)
|
||||
pm2 = pm2->next;
|
||||
pm2 = cache->mem_cache.last;
|
||||
|
||||
BLI_insertlinkafter(&cache->mem_cache, pm2, pm);
|
||||
if(pm2 && writer->cfra > pm2->frame) {
|
||||
if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
|
||||
overwrite = 1;
|
||||
else
|
||||
add = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(overwrite) {
|
||||
pm = cache->mem_cache.last;
|
||||
pmdata = pm->data;
|
||||
|
||||
for(i=0; i<writer->totelem; i++, pmdata+=incr) {
|
||||
writer->set_elem(i, writer->calldata, &temp);
|
||||
memcpy(pmdata, &temp, elemsize);
|
||||
}
|
||||
|
||||
pm->frame = writer->cfra;
|
||||
}
|
||||
else if(add) {
|
||||
pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
|
||||
pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
|
||||
pmdata = pm->data;
|
||||
|
||||
for(i=0; i<writer->totelem; i++, pmdata+=incr) {
|
||||
writer->set_elem(i, writer->calldata, &temp);
|
||||
memcpy(pmdata, &temp, elemsize);
|
||||
}
|
||||
|
||||
pm->frame = writer->cfra;
|
||||
pm->totpoint = writer->totelem;
|
||||
|
||||
BLI_addtail(&cache->mem_cache, pm);
|
||||
}
|
||||
}
|
||||
|
||||
if(writer->cfra - cache->last_exact == 1)
|
||||
cache->last_exact = writer->cfra;
|
||||
if(add || overwrite) {
|
||||
if(writer->cfra - cache->last_exact == 1
|
||||
|| writer->cfra == cache->startframe) {
|
||||
cache->last_exact = writer->cfra;
|
||||
cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
|
||||
}
|
||||
else
|
||||
cache->flag |= PTCACHE_FRAMES_SKIPPED;
|
||||
}
|
||||
|
||||
if(pf)
|
||||
BKE_ptcache_file_close(pf);
|
||||
|
||||
ptcache_update_info(writer->pid);
|
||||
BKE_ptcache_update_info(writer->pid);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -730,7 +834,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
|
||||
break;
|
||||
}
|
||||
|
||||
ptcache_update_info(pid);
|
||||
BKE_ptcache_update_info(pid);
|
||||
}
|
||||
|
||||
int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
|
||||
@@ -762,6 +866,9 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
|
||||
PointCache *cache;
|
||||
float offset, time, nexttime;
|
||||
|
||||
/* TODO: this has to be sorter out once bsystem_time gets redone, */
|
||||
/* now caches can handle interpolating etc. too - jahka */
|
||||
|
||||
/* time handling for point cache:
|
||||
* - simulation time is scaled by result of bsystem_time
|
||||
* - for offsetting time only time offset is taken into account, since
|
||||
@@ -798,7 +905,7 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
|
||||
int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
|
||||
{
|
||||
PointCache *cache;
|
||||
int reset, clear, current, after;
|
||||
int reset, clear, after;
|
||||
|
||||
if(!pid->cache)
|
||||
return 0;
|
||||
@@ -806,23 +913,17 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
|
||||
cache= pid->cache;
|
||||
reset= 0;
|
||||
clear= 0;
|
||||
current= 0;
|
||||
after= 0;
|
||||
|
||||
if(mode == PTCACHE_RESET_DEPSGRAPH) {
|
||||
if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
|
||||
if(cache->flag & PTCACHE_AUTOCACHE) {
|
||||
reset= 1;
|
||||
if(cache->flag & PTCACHE_QUICK_CACHE)
|
||||
clear= 1;
|
||||
}
|
||||
else {
|
||||
current= 1;
|
||||
after= 1;
|
||||
cache->flag |= PTCACHE_OUTDATED;
|
||||
}
|
||||
|
||||
after= 1;
|
||||
}
|
||||
else
|
||||
cache->flag |= PTCACHE_OUTDATED;
|
||||
|
||||
cache->flag |= PTCACHE_OUTDATED;
|
||||
}
|
||||
else if(mode == PTCACHE_RESET_BAKED) {
|
||||
if(!BKE_ptcache_get_continue_physics()) {
|
||||
@@ -839,17 +940,9 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
|
||||
if(!(cache->flag & PTCACHE_BAKED))
|
||||
clear= 1;
|
||||
}
|
||||
else if(mode == PTCACHE_RESET_FREE) {
|
||||
if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
|
||||
if((cache->flag & PTCACHE_AUTOCACHE)==0) {
|
||||
current= 1;
|
||||
after= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(reset) {
|
||||
cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_SIMULATION_VALID);
|
||||
cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
|
||||
cache->simframe= 0;
|
||||
cache->last_exact= 0;
|
||||
|
||||
@@ -862,12 +955,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
|
||||
}
|
||||
if(clear)
|
||||
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
|
||||
if(after)
|
||||
else if(after)
|
||||
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
|
||||
if(current)
|
||||
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, CFRA);
|
||||
|
||||
return (reset || clear || current || after);
|
||||
return (reset || clear || after);
|
||||
}
|
||||
|
||||
int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
|
||||
@@ -987,6 +1078,7 @@ PointCache *BKE_ptcache_add()
|
||||
cache= MEM_callocN(sizeof(PointCache), "PointCache");
|
||||
cache->startframe= 1;
|
||||
cache->endframe= 250;
|
||||
cache->step= 10;
|
||||
|
||||
return cache;
|
||||
}
|
||||
@@ -1019,7 +1111,39 @@ PointCache *BKE_ptcache_copy(PointCache *cache)
|
||||
|
||||
|
||||
/* Baking */
|
||||
void BKE_ptcache_autocache_all(Scene *scene)
|
||||
static int count_quick_cache(Scene *scene, int *quick_step)
|
||||
{
|
||||
Base *base = scene->base.first;
|
||||
PTCacheID *pid;
|
||||
ListBase pidlist;
|
||||
int autocache_count= 0;
|
||||
|
||||
for(base = scene->base.first; base; base = base->next) {
|
||||
if(base->object) {
|
||||
BKE_ptcache_ids_from_object(&pidlist, base->object);
|
||||
|
||||
for(pid=pidlist.first; pid; pid=pid->next) {
|
||||
if((pid->cache->flag & PTCACHE_BAKED)
|
||||
|| (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
|
||||
continue;
|
||||
|
||||
if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
|
||||
if(!autocache_count)
|
||||
*quick_step = pid->cache->step;
|
||||
else
|
||||
*quick_step = MIN2(*quick_step, pid->cache->step);
|
||||
|
||||
autocache_count++;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_freelistN(&pidlist);
|
||||
}
|
||||
}
|
||||
|
||||
return autocache_count;
|
||||
}
|
||||
void BKE_ptcache_quick_cache_all(Scene *scene)
|
||||
{
|
||||
PTCacheBaker baker;
|
||||
|
||||
@@ -1032,7 +1156,7 @@ void BKE_ptcache_autocache_all(Scene *scene)
|
||||
baker.render=0;
|
||||
baker.scene=scene;
|
||||
|
||||
if(psys_count_autocache(scene, NULL))
|
||||
if(count_quick_cache(scene, &baker.quick_step))
|
||||
BKE_ptcache_make_cache(&baker);
|
||||
}
|
||||
|
||||
@@ -1050,11 +1174,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
|
||||
int endframe = CFRA;
|
||||
int bake = baker->bake;
|
||||
int render = baker->render;
|
||||
int step = baker->quick_step;
|
||||
|
||||
G.afbreek = 0;
|
||||
|
||||
//printf("Caching physics...");
|
||||
|
||||
/* set caches to baking mode and figure out start frame */
|
||||
if(pid) {
|
||||
/* cache/bake a single object */
|
||||
@@ -1063,7 +1186,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
|
||||
if(pid->type==PTCACHE_TYPE_PARTICLES)
|
||||
psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
|
||||
|
||||
if(bake || cache->flag & PTCACHE_OUTDATED)
|
||||
if(bake || cache->flag & PTCACHE_REDO_NEEDED)
|
||||
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
|
||||
|
||||
startframe = MAX2(cache->last_exact, cache->startframe);
|
||||
@@ -1072,8 +1195,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
|
||||
endframe = cache->endframe;
|
||||
cache->flag |= PTCACHE_BAKING;
|
||||
}
|
||||
else
|
||||
else {
|
||||
endframe = MIN2(endframe, cache->endframe);
|
||||
}
|
||||
|
||||
cache->flag &= ~PTCACHE_BAKED;
|
||||
}
|
||||
@@ -1088,31 +1212,30 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
|
||||
if(pid->type==PTCACHE_TYPE_PARTICLES)
|
||||
psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
|
||||
|
||||
if(cache->flag & PTCACHE_OUTDATED)
|
||||
if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
|
||||
&& ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
|
||||
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
|
||||
|
||||
startframe = MIN2(startframe, cache->startframe);
|
||||
|
||||
if(bake) {
|
||||
endframe = MAX2(endframe, cache->endframe);
|
||||
if(bake || render) {
|
||||
cache->flag |= PTCACHE_BAKING;
|
||||
|
||||
if(bake)
|
||||
endframe = MAX2(endframe, cache->endframe);
|
||||
}
|
||||
else if(render)
|
||||
cache->flag |= PTCACHE_BAKING;
|
||||
|
||||
cache->flag &= ~PTCACHE_BAKED;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
BLI_freelistN(&pidlist);
|
||||
}
|
||||
|
||||
CFRA= startframe;
|
||||
scene->r.framelen = 1.0;
|
||||
scene_update_for_newframe(scene, scene->lay);
|
||||
|
||||
for(; CFRA <= endframe; CFRA++) {
|
||||
for(; CFRA <= endframe; CFRA+=step) {
|
||||
float prog;
|
||||
|
||||
if(bake)
|
||||
@@ -1133,7 +1256,8 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
|
||||
|
||||
/* clear baking flag */
|
||||
if(pid) {
|
||||
cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
|
||||
cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
|
||||
cache->flag |= PTCACHE_SIMULATION_VALID;
|
||||
if(bake)
|
||||
cache->flag |= PTCACHE_BAKED;
|
||||
}
|
||||
@@ -1141,17 +1265,26 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
|
||||
BKE_ptcache_ids_from_object(&pidlist, base->object);
|
||||
|
||||
for(pid=pidlist.first; pid; pid=pid->next) {
|
||||
cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
|
||||
cache = pid->cache;
|
||||
|
||||
if(step > 1)
|
||||
cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
|
||||
else
|
||||
cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
|
||||
|
||||
cache->flag |= PTCACHE_SIMULATION_VALID;
|
||||
|
||||
if(bake)
|
||||
cache->flag |= PTCACHE_BAKED;
|
||||
}
|
||||
BLI_freelistN(&pidlist);
|
||||
}
|
||||
|
||||
//printf("done!\n");
|
||||
|
||||
scene->r.framelen = frameleno;
|
||||
CFRA = cfrao;
|
||||
scene_update_for_newframe(scene, scene->lay);
|
||||
|
||||
/* TODO: call redraw all windows somehow */
|
||||
}
|
||||
|
||||
void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
|
||||
@@ -1161,6 +1294,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
|
||||
int totelem=0;
|
||||
int float_count=0;
|
||||
int tot;
|
||||
int last_exact = cache->last_exact;
|
||||
|
||||
if (!G.relbase_valid){
|
||||
cache->flag &= ~PTCACHE_DISK_CACHE;
|
||||
@@ -1230,6 +1364,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
|
||||
}
|
||||
|
||||
pm->frame = cfra;
|
||||
pm->totpoint = totelem;
|
||||
|
||||
BLI_addtail(&pid->cache->mem_cache, pm);
|
||||
|
||||
@@ -1241,4 +1376,8 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
|
||||
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
|
||||
cache->flag &= ~PTCACHE_DISK_CACHE;
|
||||
}
|
||||
|
||||
cache->last_exact = last_exact;
|
||||
|
||||
BKE_ptcache_update_info(pid);
|
||||
}
|
||||
|
||||
@@ -9013,6 +9013,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
Tex *tx;
|
||||
ParticleSettings *part;
|
||||
Object *ob;
|
||||
PTCacheID *pid;
|
||||
ListBase pidlist;
|
||||
|
||||
for(screen= main->screen.first; screen; screen= screen->id.next) {
|
||||
do_versions_windowmanager_2_50(screen);
|
||||
@@ -9073,14 +9075,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
}
|
||||
/* set old pointcaches to have disk cache flag */
|
||||
for(ob = main->object.first; ob; ob= ob->id.next) {
|
||||
ParticleSystem *psys = ob->particlesystem.first;
|
||||
|
||||
for(; psys; psys=psys->next) {
|
||||
if(psys->pointcache)
|
||||
psys->pointcache->flag |= PTCACHE_DISK_CACHE;
|
||||
}
|
||||
BKE_ptcache_ids_from_object(&pidlist, ob);
|
||||
|
||||
/* TODO: softbody & cloth caches */
|
||||
for(pid=pidlist.first; pid; pid=pid->next)
|
||||
pid->cache->flag |= PTCACHE_DISK_CACHE;
|
||||
|
||||
BLI_freelistN(&pidlist);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -552,6 +552,7 @@ static void write_userdef(WriteData *wd)
|
||||
|
||||
/* TODO: replace *cache with *cachelist once it's coded */
|
||||
#define PTCACHE_WRITE_PSYS 0
|
||||
#define PTCACHE_WRITE_CLOTH 1
|
||||
static void write_pointcaches(WriteData *wd, PointCache *cache, int type)
|
||||
{
|
||||
writestruct(wd, DATA, "PointCache", 1, cache);
|
||||
@@ -563,6 +564,8 @@ static void write_pointcaches(WriteData *wd, PointCache *cache, int type)
|
||||
writestruct(wd, DATA, "PTCacheMem", 1, pm);
|
||||
if(type==PTCACHE_WRITE_PSYS)
|
||||
writestruct(wd, DATA, "ParticleKey", pm->totpoint, pm->data);
|
||||
else if(type==PTCACHE_WRITE_CLOTH)
|
||||
writedata(wd, DATA, 9 * sizeof(float) * pm->totpoint, pm->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1025,7 +1028,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo)
|
||||
|
||||
writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
|
||||
writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
|
||||
writestruct(wd, DATA, "PointCache", 1, clmd->point_cache);
|
||||
write_pointcaches(wd, clmd->point_cache, PTCACHE_WRITE_CLOTH);
|
||||
}
|
||||
else if(md->type==eModifierType_Fluidsim) {
|
||||
FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_particle.h"
|
||||
@@ -39,7 +40,7 @@
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_modifier.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
@@ -81,6 +82,7 @@ static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
|
||||
baker.pid = NULL;
|
||||
baker.bake = RNA_boolean_get(op->ptr, "bake");
|
||||
baker.render = 0;
|
||||
baker.quick_step = 1;
|
||||
baker.break_test = cache_break_test;
|
||||
baker.break_data = NULL;
|
||||
baker.progressbar = (void (*)(void *, int))WM_timecursor;
|
||||
@@ -104,12 +106,11 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *op)
|
||||
|
||||
for(pid=pidlist.first; pid; pid=pid->next) {
|
||||
pid->cache->flag &= ~PTCACHE_BAKED;
|
||||
BKE_ptcache_id_reset(scene, pid, PTCACHE_RESET_OUTDATED);
|
||||
}
|
||||
|
||||
BLI_freelistN(&pidlist);
|
||||
}
|
||||
|
||||
BLI_freelistN(&pidlist);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
@@ -127,6 +128,8 @@ void PTCACHE_OT_bake_all(wmOperatorType *ot)
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
|
||||
}
|
||||
void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
|
||||
{
|
||||
@@ -142,6 +145,112 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/**************************** cloth **********************************/
|
||||
static int ptcache_bake_cloth_poll(bContext *C)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *ob= CTX_data_active_object(C);
|
||||
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
|
||||
|
||||
if(!scene || !ob || ob->id.lib || !clmd)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ptcache_bake_cloth_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *ob= CTX_data_active_object(C);
|
||||
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
|
||||
PTCacheID pid;
|
||||
PTCacheBaker baker;
|
||||
|
||||
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
|
||||
|
||||
baker.scene = scene;
|
||||
baker.pid = &pid;
|
||||
baker.bake = RNA_boolean_get(op->ptr, "bake");
|
||||
baker.render = 0;
|
||||
baker.quick_step = 1;
|
||||
baker.break_test = cache_break_test;
|
||||
baker.break_data = NULL;
|
||||
baker.progressbar = WM_timecursor;
|
||||
baker.progresscontext = CTX_wm_window(C);
|
||||
|
||||
BKE_ptcache_make_cache(&baker);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
static int ptcache_free_bake_cloth_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object *ob= CTX_data_active_object(C);
|
||||
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
|
||||
PTCacheID pid;
|
||||
|
||||
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
|
||||
pid.cache->flag &= ~PTCACHE_BAKED;
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
void PTCACHE_OT_cache_cloth(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Bake Cloth";
|
||||
ot->idname= "PTCACHE_OT_cache_cloth";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= ptcache_bake_cloth_exec;
|
||||
ot->poll= ptcache_bake_cloth_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
|
||||
}
|
||||
void PTCACHE_OT_free_bake_cloth(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Free Cloth Bake";
|
||||
ot->idname= "PTCACHE_OT_free_bake_cloth";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= ptcache_free_bake_cloth_exec;
|
||||
ot->poll= ptcache_bake_cloth_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
static int ptcache_bake_from_cloth_cache_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob= CTX_data_active_object(C);
|
||||
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
|
||||
PTCacheID pid;
|
||||
|
||||
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
|
||||
pid.cache->flag |= PTCACHE_BAKED;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
void PTCACHE_OT_bake_from_cloth_cache(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Bake From Cache";
|
||||
ot->idname= "PTCACHE_OT_bake_from_cloth_cache";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= ptcache_bake_from_cloth_cache_exec;
|
||||
ot->poll= ptcache_bake_cloth_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/**************************** particles **********************************/
|
||||
static int ptcache_bake_particle_system_poll(bContext *C)
|
||||
{
|
||||
@@ -168,6 +277,7 @@ static int ptcache_bake_particle_system_exec(bContext *C, wmOperator *op)
|
||||
baker.pid = &pid;
|
||||
baker.bake = RNA_boolean_get(op->ptr, "bake");
|
||||
baker.render = 0;
|
||||
baker.quick_step = 1;
|
||||
baker.break_test = cache_break_test;
|
||||
baker.break_data = NULL;
|
||||
baker.progressbar = (void (*)(void *, int))WM_timecursor;
|
||||
@@ -188,7 +298,6 @@ static int ptcache_free_bake_particle_system_exec(bContext *C, wmOperator *op)
|
||||
|
||||
BKE_ptcache_id_from_particles(&pid, ob, psys);
|
||||
psys->pointcache->flag &= ~PTCACHE_BAKED;
|
||||
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
|
||||
|
||||
@@ -256,6 +365,9 @@ void ED_operatortypes_pointcache(void)
|
||||
WM_operatortype_append(PTCACHE_OT_cache_particle_system);
|
||||
WM_operatortype_append(PTCACHE_OT_free_bake_particle_system);
|
||||
WM_operatortype_append(PTCACHE_OT_bake_from_particles_cache);
|
||||
WM_operatortype_append(PTCACHE_OT_cache_cloth);
|
||||
WM_operatortype_append(PTCACHE_OT_free_bake_cloth);
|
||||
WM_operatortype_append(PTCACHE_OT_bake_from_cloth_cache);
|
||||
}
|
||||
|
||||
//void ED_keymap_pointcache(wmWindowManager *wm)
|
||||
|
||||
@@ -4674,6 +4674,12 @@ void special_aftertrans_update(TransInfo *t)
|
||||
/* pointcache refresh */
|
||||
if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
|
||||
ob->recalc |= OB_RECALC_DATA;
|
||||
|
||||
/* Needed for proper updating of "quick cached" dynamics. */
|
||||
/* Creates troubles for moving animated objects without */
|
||||
/* autokey though, probably needed is an anim sys override? */
|
||||
/* Please remove if some other solution is found. -jahka */
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_OB);
|
||||
|
||||
/* Set autokey if necessary */
|
||||
if (!cancelled)
|
||||
|
||||
@@ -82,7 +82,8 @@ typedef struct PTCacheMem {
|
||||
} PTCacheMem;
|
||||
|
||||
typedef struct PointCache {
|
||||
int flag, rt; /* generic flag */
|
||||
int flag; /* generic flag */
|
||||
int step; /* frames between cached frames */
|
||||
int simframe; /* current frame of simulation (only if SIMULATION_VALID) */
|
||||
int startframe; /* simulation start frame */
|
||||
int endframe; /* simulation end frame */
|
||||
@@ -263,7 +264,11 @@ typedef struct SoftBody {
|
||||
#define PTCACHE_BAKE_EDIT 16
|
||||
#define PTCACHE_BAKE_EDIT_ACTIVE 32
|
||||
#define PTCACHE_DISK_CACHE 64
|
||||
#define PTCACHE_AUTOCACHE 128
|
||||
#define PTCACHE_QUICK_CACHE 128
|
||||
#define PTCACHE_FRAMES_SKIPPED 256
|
||||
|
||||
/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
|
||||
#define PTCACHE_REDO_NEEDED 258
|
||||
|
||||
/* ob->softflag */
|
||||
#define OB_SB_ENABLE 1
|
||||
|
||||
@@ -34,9 +34,24 @@
|
||||
#include "BKE_modifier.h"
|
||||
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
|
||||
static void rna_cloth_update(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *ob = ptr->id.data;
|
||||
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
}
|
||||
|
||||
static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value)
|
||||
{
|
||||
ClothSimSettings *settings = (ClothSimSettings*)ptr->data;
|
||||
@@ -165,42 +180,50 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_float_sdna(prop, NULL, "mingoal");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Goal Minimum", "Goal minimum, vertex group weights are scaled to match this range.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "goal_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "maxgoal");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Goal Maximum", "Goal maximum, vertex group weights are scaled to match this range.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "goal_default", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "defgoal");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value, when no Vertex Group used.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "goalspring");
|
||||
RNA_def_property_range(prop, 0.0f, 0.999f);
|
||||
RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "goalfrict");
|
||||
RNA_def_property_range(prop, 0.0f, 50.0f);
|
||||
RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
/* mass */
|
||||
|
||||
prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0f, 10.0f);
|
||||
RNA_def_property_ui_text(prop, "Mass", "Mass of cloth material.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "mass_vertex_group", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop, "rna_ClothSettings_mass_vgroup_get", "rna_ClothSettings_mass_vgroup_length", "rna_ClothSettings_mass_vgroup_set");
|
||||
RNA_def_property_ui_text(prop, "Mass Vertex Group", "Vertex group for fine control over mass distribution.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_VECTOR);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_range(prop, -100.0, 100.0);
|
||||
RNA_def_property_float_funcs(prop, "rna_ClothSettings_gravity_get", "rna_ClothSettings_gravity_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Gravity", "Gravity or external force vector.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
/* various */
|
||||
|
||||
@@ -208,61 +231,73 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
|
||||
RNA_def_property_float_sdna(prop, NULL, "Cvi");
|
||||
RNA_def_property_range(prop, 0.0f, 10.0f);
|
||||
RNA_def_property_ui_text(prop, "Air Damping", "Air has normally some thickness which slows falling things down.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "pin_cloth", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_GOAL);
|
||||
RNA_def_property_ui_text(prop, "Pin Cloth", "Define forces for vertices to stick to animated position.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "pin_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "goalspring");
|
||||
RNA_def_property_range(prop, 0.0f, 50.0);
|
||||
RNA_def_property_ui_text(prop, "Pin Stiffness", "Pin (vertex target position) spring stiffness.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "quality", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "stepsPerFrame");
|
||||
RNA_def_property_range(prop, 4, 80);
|
||||
RNA_def_property_ui_text(prop, "Quality", "Quality of the simulation in steps per frame (higher is better quality but slower).");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
/* springs */
|
||||
|
||||
prop= RNA_def_property(srna, "stiffness_scaling", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_SCALING);
|
||||
RNA_def_property_ui_text(prop, "Stiffness Scaling", "If enabled, stiffness can be scaled along a weight painted vertex group.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "spring_damping", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "Cdis");
|
||||
RNA_def_property_range(prop, 0.0f, 50.0f);
|
||||
RNA_def_property_ui_text(prop, "Spring Damping", "Damping of cloth velocity (higher = more smooth, less jiggling)");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "structural");
|
||||
RNA_def_property_range(prop, 1.0f, 10000.0f);
|
||||
RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "structural_stiffness_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_struct");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_struct_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Structural Stiffness Maximum", "Maximum structural stiffness value.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "structural_stiffness_vertex_group", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop, "rna_ClothSettings_struct_vgroup_get", "rna_ClothSettings_struct_vgroup_length", "rna_ClothSettings_struct_vgroup_set");
|
||||
RNA_def_property_ui_text(prop, "Structural Stiffness Vertex Group", "Vertex group for fine control over structural stiffness.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "bending");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_ui_text(prop, "Bending Stiffness", "Wrinkle coefficient (higher = less smaller but more big wrinkles).");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "bending_stiffness_max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "max_bend");
|
||||
RNA_def_property_range(prop, 0.0f, 10000.0f);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_bend_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Bending Stiffness Maximum", "Maximum bending stiffness value.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "bending_vertex_group", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop, "rna_ClothSettings_bend_vgroup_get", "rna_ClothSettings_bend_vgroup_length", "rna_ClothSettings_bend_vgroup_set");
|
||||
RNA_def_property_ui_text(prop, "Bending Stiffness Vertex Group", "Vertex group for fine control over bending stiffness.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
/* unused */
|
||||
|
||||
@@ -323,40 +358,48 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "enable_collision", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_ENABLED);
|
||||
RNA_def_property_ui_text(prop, "Enable Collision", "Enable collisions with other objects.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "min_distance", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "epsilon");
|
||||
RNA_def_property_range(prop, 0.001f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Minimum Distance", "Minimum distance between collision objects before collision response takes in, can be changed for each frame.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "friction", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0f, 80.0f);
|
||||
RNA_def_property_ui_text(prop, "Friction", "Friction force if a collision happened (0=movement not changed, 100=no movement left)");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "collision_quality", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "loop_count");
|
||||
RNA_def_property_range(prop, 1, 20);
|
||||
RNA_def_property_ui_text(prop, "Collision Quality", "How many collision iterations should be done. (higher is better quality but slower)");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
/* self collision */
|
||||
|
||||
prop= RNA_def_property(srna, "enable_self_collision", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_SELF);
|
||||
RNA_def_property_ui_text(prop, "Enable Self Collision", "Enable self collisions.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "self_min_distance", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "selfepsilon");
|
||||
RNA_def_property_range(prop, 0.5f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Self Minimum Distance", "0.5 means no distance at all, 1.0 is maximum distance");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "self_friction", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0f, 80.0f);
|
||||
RNA_def_property_ui_text(prop, "Self Friction", "Friction/damping with self contact.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
|
||||
prop= RNA_def_property(srna, "self_collision_quality", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "self_loop_count");
|
||||
RNA_def_property_range(prop, 1, 10);
|
||||
RNA_def_property_ui_text(prop, "Self Collision Quality", "How many self collision iterations should be done. (higher is better quality but slower), can be changed for each frame.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
|
||||
}
|
||||
|
||||
void RNA_def_cloth(BlenderRNA *brna)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
@@ -40,9 +41,38 @@
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
static void rna_Cache_change(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
PointCache *cache = (PointCache*)ptr->data;
|
||||
PTCacheID *pid = NULL;
|
||||
ListBase pidlist;
|
||||
|
||||
if(!ob)
|
||||
return;
|
||||
|
||||
cache->flag |= PTCACHE_OUTDATED;
|
||||
|
||||
BKE_ptcache_ids_from_object(&pidlist, ob);
|
||||
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
|
||||
for(pid=pidlist.first; pid; pid=pid->next) {
|
||||
if(pid->cache==cache)
|
||||
break;
|
||||
}
|
||||
|
||||
if(pid)
|
||||
BKE_ptcache_update_info(pid);
|
||||
|
||||
BLI_freelistN(&pidlist);
|
||||
}
|
||||
|
||||
static void rna_Cache_toggle_disk_cache(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
@@ -240,6 +270,12 @@ static void rna_def_pointcache(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 1, 300000);
|
||||
RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops.");
|
||||
|
||||
prop= RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "step");
|
||||
RNA_def_property_range(prop, 1, 20);
|
||||
RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames.");
|
||||
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
|
||||
|
||||
/* flags */
|
||||
prop= RNA_def_property(srna, "baked", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKED);
|
||||
@@ -257,21 +293,24 @@ static void rna_def_pointcache(BlenderRNA *brna)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Cache is outdated", "");
|
||||
|
||||
prop= RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "name");
|
||||
RNA_def_property_ui_text(prop, "Name", "Cache name");
|
||||
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
|
||||
|
||||
prop= RNA_def_property(srna, "autocache", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_AUTOCACHE);
|
||||
RNA_def_property_ui_text(prop, "Auto Cache", "Cache changes automatically");
|
||||
//RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_autocache");
|
||||
prop= RNA_def_property(srna, "quick_cache", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE);
|
||||
RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps");
|
||||
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
|
||||
|
||||
prop= RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "info");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status.");
|
||||
|
||||
}
|
||||
|
||||
static void rna_def_collision(BlenderRNA *brna)
|
||||
|
||||
@@ -2421,6 +2421,7 @@ static void update_physics_cache(Render *re, Scene *scene)
|
||||
baker.pid = NULL;
|
||||
baker.bake = 0;
|
||||
baker.render = 1;
|
||||
baker.quick_step = 1;
|
||||
baker.break_test = re->test_break;
|
||||
baker.break_data = re->tbh;
|
||||
baker.progressbar = NULL;
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_pointcache.h"
|
||||
|
||||
#include "ED_fileselect.h"
|
||||
#include "ED_screen.h"
|
||||
@@ -234,6 +235,8 @@ void wm_event_do_notifiers(bContext *C)
|
||||
for(base= scene->base.first; base; base= base->next) {
|
||||
object_handle_update(scene, base->object);
|
||||
}
|
||||
|
||||
BKE_ptcache_quick_cache_all(scene);
|
||||
}
|
||||
}
|
||||
CTX_wm_window_set(C, NULL);
|
||||
|
||||
Reference in New Issue
Block a user