Revision: 21810
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=21810
Author: jhk
Date: 2009-07-23 02:19:01 +0200 (Thu, 23 Jul 2009)
Log Message:
-----------
External cache
Particle point cache can now be loaded from external files.
- Activated by "external" checkbox in cache panel and giving proper folder path
and file name identifier.
- External cache panel has controls for particle emission start, end, lifetime
and random lifetime. These should be set according to the external data for
correct playback.
- External files should be named "identifier_frame_index.bphys" or
"identifier_frame.bphys" where:
* "identifier" is a freely choseable name.
* "frame" is the cached frame number.
** Six digits padded with zeros!, for example "000024".
* "index" can be used to tell caches with the same identifier apart.
** Two digits starting from zero.
** The index and the underscore before are optional. If no
index is present the index number in ui should be set to -1.
- Cache file format is pure floating point numbers (in binary, not text!) with
each particle's data one after the other with the following data members:
* 3 floats: particle's location vector
* 3 floats: particle's velocity vector (per second)
* 4 floats: particle's rotation quaternion
* 3 floats: particle's angular velocity vector (per second)
* 1 float: frame of the actual data (this can be non-integer for
particles that are born or die between two integer frames, but otherwise should
be the same as the "frame" in the file name)
- Cache files don't have to exist for each frame.
* Frames without actual data are interpolated from surrounding frames
that have data (extrapolation is not supported).
- Cache file formats with extended (or reduced even) data members are in future
plans for easier usage.
- Current code only does particles, don't yet know if it's applicable to cloth
or sb.
- Known issue: endianness can't yet be handled in any way.
Other changes:
New hard limits for many particle parameters. Some examples:
- Maximum amount of particles: 10M particles :) And before you all go and crash
your Blender trying this out remember that this limit is only for those freaks
who really have the machine power to handle it. 10M particles alone take around
2.2 Gb of memory / disk space in saved file and each cached frame takes around
0.5 Gb of memory / disk space depending on cache mode.
* Known issue: To actually use this many particles they most likely
need to be allocated in parts as taking hold of a 2.2Gb chunk of memory at once
is probably not ok with any operating system.
- Maximum amount of children: 100k children/particle (1T childparticles here we
come :D)
- Kink frequency: -100k to 100k half-rotations (really strange the previous
limit was only from zero upwards)
- Path draw steps: 10 (power of 2 remember)
- Path render steps: 20 (power of 2 also!! If over 1M segments doesn't get you
smooth paths then I think nothing will!)
Modified Paths:
--------------
branches/blender2.5/blender/release/ui/buttons_particle.py
branches/blender2.5/blender/source/blender/blenkernel/BKE_pointcache.h
branches/blender2.5/blender/source/blender/blenkernel/intern/particle_system.c
branches/blender2.5/blender/source/blender/blenkernel/intern/pointcache.c
branches/blender2.5/blender/source/blender/makesdna/DNA_object_force.h
branches/blender2.5/blender/source/blender/makesdna/DNA_particle_types.h
branches/blender2.5/blender/source/blender/makesrna/intern/rna_object_force.c
branches/blender2.5/blender/source/blender/makesrna/intern/rna_particle.c
Modified: branches/blender2.5/blender/release/ui/buttons_particle.py
===================================================================
--- branches/blender2.5/blender/release/ui/buttons_particle.py 2009-07-22
23:27:10 UTC (rev 21809)
+++ branches/blender2.5/blender/release/ui/buttons_particle.py 2009-07-23
00:19:01 UTC (rev 21810)
@@ -86,6 +86,12 @@
__idname__= "PARTICLE_PT_emission"
__label__ = "Emission"
+ def poll(self, context):
+ if particle_panel_poll(context):
+ return not context.particle_system.point_cache.external
+ else:
+ return False
+
def draw(self, context):
layout = self.layout
@@ -150,38 +156,61 @@
cache = psys.point_cache
row = layout.row()
- row.itemR(cache, "name")
+ row.itemL(text="File Name:")
+ row.itemR(cache, "external")
- row = layout.row()
-
- if cache.baked == True:
- row.itemO("ptcache.free_bake_particle_system",
text="Free Bake")
+ if cache.external:
+ split = layout.split(percentage=0.80)
+ split.itemR(cache, "name", text="")
+ split.itemR(cache, "index", text="")
+
+ layout.itemL(text="File Path:")
+ layout.itemR(cache, "filepath", text="")
+
+ layout.itemL(text=cache.info)
+
+ split = layout.split()
+
+ col = split.column(align=True)
+ col.itemR(part, "start")
+ col.itemR(part, "end")
+
+ col = split.column(align=True)
+ col.itemR(part, "lifetime")
+ col.itemR(part, "random_lifetime", slider=True)
else:
- row.item_booleanO("ptcache.cache_particle_system",
"bake", True, text="Bake")
+ layout.itemR(cache, "name", text="")
+
+ row = layout.row()
- subrow = row.row()
- subrow.enabled = (cache.frames_skipped or cache.outdated) and
particle_panel_enabled(psys)
- subrow.itemO("ptcache.cache_particle_system", text="Calculate
to Current Frame")
+ if cache.baked == True:
+ row.itemO("ptcache.free_bake_particle_system",
text="Free Bake")
+ else:
+
row.item_booleanO("ptcache.cache_particle_system", "bake", True, text="Bake")
- row = layout.row()
- row.enabled = particle_panel_enabled(psys)
- row.itemO("ptcache.bake_from_particles_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")
+ subrow = row.row()
+ subrow.enabled = (cache.frames_skipped or
cache.outdated) and particle_panel_enabled(psys)
+ subrow.itemO("ptcache.cache_particle_system",
text="Calculate to Current Frame")
+
+ row = layout.row()
+ row.enabled = particle_panel_enabled(psys)
+ row.itemO("ptcache.bake_from_particles_cache",
text="Current Cache to Bake")
+ row.itemR(cache, "step");
- layout.itemL(text=cache.info)
+ row = layout.row()
+ row.enabled = particle_panel_enabled(psys)
+ row.itemR(cache, "quick_cache")
+ row.itemR(cache, "disk_cache")
- layout.itemS()
+ layout.itemL(text=cache.info)
+
+ layout.itemS()
+
+ row = layout.row()
+ row.item_booleanO("ptcache.bake_all", "bake", True,
text="Bake All Dynamics")
+ row.itemO("ptcache.free_bake_all", text="Free All
Bakes")
+ layout.itemO("ptcache.bake_all", text="Update All
Dynamics to current frame")
- row = layout.row()
- row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake
All Dynamics")
- row.itemO("ptcache.free_bake_all", text="Free All Bakes")
- layout.itemO("ptcache.bake_all", text="Update All Dynamics to
current frame")
-
# for particles these are figured out automatically
#row.itemR(cache, "start_frame")
#row.itemR(cache, "end_frame")
@@ -193,7 +222,7 @@
def poll(self, context):
if particle_panel_poll(context):
psys = context.particle_system
- return psys.settings.physics_type != 'BOIDS'
+ return psys.settings.physics_type != 'BOIDS' and not
psys.point_cache.external
else:
return False
@@ -256,6 +285,12 @@
class PARTICLE_PT_physics(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_physics"
__label__ = "Physics"
+
+ def poll(self, context):
+ if particle_panel_poll(context):
+ return not context.particle_system.point_cache.external
+ else:
+ return False
def draw(self, context):
layout = self.layout
@@ -399,12 +434,15 @@
psys = context.particle_system
if psys==None: return False
if psys.settings==None: return False
+ if psys.point_cache.external: return False
return psys.settings.physics_type=='BOIDS'
def draw(self, context):
boids = context.particle_system.settings.boids
layout = self.layout
+ layout.enabled = particle_panel_enabled(psys)
+
# Currently boids can only use the first state so these are
commented out for now.
#row = layout.row()
#row.template_list(boids, "states", boids,
"active_boid_state_index", compact="True")
@@ -764,12 +802,6 @@
__label__ = "Effectors"
__default_closed__ = True
- def poll(self, context):
- psys = context.particle_system
- if psys==None: return False
- if psys.settings==None: return False
- return True;
-
def draw(self, context):
layout = self.layout
Modified: branches/blender2.5/blender/source/blender/blenkernel/BKE_pointcache.h
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/BKE_pointcache.h
2009-07-22 23:27:10 UTC (rev 21809)
+++ branches/blender2.5/blender/source/blender/blenkernel/BKE_pointcache.h
2009-07-23 00:19:01 UTC (rev 21810)
@@ -166,4 +166,6 @@
void BKE_ptcache_make_cache(struct PTCacheBaker* baker);
void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
+void BKE_ptcache_load_external(struct PTCacheID *pid);
+
#endif
Modified:
branches/blender2.5/blender/source/blender/blenkernel/intern/particle_system.c
===================================================================
---
branches/blender2.5/blender/source/blender/blenkernel/intern/particle_system.c
2009-07-22 23:27:10 UTC (rev 21809)
+++
branches/blender2.5/blender/source/blender/blenkernel/intern/particle_system.c
2009-07-23 00:19:01 UTC (rev 21810)
@@ -3982,7 +3982,8 @@
/* update alive status and push events */
if(pa->time >= cfra) {
pa->alive = pa->time==cfra ? PARS_ALIVE : PARS_UNBORN;
- reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra,
NULL, NULL, NULL);
+ if((psys->pointcache->flag & PTCACHE_EXTERNAL) == 0)
+ reset_particle(scene, pa, psys, psmd, ob, 0.0f,
cfra, NULL, NULL, NULL);
}
else if(dietime <= cfra){
if(dietime > psys->cfra){
@@ -4303,7 +4304,9 @@
oldtotpart = psys->totpart;
oldtotchild = psys->totchild;
- if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT)
+ if(psys->pointcache->flag & PTCACHE_EXTERNAL)
+ totpart = pid.cache->totpoint;
+ else if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT)
totpart = part->grid_res*part->grid_res*part->grid_res;
else
totpart = psys->part->totpart;
Modified:
branches/blender2.5/blender/source/blender/blenkernel/intern/pointcache.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/intern/pointcache.c
2009-07-22 23:27:10 UTC (rev 21809)
+++ branches/blender2.5/blender/source/blender/blenkernel/intern/pointcache.c
2009-07-23 00:19:01 UTC (rev 21810)
@@ -181,7 +181,11 @@
lib= (pid)? pid->ob->id.lib: NULL;
- if (G.relbase_valid || lib) {
+ if(pid->cache->flag & PTCACHE_EXTERNAL) {
+ strcpy(filename, pid->cache->path);
+ return BLI_add_slash(filename); /* new strlen() */
+ }
+ else if (G.relbase_valid || lib) {
char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the
file */
char *blendfilename;
@@ -214,14 +218,14 @@
filename[0] = '\0';
newname = filename;
- if (!G.relbase_valid) return 0; /* save blend file before using disk
pointcache */
+ if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0)
return 0; /* save blend file before using disk pointcache */
/* start with temp dir */
if (do_path) {
len = ptcache_path(pid, filename);
newname += len;
}
- if(strcmp(pid->cache->name, "")==0) {
+ if(strcmp(pid->cache->name, "")==0 && (pid->cache->flag &
PTCACHE_EXTERNAL)==0) {
idname = (pid->ob->id.name+2);
/* convert chars to hex so they are always a valid filename */
while('\0' != *idname) {
@@ -238,7 +242,15 @@
}
if (do_ext) {
- snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT,
cfra, pid->stack_index); /* always 6 chars */
+ if(pid->cache->flag & PTCACHE_EXTERNAL) {
+ if(pid->cache->index >= 0)
+ snprintf(newname, MAX_PTCACHE_FILE,
"_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+ else
+ snprintf(newname, MAX_PTCACHE_FILE,
"_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
+ }
+ else {
+ snprintf(newname, MAX_PTCACHE_FILE,
"_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+ }
len += 16;
}
@@ -256,7 +268,7 @@
if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
return NULL;
- if (!G.relbase_valid) return NULL; /* save blend file before using disk
pointcache */
+ if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0)
return NULL; /* save blend file before using disk pointcache */
BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
@@ -328,6 +340,21 @@
int totframes = 0;
char mem_info[64];
+ if(cache->flag & PTCACHE_EXTERNAL) {
+ int cfra = cache->startframe;
+
+ for(; cfra<=cache->endframe; cfra++) {
+ if(BKE_ptcache_id_exist(pid, cfra))
+ totframes++;
+ }
+
+ if(totframes)
+ sprintf(cache->info, "%i points read for %i frames",
cache->totpoint, totframes);
+ else
+ sprintf(cache->info, "No valid data to read!");
+ return;
+ }
+
if(cache->flag & PTCACHE_DISK_CACHE) {
int cfra = cache->startframe;
@@ -743,7 +770,7 @@
char path_full[MAX_PTCACHE_FILE];
char ext[MAX_PTCACHE_PATH];
- if(!pid->cache)
+ if(!pid->cache || pid->cache->flag & PTCACHE_BAKED)
return;
/* don't allow clearing for linked objects */
@@ -1408,3 +1435,77 @@
BKE_ptcache_update_info(pid);
}
+
+void BKE_ptcache_load_external(PTCacheID *pid)
+{
+ PointCache *cache = pid->cache;
+ int len; /* store the length of the string */
+
+ /* mode is same as fopen's modes */
+ DIR *dir;
+ struct dirent *de;
+ char path[MAX_PTCACHE_PATH];
+ char filename[MAX_PTCACHE_FILE];
+ char path_full[MAX_PTCACHE_FILE];
+ char ext[MAX_PTCACHE_PATH];
+
+ if(!cache)
+ return;
+
+ cache->startframe = MAXFRAME;
+ cache->endframe = -1;
+ cache->totpoint = 0;
+
+ ptcache_path(pid, path);
+
@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs