Revision: 27131
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=27131
Author:   jhk
Date:     2010-02-25 01:03:16 +0100 (Thu, 25 Feb 2010)

Log Message:
-----------
Fix for [#19955] 2.5 Particles are calculated wrong when object has any 
transform animation
* The exact location of particle birth wasn't cached if cache step was greater 
than 1, so the interpolation from an unborn particle to a living one wasn't 
accurate at all.
* Although not ideal, the current solution is to copy the birth location to the 
previous cached frame so it's always exact. This should work properly for 
memory & disk cache.
* This fix shouldn't cause any problems, but exhaustive tests of caching are 
difficult so be sure to let me know if there's strange behavior.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_pointcache.h
    trunk/blender/source/blender/blenkernel/intern/pointcache.c

Modified: trunk/blender/source/blender/blenkernel/BKE_pointcache.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_pointcache.h    2010-02-24 
23:01:49 UTC (rev 27130)
+++ trunk/blender/source/blender/blenkernel/BKE_pointcache.h    2010-02-25 
00:03:16 UTC (rev 27131)
@@ -55,6 +55,7 @@
 /* File open options, for BKE_ptcache_file_open */
 #define PTCACHE_FILE_READ      0
 #define PTCACHE_FILE_WRITE     1
+#define PTCACHE_FILE_UPDATE    2
 
 /* PTCacheID types */
 #define PTCACHE_TYPE_SOFTBODY                  0

Modified: trunk/blender/source/blender/blenkernel/intern/pointcache.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/pointcache.c 2010-02-24 
23:01:49 UTC (rev 27130)
+++ trunk/blender/source/blender/blenkernel/intern/pointcache.c 2010-02-25 
00:03:16 UTC (rev 27131)
@@ -203,9 +203,9 @@
        ParticleData *pa = psys->particles + index;
        BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? 
pa->boid : NULL;
        float times[3] = {pa->time, pa->dietime, pa->lifetime};
+       int step = psys->pointcache->step;
 
        if(data[BPHYS_DATA_INDEX]) {
-               int step = psys->pointcache->step;
                /* No need to store unborn or died particles */
                if(pa->time - step > pa->state.time || pa->dietime + step < 
pa->state.time)
                        return 0;
@@ -222,7 +222,8 @@
        if(boid)
                PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
 
-       return 1;
+       /* return flag 1+1=2 for newly born particles to copy exact birth 
location to previously cached frame */
+       return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= 
pa->time);
 }
 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, 
float time)
 {
@@ -249,6 +250,10 @@
 
        BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
 
+       /* set frames cached before birth to birth time */
+       if(cfra < pa->time)
+               pa->state.time = pa->time;
+
        if(data[BPHYS_DATA_SIZE])
                PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
        
@@ -1148,6 +1153,9 @@
        } else if (mode==PTCACHE_FILE_WRITE) {
                BLI_make_existing_file(filename); /* will create the dir if 
needs be, same as //textures is created */
                fp = fopen(filename, "wb");
+       } else if (mode==PTCACHE_FILE_UPDATE) {
+               BLI_make_existing_file(filename);
+               fp = fopen(filename, "rb+");
        }
 
        if (!fp)
@@ -1253,6 +1261,18 @@
        pf->cur[BPHYS_DATA_BOIDS] =             data_types & 
(1<<BPHYS_DATA_BOIDS) ?            &pf->data.boids : NULL;
 }
 
+static void ptcache_file_seek_pointers(int index, PTCacheFile *pf)
+{
+       int i, size=0;
+       int data_types = pf->data_types;
+
+       for(i=0; i<BPHYS_TOT_DATA; i++)
+               size += pf->data_types & (1<<i) ? ptcache_data_size[i] : 0;
+
+       ptcache_file_init_pointers(pf);
+       /* size of default header + data up to index */
+       fseek(pf->fp, 8 + 3*sizeof(int) + index * size, SEEK_SET);
+}
 void BKE_ptcache_mem_init_pointers(PTCacheMem *pm)
 {
        int data_types = pm->data_types;
@@ -1271,6 +1291,14 @@
                        pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i];
        }
 }
