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

Reply via email to