+void BKE_ptcache_mem_seek_pointers(int index, PTCacheMem *pm)
+{
+       int data_types = pm->data_types;
+       int i;
+
+       for(i=0; i<BPHYS_TOT_DATA; i++)
+               pm->cur[i] = data_types & (1<<i) ? (char*)pm->data[i] + index * 
ptcache_data_size[i] : NULL;
+}
 static void ptcache_alloc_data(PTCacheMem *pm)
 {
        int data_types = pm->data_types;
@@ -1453,7 +1481,7 @@
                        else if(pid->read_header(pf2)) {
                                ptcache_file_init_pointers(pf2);
                                totpoint2 = pf2->totpoint;
-                               index2 = pf->data_types & BPHYS_DATA_INDEX ? 
&pf2->data.index : &i;
+                               index2 = pf2->data_types & BPHYS_DATA_INDEX ? 
&pf2->data.index : &i;
                        }
                }
                else {
@@ -1615,7 +1643,7 @@
 int BKE_ptcache_write_cache(PTCacheID *pid, int cfra)
 {
        PointCache *cache = pid->cache;
-       PTCacheFile *pf= NULL;
+       PTCacheFile *pf= NULL, *pf2= NULL;
        int i;
        int totpoint = pid->totpoint(pid->calldata);
        int add = 0, overwrite = 0;
@@ -1625,7 +1653,7 @@
                return 0;
 
        if(cache->flag & PTCACHE_DISK_CACHE) {
-               int efra = cache->endframe;
+               int ofra, efra = cache->endframe;
 
                if(cfra==0)
                        add = 1;
@@ -1636,7 +1664,6 @@
                        add = 1;
                }
                else {
-                       int ofra;
                        /* find last cached frame */
                        while(efra > cache->startframe && 
!BKE_ptcache_id_exist(pid, efra))
                                efra--;
@@ -1679,11 +1706,36 @@
                        }
                        else
                                for(i=0; i<totpoint; i++) {
-                                       if(pid->write_elem && 
pid->write_elem(i, pid->calldata, pf->cur))
-                                               
if(!ptcache_file_write_data(pf)) {
-                                                       ptcache_file_close(pf);
-                                                       return 0;
+                                       if(pid->write_elem) {
+                                               int write = pid->write_elem(i, 
pid->calldata, pf->cur);
+                                               if(write) {
+                                                       
if(!ptcache_file_write_data(pf)) {
+                                                               
ptcache_file_close(pf);
+                                                               if(pf2) 
ptcache_file_close(pf2);
+                                                               return 0;
+                                                       }
+                                                       /* newly born particles 
have to be copied to previous cached frame */
+                                                       else if(overwrite && 
write == 2) {
+                                                               if(!pf2) {
+                                                                       pf2 = 
ptcache_file_open(pid, PTCACHE_FILE_UPDATE, ofra);
+                                                                       
if(!pf2) {
+                                                                               
ptcache_file_close(pf);
+                                                                               
return 0;
+                                                                       }
+                                                                       
pf2->type = pid->type;
+                                                                       
pf2->totpoint = totpoint;
+                                                                       
pf2->data_types = pid->data_types;
+                                                               }
+                                                               
ptcache_file_seek_pointers(i, pf2);
+                                                               
pid->write_elem(i, pid->calldata, pf2->cur);
+                                                               
if(!ptcache_file_write_data(pf2)) {
+                                                                       
ptcache_file_close(pf);
+                                                                       
ptcache_file_close(pf2);
+                                                                       return 
0;
+                                                               }
+                                                       }
                                                }
+                                       }
                                }
                }
        }
@@ -1728,8 +1780,19 @@
                        BKE_ptcache_mem_init_pointers(pm);
 
                        for(i=0; i<totpoint; i++) {
-                               if(pid->write_elem && pid->write_elem(i, 
pid->calldata, pm->cur))
-                                       BKE_ptcache_mem_incr_pointers(pm);
+                               if(pid->write_elem) {
+                                       int write = pid->write_elem(i, 
pid->calldata, pm->cur);
+                                       if(write) {
+                                               
BKE_ptcache_mem_incr_pointers(pm);
+
+                                               /* newly born particles have to 
be copied to previous cached frame */
+                                               if(overwrite && write == 2) {
+                                                       pm2 = 
cache->mem_cache.last;
+                                                       
BKE_ptcache_mem_seek_pointers(i, pm2);
+                                                       pid->write_elem(i, 
pid->calldata, pm2->cur);
+                                               }
+                                       }
+                               }
                        }
                        //ptcache_make_index_array(pm, 
pid->totpoint(pid->calldata));
 
@@ -1748,9 +1811,10 @@
                        cache->flag |= PTCACHE_FRAMES_SKIPPED;
        }
        
-       if(pf)
-               ptcache_file_close(pf);
+       if(pf) ptcache_file_close(pf);
 
+       if(pf2) ptcache_file_close(pf2);
+
        BKE_ptcache_update_info(pid);
 
        return 1;


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to