Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Campbell Barton <ideasman42@gmail.com> 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <stdlib.h> 00032 #include <stdio.h> 00033 #include <string.h> 00034 #include <sys/stat.h> 00035 #include <sys/types.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "DNA_ID.h" 00040 #include "DNA_cloth_types.h" 00041 #include "DNA_dynamicpaint_types.h" 00042 #include "DNA_modifier_types.h" 00043 #include "DNA_object_types.h" 00044 #include "DNA_object_force.h" 00045 #include "DNA_particle_types.h" 00046 #include "DNA_scene_types.h" 00047 #include "DNA_smoke_types.h" 00048 00049 #include "BLI_blenlib.h" 00050 #include "BLI_threads.h" 00051 #include "BLI_math.h" 00052 #include "BLI_utildefines.h" 00053 00054 #include "PIL_time.h" 00055 00056 #include "WM_api.h" 00057 00058 #include "BKE_anim.h" 00059 #include "BKE_blender.h" 00060 #include "BKE_cloth.h" 00061 #include "BKE_depsgraph.h" 00062 #include "BKE_dynamicpaint.h" 00063 #include "BKE_global.h" 00064 #include "BKE_library.h" 00065 #include "BKE_main.h" 00066 #include "BKE_object.h" 00067 #include "BKE_particle.h" 00068 #include "BKE_pointcache.h" 00069 #include "BKE_scene.h" 00070 #include "BKE_smoke.h" 00071 #include "BKE_softbody.h" 00072 #include "BKE_utildefines.h" 00073 00074 #include "BIK_api.h" 00075 00076 /* both in intern */ 00077 #include "smoke_API.h" 00078 00079 #ifdef WITH_LZO 00080 #include "minilzo.h" 00081 #else 00082 /* used for non-lzo cases */ 00083 #define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3) 00084 #endif 00085 00086 #ifdef WITH_LZMA 00087 #include "LzmaLib.h" 00088 #endif 00089 00090 /* needed for directory lookup */ 00091 /* untitled blend's need getpid for a unique name */ 00092 #ifndef WIN32 00093 #include <dirent.h> 00094 #include <unistd.h> 00095 #else 00096 #include <process.h> 00097 #include "BLI_winstuff.h" 00098 #endif 00099 00100 #define PTCACHE_DATA_FROM(data, type, from) if(data[type]) { memcpy(data[type], from, ptcache_data_size[type]); } 00101 #define PTCACHE_DATA_TO(data, type, index, to) if(data[type]) { memcpy(to, (char*)data[type] + (index ? index * ptcache_data_size[type] : 0), ptcache_data_size[type]); } 00102 00103 /* could be made into a pointcache option */ 00104 #define DURIAN_POINTCACHE_LIB_OK 1 00105 00106 static int ptcache_data_size[] = { 00107 sizeof(unsigned int), // BPHYS_DATA_INDEX 00108 3 * sizeof(float), // BPHYS_DATA_LOCATION 00109 3 * sizeof(float), // BPHYS_DATA_VELOCITY 00110 4 * sizeof(float), // BPHYS_DATA_ROTATION 00111 3 * sizeof(float), // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST 00112 sizeof(float), // BPHYS_DATA_SIZE 00113 3 * sizeof(float), // BPHYS_DATA_TIMES 00114 sizeof(BoidData) // case BPHYS_DATA_BOIDS 00115 }; 00116 00117 static int ptcache_extra_datasize[] = { 00118 0, 00119 sizeof(ParticleSpring) 00120 }; 00121 00122 /* forward declerations */ 00123 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len); 00124 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode); 00125 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size); 00126 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size); 00127 00128 /* Common functions */ 00129 static int ptcache_basic_header_read(PTCacheFile *pf) 00130 { 00131 int error=0; 00132 00133 /* Custom functions should read these basic elements too! */ 00134 if(!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) 00135 error = 1; 00136 00137 if(!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) 00138 error = 1; 00139 00140 return !error; 00141 } 00142 static int ptcache_basic_header_write(PTCacheFile *pf) 00143 { 00144 /* Custom functions should write these basic elements too! */ 00145 if(!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) 00146 return 0; 00147 00148 if(!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) 00149 return 0; 00150 00151 return 1; 00152 } 00153 /* Softbody functions */ 00154 static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra)) 00155 { 00156 SoftBody *soft= soft_v; 00157 BodyPoint *bp = soft->bpoint + index; 00158 00159 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos); 00160 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec); 00161 00162 return 1; 00163 } 00164 static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data) 00165 { 00166 SoftBody *soft= soft_v; 00167 BodyPoint *bp = soft->bpoint + index; 00168 00169 if(old_data) { 00170 memcpy(bp->pos, data, 3 * sizeof(float)); 00171 memcpy(bp->vec, data + 3, 3 * sizeof(float)); 00172 } 00173 else { 00174 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos); 00175 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec); 00176 } 00177 } 00178 static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) 00179 { 00180 SoftBody *soft= soft_v; 00181 BodyPoint *bp = soft->bpoint + index; 00182 ParticleKey keys[4]; 00183 float dfra; 00184 00185 if(cfra1 == cfra2) 00186 return; 00187 00188 copy_v3_v3(keys[1].co, bp->pos); 00189 copy_v3_v3(keys[1].vel, bp->vec); 00190 00191 if(old_data) { 00192 memcpy(keys[2].co, old_data, 3 * sizeof(float)); 00193 memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float)); 00194 } 00195 else 00196 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); 00197 00198 dfra = cfra2 - cfra1; 00199 00200 mul_v3_fl(keys[1].vel, dfra); 00201 mul_v3_fl(keys[2].vel, dfra); 00202 00203 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); 00204 00205 mul_v3_fl(keys->vel, 1.0f / dfra); 00206 00207 copy_v3_v3(bp->pos, keys->co); 00208 copy_v3_v3(bp->vec, keys->vel); 00209 } 00210 static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra)) 00211 { 00212 SoftBody *soft= soft_v; 00213 return soft->totpoint; 00214 } 00215 /* Particle functions */ 00216 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) 00217 { 00218 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co); 00219 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel); 00220 00221 /* no rotation info, so make something nice up */ 00222 if(data[BPHYS_DATA_ROTATION]==NULL) { 00223 vec_to_quat( key->rot, key->vel, OB_NEGX, OB_POSZ); 00224 } 00225 else { 00226 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot); 00227 } 00228 00229 PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave); 00230 key->time = time; 00231 } 00232 static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra) 00233 { 00234 ParticleSystem *psys= psys_v; 00235 ParticleData *pa = psys->particles + index; 00236 BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; 00237 float times[3]; 00238 int step = psys->pointcache->step; 00239 00240 /* No need to store unborn or died particles outside cache step bounds */ 00241 if(data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step)) 00242 return 0; 00243 00244 times[0]= pa->time; 00245 times[1]= pa->dietime; 00246 times[2]= pa->lifetime; 00247 00248 PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); 00249 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); 00250 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); 00251 PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot); 00252 PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave); 00253 PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size); 00254 PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times); 00255 00256 if(boid) 00257 PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); 00258 00259 /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */ 00260 return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time); 00261 } 00262 static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data) 00263 { 00264 ParticleSystem *psys= psys_v; 00265 ParticleData *pa; 00266 BoidParticle *boid; 00267 float timestep = 0.04f*psys->part->timetweak; 00268 00269 if(index >= psys->totpart) 00270 return; 00271 00272 pa = psys->particles + index; 00273 boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; 00274 00275 if(cfra > pa->state.time) 00276 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey)); 00277 00278 if(old_data){ 00279 /* old format cache */ 00280 memcpy(&pa->state, old_data, sizeof(ParticleKey)); 00281 return; 00282 } 00283 00284 BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); 00285 00286 /* set frames cached before birth to birth time */ 00287 if(cfra < pa->time) 00288 pa->state.time = pa->time; 00289 else if(cfra > pa->dietime) 00290 pa->state.time = pa->dietime; 00291 00292 if(data[BPHYS_DATA_SIZE]) 00293 PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); 00294 00295 if(data[BPHYS_DATA_TIMES]) { 00296 float times[3]; 00297 PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×); 00298 pa->time = times[0]; 00299 pa->dietime = times[1]; 00300 pa->lifetime = times[2]; 00301 } 00302 00303 if(boid) 00304 PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); 00305 00306 /* determine velocity from previous location */ 00307 if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { 00308 if(cfra > pa->prev_state.time) { 00309 sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co); 00310 mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep); 00311 } 00312 else { 00313 sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co); 00314 mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep); 00315 } 00316 } 00317 00318 /* determine rotation from velocity */ 00319 if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { 00320 vec_to_quat( pa->state.rot,pa->state.vel, OB_NEGX, OB_POSZ); 00321 } 00322 } 00323 static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) 00324 { 00325 ParticleSystem *psys= psys_v; 00326 ParticleData *pa; 00327 ParticleKey keys[4]; 00328 float dfra, timestep = 0.04f*psys->part->timetweak; 00329 00330 if(index >= psys->totpart) 00331 return; 00332 00333 pa = psys->particles + index; 00334 00335 /* particle wasn't read from first cache so can't interpolate */ 00336 if((int)cfra1 < pa->time - psys->pointcache->step || (int)cfra1 > pa->dietime + psys->pointcache->step) 00337 return; 00338 00339 cfra = MIN2(cfra, pa->dietime); 00340 cfra1 = MIN2(cfra1, pa->dietime); 00341 cfra2 = MIN2(cfra2, pa->dietime); 00342 00343 if(cfra1 == cfra2) 00344 return; 00345 00346 memcpy(keys+1, &pa->state, sizeof(ParticleKey)); 00347 if(old_data) 00348 memcpy(keys+2, old_data, sizeof(ParticleKey)); 00349 else 00350 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); 00351 00352 /* determine velocity from previous location */ 00353 if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { 00354 if(keys[1].time > keys[2].time) { 00355 sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co); 00356 mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep); 00357 } 00358 else { 00359 sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co); 00360 mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep); 00361 } 00362 } 00363 00364 /* determine rotation from velocity */ 00365 if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { 00366 vec_to_quat( keys[2].rot,keys[2].vel, OB_NEGX, OB_POSZ); 00367 } 00368 00369 if(cfra > pa->time) 00370 cfra1 = MAX2(cfra1, pa->time); 00371 00372 dfra = cfra2 - cfra1; 00373 00374 mul_v3_fl(keys[1].vel, dfra * timestep); 00375 mul_v3_fl(keys[2].vel, dfra * timestep); 00376 00377 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); 00378 interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); 00379 00380 mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep)); 00381 00382 pa->state.time = cfra; 00383 } 00384 00385 static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra)) 00386 { 00387 ParticleSystem *psys = psys_v; 00388 return psys->totpart; 00389 } 00390 static int ptcache_particle_totwrite(void *psys_v, int cfra) 00391 { 00392 ParticleSystem *psys = psys_v; 00393 ParticleData *pa= psys->particles; 00394 int p, step = psys->pointcache->step; 00395 int totwrite = 0; 00396 00397 if(cfra == 0) 00398 return psys->totpart; 00399 00400 for(p=0; p<psys->totpart; p++,pa++) 00401 totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step); 00402 00403 return totwrite; 00404 } 00405 00406 static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra)) 00407 { 00408 ParticleSystem *psys = psys_v; 00409 PTCacheExtra *extra = NULL; 00410 00411 if(psys->part->phystype == PART_PHYS_FLUID && 00412 psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS && 00413 psys->tot_fluidsprings && psys->fluid_springs) { 00414 00415 extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data"); 00416 00417 extra->type = BPHYS_EXTRA_FLUID_SPRINGS; 00418 extra->totdata = psys->tot_fluidsprings; 00419 00420 extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data"); 00421 memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]); 00422 00423 BLI_addtail(&pm->extradata, extra); 00424 } 00425 } 00426 00427 static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra)) 00428 { 00429 ParticleSystem *psys = psys_v; 00430 PTCacheExtra *extra = pm->extradata.first; 00431 00432 for(; extra; extra=extra->next) { 00433 switch(extra->type) { 00434 case BPHYS_EXTRA_FLUID_SPRINGS: 00435 { 00436 if(psys->fluid_springs) 00437 MEM_freeN(psys->fluid_springs); 00438 00439 psys->fluid_springs = MEM_dupallocN(extra->data); 00440 psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata; 00441 break; 00442 } 00443 } 00444 } 00445 } 00446 00447 /* Cloth functions */ 00448 static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra)) 00449 { 00450 ClothModifierData *clmd= cloth_v; 00451 Cloth *cloth= clmd->clothObject; 00452 ClothVertex *vert = cloth->verts + index; 00453 00454 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x); 00455 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v); 00456 PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst); 00457 00458 return 1; 00459 } 00460 static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data) 00461 { 00462 ClothModifierData *clmd= cloth_v; 00463 Cloth *cloth= clmd->clothObject; 00464 ClothVertex *vert = cloth->verts + index; 00465 00466 if(old_data) { 00467 memcpy(vert->x, data, 3 * sizeof(float)); 00468 memcpy(vert->xconst, data + 3, 3 * sizeof(float)); 00469 memcpy(vert->v, data + 6, 3 * sizeof(float)); 00470 } 00471 else { 00472 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x); 00473 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v); 00474 PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst); 00475 } 00476 } 00477 static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) 00478 { 00479 ClothModifierData *clmd= cloth_v; 00480 Cloth *cloth= clmd->clothObject; 00481 ClothVertex *vert = cloth->verts + index; 00482 ParticleKey keys[4]; 00483 float dfra; 00484 00485 if(cfra1 == cfra2) 00486 return; 00487 00488 copy_v3_v3(keys[1].co, vert->x); 00489 copy_v3_v3(keys[1].vel, vert->v); 00490 00491 if(old_data) { 00492 memcpy(keys[2].co, old_data, 3 * sizeof(float)); 00493 memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float)); 00494 } 00495 else 00496 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); 00497 00498 dfra = cfra2 - cfra1; 00499 00500 mul_v3_fl(keys[1].vel, dfra); 00501 mul_v3_fl(keys[2].vel, dfra); 00502 00503 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); 00504 00505 mul_v3_fl(keys->vel, 1.0f / dfra); 00506 00507 copy_v3_v3(vert->x, keys->co); 00508 copy_v3_v3(vert->v, keys->vel); 00509 00510 /* should vert->xconst be interpolated somehow too? - jahka */ 00511 } 00512 00513 static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) 00514 { 00515 ClothModifierData *clmd= cloth_v; 00516 return clmd->clothObject ? clmd->clothObject->numverts : 0; 00517 } 00518 00519 #ifdef WITH_SMOKE 00520 /* Smoke functions */ 00521 static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) 00522 { 00523 SmokeModifierData *smd= (SmokeModifierData *)smoke_v; 00524 SmokeDomainSettings *sds = smd->domain; 00525 00526 if(sds->fluid) { 00527 return sds->res[0]*sds->res[1]*sds->res[2]; 00528 } 00529 else 00530 return 0; 00531 } 00532 static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) 00533 { 00534 SmokeModifierData *smd= (SmokeModifierData *)smoke_v; 00535 SmokeDomainSettings *sds = smd->domain; 00536 int ret = 0; 00537 00538 if(sds->fluid) { 00539 size_t res = sds->res[0]*sds->res[1]*sds->res[2]; 00540 float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold; 00541 unsigned char *obstacles; 00542 unsigned int in_len = sizeof(float)*(unsigned int)res; 00543 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); 00544 //int mode = res >= 1000000 ? 2 : 1; 00545 int mode=1; // light 00546 if (sds->cache_comp == SM_CACHE_HEAVY) mode=2; // heavy 00547 00548 smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); 00549 00550 ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); 00551 ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode); 00552 ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len, out, mode); 00553 ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode); 00554 ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode); 00555 ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode); 00556 ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode); 00557 ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode); 00558 ptcache_file_compressed_write(pf, (unsigned char *)vxold, in_len, out, mode); 00559 ptcache_file_compressed_write(pf, (unsigned char *)vyold, in_len, out, mode); 00560 ptcache_file_compressed_write(pf, (unsigned char *)vzold, in_len, out, mode); 00561 ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); 00562 ptcache_file_write(pf, &dt, 1, sizeof(float)); 00563 ptcache_file_write(pf, &dx, 1, sizeof(float)); 00564 00565 MEM_freeN(out); 00566 00567 ret = 1; 00568 } 00569 00570 if(sds->wt) { 00571 int res_big_array[3]; 00572 int res_big; 00573 int res = sds->res[0]*sds->res[1]*sds->res[2]; 00574 float *dens, *densold, *tcu, *tcv, *tcw; 00575 unsigned int in_len = sizeof(float)*(unsigned int)res; 00576 unsigned int in_len_big; 00577 unsigned char *out; 00578 int mode; 00579 00580 smoke_turbulence_get_res(sds->wt, res_big_array); 00581 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; 00582 //mode = res_big >= 1000000 ? 2 : 1; 00583 mode = 1; // light 00584 if (sds->cache_high_comp == SM_CACHE_HEAVY) mode=2; // heavy 00585 00586 in_len_big = sizeof(float) * (unsigned int)res_big; 00587 00588 smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); 00589 00590 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer"); 00591 ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode); 00592 ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len_big, out, mode); 00593 MEM_freeN(out); 00594 00595 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer"); 00596 ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode); 00597 ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode); 00598 ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode); 00599 MEM_freeN(out); 00600 00601 ret = 1; 00602 } 00603 00604 return ret; 00605 } 00606 static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) 00607 { 00608 SmokeModifierData *smd= (SmokeModifierData *)smoke_v; 00609 SmokeDomainSettings *sds = smd->domain; 00610 00611 if(sds->fluid) { 00612 size_t res = sds->res[0]*sds->res[1]*sds->res[2]; 00613 float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold; 00614 unsigned char *obstacles; 00615 unsigned int out_len = (unsigned int)res * sizeof(float); 00616 00617 smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); 00618 00619 ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len); 00620 ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len); 00621 ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len); 00622 ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len); 00623 ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len); 00624 ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len); 00625 ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len); 00626 ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len); 00627 ptcache_file_compressed_read(pf, (unsigned char*)vxold, out_len); 00628 ptcache_file_compressed_read(pf, (unsigned char*)vyold, out_len); 00629 ptcache_file_compressed_read(pf, (unsigned char*)vzold, out_len); 00630 ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res); 00631 ptcache_file_read(pf, &dt, 1, sizeof(float)); 00632 ptcache_file_read(pf, &dx, 1, sizeof(float)); 00633 00634 if(pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) { 00635 int res = sds->res[0]*sds->res[1]*sds->res[2]; 00636 int res_big, res_big_array[3]; 00637 float *dens, *densold, *tcu, *tcv, *tcw; 00638 unsigned int out_len = sizeof(float)*(unsigned int)res; 00639 unsigned int out_len_big; 00640 00641 smoke_turbulence_get_res(sds->wt, res_big_array); 00642 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; 00643 out_len_big = sizeof(float) * (unsigned int)res_big; 00644 00645 smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); 00646 00647 ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big); 00648 ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len_big); 00649 00650 ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len); 00651 ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len); 00652 ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len); 00653 } 00654 } 00655 00656 return 1; 00657 } 00658 #else // WITH_SMOKE 00659 static int ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; } 00660 static int ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; } 00661 static int ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; } 00662 #endif // WITH_SMOKE 00663 00664 static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra)) 00665 { 00666 DynamicPaintSurface *surface = (DynamicPaintSurface*)sd; 00667 00668 if (!surface->data) return 0; 00669 else return surface->data->total_points; 00670 } 00671 00672 #define DPAINT_CACHE_VERSION "1.01" 00673 00674 static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v) 00675 { 00676 DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v; 00677 int cache_compress = 1; 00678 00679 /* version header */ 00680 ptcache_file_write(pf, DPAINT_CACHE_VERSION, 1, sizeof(char)*4); 00681 00682 if(surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) { 00683 int total_points=surface->data->total_points; 00684 unsigned int in_len; 00685 unsigned char *out; 00686 00687 /* cache type */ 00688 ptcache_file_write(pf, &surface->type, 1, sizeof(int)); 00689 00690 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) 00691 in_len = sizeof(PaintPoint)*total_points; 00692 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || 00693 surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) 00694 in_len = sizeof(float)*total_points; 00695 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) 00696 in_len = sizeof(PaintWavePoint)*total_points; 00697 else return 0; 00698 00699 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer"); 00700 00701 ptcache_file_compressed_write(pf, (unsigned char *)surface->data->type_data, in_len, out, cache_compress); 00702 MEM_freeN(out); 00703 00704 } 00705 return 1; 00706 } 00707 static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v) 00708 { 00709 DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v; 00710 char version[4]; 00711 00712 /* version header */ 00713 ptcache_file_read(pf, version, 1, sizeof(char)*4); 00714 if (strncmp(version, DPAINT_CACHE_VERSION,4)) {printf("Dynamic Paint: Invalid cache version: %s!\n",version); return 0;} 00715 00716 if(surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) { 00717 unsigned int data_len; 00718 int surface_type; 00719 00720 /* cache type */ 00721 ptcache_file_read(pf, &surface_type, 1, sizeof(int)); 00722 00723 if (surface_type != surface->type) 00724 return 0; 00725 00726 /* read surface data */ 00727 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) 00728 data_len = sizeof(PaintPoint); 00729 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || 00730 surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) 00731 data_len = sizeof(float); 00732 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) 00733 data_len = sizeof(PaintWavePoint); 00734 else return 0; 00735 00736 ptcache_file_compressed_read(pf, (unsigned char*)surface->data->type_data, data_len*surface->data->total_points); 00737 00738 } 00739 return 1; 00740 } 00741 00742 /* Creating ID's */ 00743 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) 00744 { 00745 memset(pid, 0, sizeof(PTCacheID)); 00746 00747 pid->ob= ob; 00748 pid->calldata= sb; 00749 pid->type= PTCACHE_TYPE_SOFTBODY; 00750 pid->cache= sb->pointcache; 00751 pid->cache_ptr= &sb->pointcache; 00752 pid->ptcaches= &sb->ptcaches; 00753 pid->totpoint= pid->totwrite= ptcache_softbody_totpoint; 00754 00755 pid->write_point = ptcache_softbody_write; 00756 pid->read_point = ptcache_softbody_read; 00757 pid->interpolate_point = ptcache_softbody_interpolate; 00758 00759 pid->write_stream = NULL; 00760 pid->read_stream = NULL; 00761 00762 pid->write_extra_data = NULL; 00763 pid->read_extra_data = NULL; 00764 pid->interpolate_extra_data = NULL; 00765 00766 pid->write_header = ptcache_basic_header_write; 00767 pid->read_header = ptcache_basic_header_read; 00768 00769 pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); 00770 pid->info_types= 0; 00771 00772 pid->stack_index = pid->cache->index; 00773 00774 pid->default_step = 10; 00775 pid->max_step = 20; 00776 } 00777 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) 00778 { 00779 memset(pid, 0, sizeof(PTCacheID)); 00780 00781 pid->ob= ob; 00782 pid->calldata= psys; 00783 pid->type= PTCACHE_TYPE_PARTICLES; 00784 pid->stack_index= psys->pointcache->index; 00785 pid->cache= psys->pointcache; 00786 pid->cache_ptr= &psys->pointcache; 00787 pid->ptcaches= &psys->ptcaches; 00788 00789 if(psys->part->type != PART_HAIR) 00790 pid->flag |= PTCACHE_VEL_PER_SEC; 00791 00792 pid->totpoint = ptcache_particle_totpoint; 00793 pid->totwrite = ptcache_particle_totwrite; 00794 00795 pid->write_point = ptcache_particle_write; 00796 pid->read_point = ptcache_particle_read; 00797 pid->interpolate_point = ptcache_particle_interpolate; 00798 00799 pid->write_stream = NULL; 00800 pid->read_stream = NULL; 00801 00802 pid->write_extra_data = NULL; 00803 pid->read_extra_data = NULL; 00804 pid->interpolate_extra_data = NULL; 00805 00806 pid->write_header = ptcache_basic_header_write; 00807 pid->read_header = ptcache_basic_header_read; 00808 00809 pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX); 00810 00811 if(psys->part->phystype == PART_PHYS_BOIDS) 00812 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS); 00813 else if(psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) { 00814 pid->write_extra_data = ptcache_particle_extra_write; 00815 pid->read_extra_data = ptcache_particle_extra_read; 00816 } 00817 00818 if(psys->part->rotmode!=PART_ROT_VEL 00819 || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) 00820 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION); 00821 00822 if(psys->part->flag & PART_ROT_DYN) 00823 pid->data_types|= (1<<BPHYS_DATA_ROTATION); 00824 00825 pid->info_types= (1<<BPHYS_DATA_TIMES); 00826 00827 pid->default_step = 10; 00828 pid->max_step = 20; 00829 } 00830 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd) 00831 { 00832 memset(pid, 0, sizeof(PTCacheID)); 00833 00834 pid->ob= ob; 00835 pid->calldata= clmd; 00836 pid->type= PTCACHE_TYPE_CLOTH; 00837 pid->stack_index= clmd->point_cache->index; 00838 pid->cache= clmd->point_cache; 00839 pid->cache_ptr= &clmd->point_cache; 00840 pid->ptcaches= &clmd->ptcaches; 00841 pid->totpoint= pid->totwrite= ptcache_cloth_totpoint; 00842 00843 pid->write_point = ptcache_cloth_write; 00844 pid->read_point = ptcache_cloth_read; 00845 pid->interpolate_point = ptcache_cloth_interpolate; 00846 00847 pid->write_stream = NULL; 00848 pid->read_stream = NULL; 00849 00850 pid->write_extra_data = NULL; 00851 pid->read_extra_data = NULL; 00852 pid->interpolate_extra_data = NULL; 00853 00854 pid->write_header = ptcache_basic_header_write; 00855 pid->read_header = ptcache_basic_header_read; 00856 00857 pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST); 00858 pid->info_types= 0; 00859 00860 pid->default_step = 1; 00861 pid->max_step = 1; 00862 } 00863 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) 00864 { 00865 SmokeDomainSettings *sds = smd->domain; 00866 00867 memset(pid, 0, sizeof(PTCacheID)); 00868 00869 pid->ob= ob; 00870 pid->calldata= smd; 00871 00872 pid->type= PTCACHE_TYPE_SMOKE_DOMAIN; 00873 pid->stack_index= sds->point_cache[0]->index; 00874 00875 pid->cache= sds->point_cache[0]; 00876 pid->cache_ptr= &(sds->point_cache[0]); 00877 pid->ptcaches= &(sds->ptcaches[0]); 00878 00879 pid->totpoint= pid->totwrite= ptcache_smoke_totpoint; 00880 00881 pid->write_point = NULL; 00882 pid->read_point = NULL; 00883 pid->interpolate_point = NULL; 00884 00885 pid->read_stream = ptcache_smoke_read; 00886 pid->write_stream = ptcache_smoke_write; 00887 00888 pid->write_extra_data = NULL; 00889 pid->read_extra_data = NULL; 00890 pid->interpolate_extra_data = NULL; 00891 00892 pid->write_header = ptcache_basic_header_write; 00893 pid->read_header = ptcache_basic_header_read; 00894 00895 pid->data_types= 0; 00896 pid->info_types= 0; 00897 00898 if(sds->fluid) 00899 pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW); 00900 if(sds->wt) 00901 pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH); 00902 00903 pid->default_step = 1; 00904 pid->max_step = 1; 00905 } 00906 00907 void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface) 00908 { 00909 00910 memset(pid, 0, sizeof(PTCacheID)); 00911 00912 pid->ob= ob; 00913 pid->calldata= surface; 00914 pid->type= PTCACHE_TYPE_DYNAMICPAINT; 00915 pid->cache= surface->pointcache; 00916 pid->cache_ptr= &surface->pointcache; 00917 pid->ptcaches= &surface->ptcaches; 00918 pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint; 00919 00920 pid->write_point = NULL; 00921 pid->read_point = NULL; 00922 pid->interpolate_point = NULL; 00923 00924 pid->write_stream = ptcache_dynamicpaint_write; 00925 pid->read_stream = ptcache_dynamicpaint_read; 00926 00927 pid->write_extra_data = NULL; 00928 pid->read_extra_data = NULL; 00929 pid->interpolate_extra_data = NULL; 00930 00931 pid->write_header = ptcache_basic_header_write; 00932 pid->read_header = ptcache_basic_header_read; 00933 00934 pid->data_types= BPHYS_DATA_DYNAMICPAINT; 00935 pid->info_types= 0; 00936 00937 pid->stack_index = pid->cache->index; 00938 00939 pid->default_step = 1; 00940 pid->max_step = 1; 00941 } 00942 00943 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) 00944 { 00945 PTCacheID *pid; 00946 ParticleSystem *psys; 00947 ModifierData *md; 00948 00949 lb->first= lb->last= NULL; 00950 00951 if(ob->soft) { 00952 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 00953 BKE_ptcache_id_from_softbody(pid, ob, ob->soft); 00954 BLI_addtail(lb, pid); 00955 } 00956 00957 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 00958 if(psys->part==NULL) 00959 continue; 00960 00961 /* check to make sure point cache is actually used by the particles */ 00962 if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) 00963 continue; 00964 00965 /* hair needs to be included in id-list for cache edit mode to work */ 00966 /* if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */ 00967 /* continue; */ 00968 00969 if(psys->part->type == PART_FLUID) 00970 continue; 00971 00972 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 00973 BKE_ptcache_id_from_particles(pid, ob, psys); 00974 BLI_addtail(lb, pid); 00975 } 00976 00977 for(md=ob->modifiers.first; md; md=md->next) { 00978 if(md->type == eModifierType_Cloth) { 00979 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 00980 BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md); 00981 BLI_addtail(lb, pid); 00982 } 00983 else if(md->type == eModifierType_Smoke) { 00984 SmokeModifierData *smd = (SmokeModifierData *)md; 00985 if(smd->type & MOD_SMOKE_TYPE_DOMAIN) 00986 { 00987 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 00988 BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md); 00989 BLI_addtail(lb, pid); 00990 } 00991 } 00992 else if(md->type == eModifierType_DynamicPaint) { 00993 DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; 00994 if(pmd->canvas) 00995 { 00996 DynamicPaintSurface *surface = pmd->canvas->surfaces.first; 00997 00998 for (; surface; surface=surface->next) { 00999 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 01000 BKE_ptcache_id_from_dynamicpaint(pid, ob, surface); 01001 BLI_addtail(lb, pid); 01002 } 01003 } 01004 } 01005 } 01006 01007 if(scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) { 01008 ListBase *lb_dupli_ob; 01009 01010 if((lb_dupli_ob=object_duplilist(scene, ob))) { 01011 DupliObject *dob; 01012 for(dob= lb_dupli_ob->first; dob; dob= dob->next) { 01013 if(dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */ 01014 ListBase lb_dupli_pid; 01015 BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis); 01016 BLI_movelisttolist(lb, &lb_dupli_pid); 01017 if(lb_dupli_pid.first) 01018 printf("Adding Dupli\n"); 01019 } 01020 } 01021 01022 free_object_duplilist(lb_dupli_ob); /* does restore */ 01023 } 01024 } 01025 } 01026 01027 /* File handling */ 01028 01029 /* Takes an Object ID and returns a unique name 01030 - id: object id 01031 - cfra: frame for the cache, can be negative 01032 - stack_index: index in the modifier stack. we can have cache for more then one stack_index 01033 */ 01034 01035 #define MAX_PTCACHE_PATH FILE_MAX 01036 #define MAX_PTCACHE_FILE ((FILE_MAX)*2) 01037 01038 static int ptcache_path(PTCacheID *pid, char *filename) 01039 { 01040 Library *lib= (pid->ob)? pid->ob->id.lib: NULL; 01041 const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name; 01042 size_t i; 01043 01044 if(pid->cache->flag & PTCACHE_EXTERNAL) { 01045 strcpy(filename, pid->cache->path); 01046 01047 if(strncmp(filename, "//", 2)==0) 01048 BLI_path_abs(filename, blendfilename); 01049 01050 return BLI_add_slash(filename); /* new strlen() */ 01051 } 01052 else if (G.relbase_valid || lib) { 01053 char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */ 01054 01055 BLI_split_file_part(blendfilename, file, sizeof(file)); 01056 i = strlen(file); 01057 01058 /* remove .blend */ 01059 if (i > 6) 01060 file[i-6] = '\0'; 01061 01062 BLI_snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */ 01063 BLI_path_abs(filename, blendfilename); 01064 return BLI_add_slash(filename); /* new strlen() */ 01065 } 01066 01067 /* use the temp path. this is weak but better then not using point cache at all */ 01068 /* temporary directory is assumed to exist and ALWAYS has a trailing slash */ 01069 BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", BLI_temporary_dir(), abs(getpid())); 01070 01071 return BLI_add_slash(filename); /* new strlen() */ 01072 } 01073 01074 static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext) 01075 { 01076 int len=0; 01077 char *idname; 01078 char *newname; 01079 filename[0] = '\0'; 01080 newname = filename; 01081 01082 if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */ 01083 01084 /* start with temp dir */ 01085 if (do_path) { 01086 len = ptcache_path(pid, filename); 01087 newname += len; 01088 } 01089 if(pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) { 01090 idname = (pid->ob->id.name+2); 01091 /* convert chars to hex so they are always a valid filename */ 01092 while('\0' != *idname) { 01093 BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++)); 01094 newname+=2; 01095 len += 2; 01096 } 01097 } 01098 else { 01099 int temp = (int)strlen(pid->cache->name); 01100 strcpy(newname, pid->cache->name); 01101 newname+=temp; 01102 len += temp; 01103 } 01104 01105 if (do_ext) { 01106 01107 if(pid->cache->index < 0) 01108 pid->cache->index = pid->stack_index = object_insert_ptcache(pid->ob); 01109 01110 if(pid->cache->flag & PTCACHE_EXTERNAL) { 01111 if(pid->cache->index >= 0) 01112 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */ 01113 else 01114 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */ 01115 } 01116 else { 01117 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */ 01118 } 01119 len += 16; 01120 } 01121 01122 return len; /* make sure the above string is always 16 chars */ 01123 } 01124 01125 /* youll need to close yourself after! */ 01126 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) 01127 { 01128 PTCacheFile *pf; 01129 FILE *fp = NULL; 01130 char filename[(FILE_MAX)*2]; 01131 01132 #ifndef DURIAN_POINTCACHE_LIB_OK 01133 /* don't allow writing for linked objects */ 01134 if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE) 01135 return NULL; 01136 #endif 01137 if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */ 01138 01139 ptcache_filename(pid, filename, cfra, 1, 1); 01140 01141 if (mode==PTCACHE_FILE_READ) { 01142 if (!BLI_exists(filename)) { 01143 return NULL; 01144 } 01145 fp = fopen(filename, "rb"); 01146 } else if (mode==PTCACHE_FILE_WRITE) { 01147 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */ 01148 fp = fopen(filename, "wb"); 01149 } else if (mode==PTCACHE_FILE_UPDATE) { 01150 BLI_make_existing_file(filename); 01151 fp = fopen(filename, "rb+"); 01152 } 01153 01154 if (!fp) 01155 return NULL; 01156 01157 pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile"); 01158 pf->fp= fp; 01159 pf->old_format = 0; 01160 pf->frame = cfra; 01161 01162 return pf; 01163 } 01164 static void ptcache_file_close(PTCacheFile *pf) 01165 { 01166 if(pf) { 01167 fclose(pf->fp); 01168 MEM_freeN(pf); 01169 } 01170 } 01171 01172 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len) 01173 { 01174 int r = 0; 01175 unsigned char compressed = 0; 01176 size_t in_len; 01177 #ifdef WITH_LZO 01178 size_t out_len = len; 01179 #endif 01180 unsigned char *in; 01181 unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); 01182 01183 ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); 01184 if(compressed) { 01185 unsigned int size; 01186 ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); 01187 in_len = (size_t)size; 01188 if(in_len==0) { 01189 /* do nothing */ 01190 } 01191 else { 01192 in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); 01193 ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); 01194 #ifdef WITH_LZO 01195 if(compressed == 1) 01196 r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); 01197 #endif 01198 #ifdef WITH_LZMA 01199 if(compressed == 2) 01200 { 01201 size_t sizeOfIt; 01202 size_t leni = in_len, leno = out_len; 01203 ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); 01204 sizeOfIt = (size_t)size; 01205 ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); 01206 r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); 01207 } 01208 #endif 01209 MEM_freeN(in); 01210 } 01211 } 01212 else { 01213 ptcache_file_read(pf, result, len, sizeof(unsigned char)); 01214 } 01215 01216 MEM_freeN(props); 01217 01218 return r; 01219 } 01220 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) 01221 { 01222 int r = 0; 01223 unsigned char compressed = 0; 01224 size_t out_len= 0; 01225 unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); 01226 size_t sizeOfIt = 5; 01227 01228 (void)mode; /* unused when building w/o compression */ 01229 01230 #ifdef WITH_LZO 01231 out_len= LZO_OUT_LEN(in_len); 01232 if(mode == 1) { 01233 LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); 01234 01235 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); 01236 if (!(r == LZO_E_OK) || (out_len >= in_len)) 01237 compressed = 0; 01238 else 01239 compressed = 1; 01240 } 01241 #endif 01242 #ifdef WITH_LZMA 01243 if(mode == 2) { 01244 01245 r = LzmaCompress(out, &out_len, in, in_len,//assume sizeof(char)==1.... 01246 props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); 01247 01248 if(!(r == SZ_OK) || (out_len >= in_len)) 01249 compressed = 0; 01250 else 01251 compressed = 2; 01252 } 01253 #endif 01254 01255 ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); 01256 if(compressed) { 01257 unsigned int size = out_len; 01258 ptcache_file_write(pf, &size, 1, sizeof(unsigned int)); 01259 ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); 01260 } 01261 else 01262 ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); 01263 01264 if(compressed == 2) 01265 { 01266 unsigned int size = sizeOfIt; 01267 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int)); 01268 ptcache_file_write(pf, props, size, sizeof(unsigned char)); 01269 } 01270 01271 MEM_freeN(props); 01272 01273 return r; 01274 } 01275 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size) 01276 { 01277 return (fread(f, size, tot, pf->fp) == tot); 01278 } 01279 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size) 01280 { 01281 return (fwrite(f, size, tot, pf->fp) == tot); 01282 } 01283 static int ptcache_file_data_read(PTCacheFile *pf) 01284 { 01285 int i; 01286 01287 for(i=0; i<BPHYS_TOT_DATA; i++) { 01288 if((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) 01289 return 0; 01290 } 01291 01292 return 1; 01293 } 01294 static int ptcache_file_data_write(PTCacheFile *pf) 01295 { 01296 int i; 01297 01298 for(i=0; i<BPHYS_TOT_DATA; i++) { 01299 if((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) 01300 return 0; 01301 } 01302 01303 return 1; 01304 } 01305 static int ptcache_file_header_begin_read(PTCacheFile *pf) 01306 { 01307 unsigned int typeflag=0; 01308 int error=0; 01309 char bphysics[8]; 01310 01311 pf->data_types = 0; 01312 01313 if(fread(bphysics, sizeof(char), 8, pf->fp) != 8) 01314 error = 1; 01315 01316 if(!error && strncmp(bphysics, "BPHYSICS", 8)) 01317 error = 1; 01318 01319 if(!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp)) 01320 error = 1; 01321 01322 pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK); 01323 pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK); 01324 01325 /* if there was an error set file as it was */ 01326 if(error) 01327 fseek(pf->fp, 0, SEEK_SET); 01328 01329 return !error; 01330 } 01331 static int ptcache_file_header_begin_write(PTCacheFile *pf) 01332 { 01333 const char *bphysics = "BPHYSICS"; 01334 unsigned int typeflag = pf->type + pf->flag; 01335 01336 if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) 01337 return 0; 01338 01339 if(!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp)) 01340 return 0; 01341 01342 return 1; 01343 } 01344 01345 /* Data pointer handling */ 01346 int BKE_ptcache_data_size(int data_type) 01347 { 01348 return ptcache_data_size[data_type]; 01349 } 01350 01351 static void ptcache_file_pointers_init(PTCacheFile *pf) 01352 { 01353 int data_types = pf->data_types; 01354 01355 pf->cur[BPHYS_DATA_INDEX] = (data_types & (1<<BPHYS_DATA_INDEX)) ? &pf->data.index : NULL; 01356 pf->cur[BPHYS_DATA_LOCATION] = (data_types & (1<<BPHYS_DATA_LOCATION)) ? &pf->data.loc : NULL; 01357 pf->cur[BPHYS_DATA_VELOCITY] = (data_types & (1<<BPHYS_DATA_VELOCITY)) ? &pf->data.vel : NULL; 01358 pf->cur[BPHYS_DATA_ROTATION] = (data_types & (1<<BPHYS_DATA_ROTATION)) ? &pf->data.rot : NULL; 01359 pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))? &pf->data.ave : NULL; 01360 pf->cur[BPHYS_DATA_SIZE] = (data_types & (1<<BPHYS_DATA_SIZE)) ? &pf->data.size : NULL; 01361 pf->cur[BPHYS_DATA_TIMES] = (data_types & (1<<BPHYS_DATA_TIMES)) ? &pf->data.times : NULL; 01362 pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1<<BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL; 01363 } 01364 01365 /* Check to see if point number "index" is in pm, uses binary search for index data. */ 01366 int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index) 01367 { 01368 if(pm->data[BPHYS_DATA_INDEX]) { 01369 unsigned int *data = pm->data[BPHYS_DATA_INDEX]; 01370 unsigned int mid, low = 0, high = pm->totpoint - 1; 01371 01372 if(index < *data || index > *(data+high)) 01373 return -1; 01374 01375 /* check simple case for continuous indexes first */ 01376 if(index-*data < high && data[index-*data] == index) 01377 return index-*data; 01378 01379 while(low <= high) { 01380 mid= (low + high)/2; 01381 01382 if(data[mid] > index) 01383 high = mid - 1; 01384 else if(data[mid] < index) 01385 low = mid + 1; 01386 else 01387 return mid; 01388 } 01389 01390 return -1; 01391 } 01392 else { 01393 return (index < pm->totpoint ? index : -1); 01394 } 01395 } 01396 01397 void BKE_ptcache_mem_pointers_init(PTCacheMem *pm) 01398 { 01399 int data_types = pm->data_types; 01400 int i; 01401 01402 for(i=0; i<BPHYS_TOT_DATA; i++) 01403 pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL); 01404 } 01405 01406 void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm) 01407 { 01408 int i; 01409 01410 for(i=0; i<BPHYS_TOT_DATA; i++) { 01411 if(pm->cur[i]) 01412 pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; 01413 } 01414 } 01415 int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm) 01416 { 01417 int data_types = pm->data_types; 01418 int i, index = BKE_ptcache_mem_index_find(pm, point_index); 01419 01420 if(index < 0) { 01421 /* Can't give proper location without reallocation, so don't give any location. 01422 * Some points will be cached improperly, but this only happens with simulation 01423 * steps bigger than cache->step, so the cache has to be recalculated anyways 01424 * at some point. 01425 */ 01426 return 0; 01427 } 01428 01429 for(i=0; i<BPHYS_TOT_DATA; i++) 01430 pm->cur[i] = data_types & (1<<i) ? (char*)pm->data[i] + index * ptcache_data_size[i] : NULL; 01431 01432 return 1; 01433 } 01434 static void ptcache_data_alloc(PTCacheMem *pm) 01435 { 01436 int data_types = pm->data_types; 01437 int totpoint = pm->totpoint; 01438 int i; 01439 01440 for(i=0; i<BPHYS_TOT_DATA; i++) { 01441 if(data_types & (1<<i)) 01442 pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data"); 01443 } 01444 } 01445 static void ptcache_data_free(PTCacheMem *pm) 01446 { 01447 void **data = pm->data; 01448 int i; 01449 01450 for(i=0; i<BPHYS_TOT_DATA; i++) { 01451 if(data[i]) 01452 MEM_freeN(data[i]); 01453 } 01454 } 01455 static void ptcache_data_copy(void *from[], void *to[]) 01456 { 01457 int i; 01458 for(i=0; i<BPHYS_TOT_DATA; i++) { 01459 /* note, durian file 03.4b_comp crashes if to[i] is not tested 01460 * its NULL, not sure if this should be fixed elsewhere but for now its needed */ 01461 if(from[i] && to[i]) 01462 memcpy(to[i], from[i], ptcache_data_size[i]); 01463 } 01464 } 01465 01466 static void ptcache_extra_free(PTCacheMem *pm) 01467 { 01468 PTCacheExtra *extra = pm->extradata.first; 01469 01470 if(extra) { 01471 for(; extra; extra=extra->next) { 01472 if(extra->data) 01473 MEM_freeN(extra->data); 01474 } 01475 01476 BLI_freelistN(&pm->extradata); 01477 } 01478 } 01479 static int ptcache_old_elemsize(PTCacheID *pid) 01480 { 01481 if(pid->type==PTCACHE_TYPE_SOFTBODY) 01482 return 6 * sizeof(float); 01483 else if(pid->type==PTCACHE_TYPE_PARTICLES) 01484 return sizeof(ParticleKey); 01485 else if(pid->type==PTCACHE_TYPE_CLOTH) 01486 return 9 * sizeof(float); 01487 01488 return 0; 01489 } 01490 01491 static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2) 01492 { 01493 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01494 int cfra1=frame, cfra2=frame+1; 01495 01496 while(cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) 01497 cfra1--; 01498 01499 if(cfra1 < pid->cache->startframe) 01500 cfra1 = 0; 01501 01502 while(cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) 01503 cfra2++; 01504 01505 if(cfra2 > pid->cache->endframe) 01506 cfra2 = 0; 01507 01508 if(cfra1 && !cfra2) { 01509 *fra1 = 0; 01510 *fra2 = cfra1; 01511 } 01512 else { 01513 *fra1 = cfra1; 01514 *fra2 = cfra2; 01515 } 01516 } 01517 else if(pid->cache->mem_cache.first) { 01518 PTCacheMem *pm = pid->cache->mem_cache.first; 01519 PTCacheMem *pm2 = pid->cache->mem_cache.last; 01520 01521 while(pm->next && pm->next->frame <= frame) 01522 pm= pm->next; 01523 01524 if(pm2->frame < frame) { 01525 pm2 = NULL; 01526 } 01527 else { 01528 while(pm2->prev && pm2->prev->frame > frame) { 01529 pm2= pm2->prev; 01530 } 01531 } 01532 01533 if(!pm2) { 01534 *fra1 = 0; 01535 *fra2 = pm->frame; 01536 } 01537 else { 01538 *fra1 = pm->frame; 01539 *fra2 = pm2->frame; 01540 } 01541 } 01542 } 01543 01544 static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) 01545 { 01546 PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); 01547 PTCacheMem *pm = NULL; 01548 unsigned int i, error = 0; 01549 01550 if(pf == NULL) 01551 return NULL; 01552 01553 if(!ptcache_file_header_begin_read(pf)) 01554 error = 1; 01555 01556 if(!error && (pf->type != pid->type || !pid->read_header(pf))) 01557 error = 1; 01558 01559 if(!error) { 01560 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); 01561 01562 pm->totpoint = pf->totpoint; 01563 pm->data_types = pf->data_types; 01564 pm->frame = pf->frame; 01565 01566 ptcache_data_alloc(pm); 01567 01568 if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) { 01569 for(i=0; i<BPHYS_TOT_DATA; i++) { 01570 unsigned int out_len = pm->totpoint*ptcache_data_size[i]; 01571 if(pf->data_types & (1<<i)) 01572 ptcache_file_compressed_read(pf, (unsigned char*)(pm->data[i]), out_len); 01573 } 01574 } 01575 else { 01576 BKE_ptcache_mem_pointers_init(pm); 01577 ptcache_file_pointers_init(pf); 01578 01579 for(i=0; i<pm->totpoint; i++) { 01580 if(!ptcache_file_data_read(pf)) { 01581 error = 1; 01582 break; 01583 } 01584 ptcache_data_copy(pf->cur, pm->cur); 01585 BKE_ptcache_mem_pointers_incr(pm); 01586 } 01587 } 01588 } 01589 01590 if(!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) { 01591 unsigned int extratype = 0; 01592 01593 while(ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) { 01594 PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata"); 01595 01596 extra->type = extratype; 01597 01598 ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int)); 01599 01600 extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data"); 01601 01602 if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) 01603 ptcache_file_compressed_read(pf, (unsigned char*)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]); 01604 else 01605 ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); 01606 01607 BLI_addtail(&pm->extradata, extra); 01608 } 01609 } 01610 01611 if(error && pm) { 01612 ptcache_data_free(pm); 01613 ptcache_extra_free(pm); 01614 MEM_freeN(pm); 01615 pm = NULL; 01616 } 01617 01618 ptcache_file_close(pf); 01619 01620 if (error && G.f & G_DEBUG) 01621 printf("Error reading from disk cache\n"); 01622 01623 return pm; 01624 } 01625 static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm) 01626 { 01627 PTCacheFile *pf = NULL; 01628 unsigned int i, error = 0; 01629 01630 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame); 01631 01632 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); 01633 01634 if(pf==NULL) { 01635 if (G.f & G_DEBUG) 01636 printf("Error opening disk cache file for writing\n"); 01637 return 0; 01638 } 01639 01640 pf->data_types = pm->data_types; 01641 pf->totpoint = pm->totpoint; 01642 pf->type = pid->type; 01643 pf->flag = 0; 01644 01645 if(pm->extradata.first) 01646 pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA; 01647 01648 if(pid->cache->compression) 01649 pf->flag |= PTCACHE_TYPEFLAG_COMPRESS; 01650 01651 if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) 01652 error = 1; 01653 01654 if(!error) { 01655 if(pid->cache->compression) { 01656 for(i=0; i<BPHYS_TOT_DATA; i++) { 01657 if(pm->data[i]) { 01658 unsigned int in_len = pm->totpoint*ptcache_data_size[i]; 01659 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); 01660 ptcache_file_compressed_write(pf, (unsigned char*)(pm->data[i]), in_len, out, pid->cache->compression); 01661 MEM_freeN(out); 01662 } 01663 } 01664 } 01665 else { 01666 BKE_ptcache_mem_pointers_init(pm); 01667 ptcache_file_pointers_init(pf); 01668 01669 for(i=0; i<pm->totpoint; i++) { 01670 ptcache_data_copy(pm->cur, pf->cur); 01671 if(!ptcache_file_data_write(pf)) { 01672 error = 1; 01673 break; 01674 } 01675 BKE_ptcache_mem_pointers_incr(pm); 01676 } 01677 } 01678 } 01679 01680 if(!error && pm->extradata.first) { 01681 PTCacheExtra *extra = pm->extradata.first; 01682 01683 for(; extra; extra=extra->next) { 01684 if(extra->data == NULL || extra->totdata == 0) 01685 continue; 01686 01687 ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int)); 01688 ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int)); 01689 01690 if(pid->cache->compression) { 01691 unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type]; 01692 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); 01693 ptcache_file_compressed_write(pf, (unsigned char*)(extra->data), in_len, out, pid->cache->compression); 01694 MEM_freeN(out); 01695 } 01696 else { 01697 ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); 01698 } 01699 } 01700 } 01701 01702 ptcache_file_close(pf); 01703 01704 if (error && G.f & G_DEBUG) 01705 printf("Error writing to disk cache\n"); 01706 01707 return error==0; 01708 } 01709 01710 static int ptcache_read_stream(PTCacheID *pid, int cfra) 01711 { 01712 PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); 01713 int error = 0; 01714 01715 if(pid->read_stream == NULL) 01716 return 0; 01717 01718 if(pf == NULL) { 01719 if (G.f & G_DEBUG) 01720 printf("Error opening disk cache file for reading\n"); 01721 return 0; 01722 } 01723 01724 if(!ptcache_file_header_begin_read(pf)) 01725 error = 1; 01726 01727 if(!error && (pf->type != pid->type || !pid->read_header(pf))) 01728 error = 1; 01729 01730 if(!error && pf->totpoint != pid->totpoint(pid->calldata, cfra)) 01731 error = 1; 01732 01733 if(!error) { 01734 ptcache_file_pointers_init(pf); 01735 01736 // we have stream reading here 01737 if (!pid->read_stream(pf, pid->calldata)) 01738 error = 1; 01739 } 01740 01741 ptcache_file_close(pf); 01742 01743 return error == 0; 01744 } 01745 static int ptcache_read(PTCacheID *pid, int cfra) 01746 { 01747 PTCacheMem *pm = NULL; 01748 int i; 01749 int *index = &i; 01750 01751 /* get a memory cache to read from */ 01752 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01753 pm = ptcache_disk_frame_to_mem(pid, cfra); 01754 } 01755 else { 01756 pm = pid->cache->mem_cache.first; 01757 01758 while(pm && pm->frame != cfra) 01759 pm = pm->next; 01760 } 01761 01762 /* read the cache */ 01763 if(pm) { 01764 int totpoint = pm->totpoint; 01765 01766 if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) 01767 totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra)); 01768 01769 BKE_ptcache_mem_pointers_init(pm); 01770 01771 for(i=0; i<totpoint; i++) { 01772 if(pm->data_types & (1<<BPHYS_DATA_INDEX)) 01773 index = pm->cur[BPHYS_DATA_INDEX]; 01774 01775 pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL); 01776 01777 BKE_ptcache_mem_pointers_incr(pm); 01778 } 01779 01780 if(pid->read_extra_data && pm->extradata.first) 01781 pid->read_extra_data(pid->calldata, pm, (float)pm->frame); 01782 01783 /* clean up temporary memory cache */ 01784 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01785 ptcache_data_free(pm); 01786 ptcache_extra_free(pm); 01787 MEM_freeN(pm); 01788 } 01789 } 01790 01791 return 1; 01792 } 01793 static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) 01794 { 01795 PTCacheMem *pm = NULL; 01796 int i; 01797 int *index = &i; 01798 01799 /* get a memory cache to read from */ 01800 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01801 pm = ptcache_disk_frame_to_mem(pid, cfra2); 01802 } 01803 else { 01804 pm = pid->cache->mem_cache.first; 01805 01806 while(pm && pm->frame != cfra2) 01807 pm = pm->next; 01808 } 01809 01810 /* read the cache */ 01811 if(pm) { 01812 int totpoint = pm->totpoint; 01813 01814 if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) 01815 totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra)); 01816 01817 BKE_ptcache_mem_pointers_init(pm); 01818 01819 for(i=0; i<totpoint; i++) { 01820 if(pm->data_types & (1<<BPHYS_DATA_INDEX)) 01821 index = pm->cur[BPHYS_DATA_INDEX]; 01822 01823 pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL); 01824 BKE_ptcache_mem_pointers_incr(pm); 01825 } 01826 01827 if(pid->interpolate_extra_data && pm->extradata.first) 01828 pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2); 01829 01830 /* clean up temporary memory cache */ 01831 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01832 ptcache_data_free(pm); 01833 ptcache_extra_free(pm); 01834 MEM_freeN(pm); 01835 } 01836 } 01837 01838 return 1; 01839 } 01840 /* reads cache from disk or memory */ 01841 /* possible to get old or interpolated result */ 01842 int BKE_ptcache_read(PTCacheID *pid, float cfra) 01843 { 01844 int cfrai = (int)floor(cfra), cfra1=0, cfra2=0; 01845 int ret = 0; 01846 01847 /* nothing to read to */ 01848 if(pid->totpoint(pid->calldata, cfrai) == 0) 01849 return 0; 01850 01851 if(pid->cache->flag & PTCACHE_READ_INFO) { 01852 pid->cache->flag &= ~PTCACHE_READ_INFO; 01853 ptcache_read(pid, 0); 01854 } 01855 01856 /* first check if we have the actual frame cached */ 01857 if(cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai)) 01858 cfra1 = cfrai; 01859 01860 /* no exact cache frame found so try to find cached frames around cfra */ 01861 if(cfra1 == 0) 01862 ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2); 01863 01864 if(cfra1 == 0 && cfra2 == 0) 01865 return 0; 01866 01867 /* don't read old cache if already simulated past cached frame */ 01868 if(cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) 01869 return 0; 01870 if(cfra1 && cfra1 == cfra2) 01871 return 0; 01872 01873 if(cfra1) { 01874 01875 if(pid->read_stream) { 01876 if (!ptcache_read_stream(pid, cfra1)) 01877 return 0; 01878 } 01879 else if(pid->read_point) 01880 ptcache_read(pid, cfra1); 01881 } 01882 01883 if(cfra2) { 01884 01885 if(pid->read_stream) { 01886 if (!ptcache_read_stream(pid, cfra2)) 01887 return 0; 01888 } 01889 else if(pid->read_point) { 01890 if(cfra1 && cfra2 && pid->interpolate_point) 01891 ptcache_interpolate(pid, cfra, cfra1, cfra2); 01892 else 01893 ptcache_read(pid, cfra2); 01894 } 01895 } 01896 01897 if(cfra1) 01898 ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT); 01899 else if(cfra2) { 01900 ret = PTCACHE_READ_OLD; 01901 pid->cache->simframe = cfra2; 01902 } 01903 01904 if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) { 01905 cfrai = (int)cfra; 01906 /* clear invalid cache frames so that better stuff can be simulated */ 01907 if(pid->cache->flag & PTCACHE_OUTDATED) { 01908 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai); 01909 } 01910 else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) { 01911 if(cfra <= pid->cache->last_exact) 01912 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; 01913 01914 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact)); 01915 } 01916 } 01917 01918 return ret; 01919 } 01920 static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint) 01921 { 01922 PTCacheFile *pf = NULL; 01923 int error = 0; 01924 01925 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra); 01926 01927 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); 01928 01929 if(pf==NULL) { 01930 if (G.f & G_DEBUG) 01931 printf("Error opening disk cache file for writing\n"); 01932 return 0; 01933 } 01934 01935 pf->data_types = pid->data_types; 01936 pf->totpoint = totpoint; 01937 pf->type = pid->type; 01938 pf->flag = 0; 01939 01940 if(!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))) 01941 error = 1; 01942 01943 if(!error && pid->write_stream) 01944 pid->write_stream(pf, pid->calldata); 01945 01946 ptcache_file_close(pf); 01947 01948 if (error && G.f & G_DEBUG) 01949 printf("Error writing to disk cache\n"); 01950 01951 return error == 0; 01952 } 01953 static int ptcache_write(PTCacheID *pid, int cfra, int overwrite) 01954 { 01955 PointCache *cache = pid->cache; 01956 PTCacheMem *pm=NULL, *pm2=NULL; 01957 int totpoint = pid->totpoint(pid->calldata, cfra); 01958 int i, error = 0; 01959 01960 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); 01961 01962 pm->totpoint = pid->totwrite(pid->calldata, cfra); 01963 pm->data_types = cfra ? pid->data_types : pid->info_types; 01964 01965 ptcache_data_alloc(pm); 01966 BKE_ptcache_mem_pointers_init(pm); 01967 01968 if(overwrite) { 01969 if(cache->flag & PTCACHE_DISK_CACHE) { 01970 int fra = cfra-1; 01971 01972 while(fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra)) 01973 fra--; 01974 01975 pm2 = ptcache_disk_frame_to_mem(pid, fra); 01976 } 01977 else 01978 pm2 = cache->mem_cache.last; 01979 } 01980 01981 if(pid->write_point) { 01982 for(i=0; i<totpoint; i++) { 01983 int write = pid->write_point(i, pid->calldata, pm->cur, cfra); 01984 if(write) { 01985 BKE_ptcache_mem_pointers_incr(pm); 01986 01987 /* newly born particles have to be copied to previous cached frame */ 01988 if(overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2)) 01989 pid->write_point(i, pid->calldata, pm2->cur, cfra); 01990 } 01991 } 01992 } 01993 01994 if(pid->write_extra_data) 01995 pid->write_extra_data(pid->calldata, pm, cfra); 01996 01997 pm->frame = cfra; 01998 01999 if(cache->flag & PTCACHE_DISK_CACHE) { 02000 error += !ptcache_mem_frame_to_disk(pid, pm); 02001 02002 // if(pm) /* pm is always set */ 02003 { 02004 ptcache_data_free(pm); 02005 ptcache_extra_free(pm); 02006 MEM_freeN(pm); 02007 } 02008 02009 if(pm2) { 02010 error += !ptcache_mem_frame_to_disk(pid, pm2); 02011 ptcache_data_free(pm2); 02012 ptcache_extra_free(pm2); 02013 MEM_freeN(pm2); 02014 } 02015 } 02016 else { 02017 BLI_addtail(&cache->mem_cache, pm); 02018 } 02019 02020 return error; 02021 } 02022 static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite) 02023 { 02024 PointCache *cache = pid->cache; 02025 int ofra = 0, efra = cache->endframe; 02026 02027 /* allways start from scratch on the first frame */ 02028 if(cfra && cfra == cache->startframe) { 02029 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); 02030 cache->flag &= ~PTCACHE_REDO_NEEDED; 02031 return 1; 02032 } 02033 02034 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 02035 if(cfra==0 && cache->startframe > 0) 02036 return 1; 02037 02038 /* find last cached frame */ 02039 while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) 02040 efra--; 02041 02042 /* find second last cached frame */ 02043 ofra = efra-1; 02044 while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) 02045 ofra--; 02046 } 02047 else { 02048 PTCacheMem *pm = cache->mem_cache.last; 02049 /* don't write info file in memory */ 02050 if(cfra == 0) 02051 return 0; 02052 02053 if(pm == NULL) 02054 return 1; 02055 02056 efra = pm->frame; 02057 ofra = (pm->prev ? pm->prev->frame : efra - cache->step); 02058 } 02059 02060 if(efra >= cache->startframe && cfra > efra) { 02061 if(ofra >= cache->startframe && efra - ofra < cache->step) { 02062 /* overwrite previous frame */ 02063 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra); 02064 *overwrite = 1; 02065 } 02066 return 1; 02067 } 02068 02069 return 0; 02070 } 02071 /* writes cache to disk or memory */ 02072 int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra) 02073 { 02074 PointCache *cache = pid->cache; 02075 int totpoint = pid->totpoint(pid->calldata, cfra); 02076 int overwrite = 0, error = 0; 02077 02078 if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) 02079 return 0; 02080 02081 if(ptcache_write_needed(pid, cfra, &overwrite)==0) 02082 return 0; 02083 02084 if(pid->write_stream) { 02085 ptcache_write_stream(pid, cfra, totpoint); 02086 } 02087 else if(pid->write_point) { 02088 error += ptcache_write(pid, cfra, overwrite); 02089 } 02090 02091 /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */ 02092 if(cfra - cache->last_exact == 1 || cfra == cache->startframe) { 02093 cache->last_exact = cfra; 02094 cache->flag &= ~PTCACHE_FRAMES_SKIPPED; 02095 } 02096 /* Don't mark skipped when writing info file (frame 0) */ 02097 else if(cfra) 02098 cache->flag |= PTCACHE_FRAMES_SKIPPED; 02099 02100 /* Update timeline cache display */ 02101 if(cfra && cache->cached_frames) 02102 cache->cached_frames[cfra-cache->startframe] = 1; 02103 02104 BKE_ptcache_update_info(pid); 02105 02106 return !error; 02107 } 02108 /* youll need to close yourself after! 02109 * mode - PTCACHE_CLEAR_ALL, 02110 02111 */ 02112 /* Clears & resets */ 02113 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) 02114 { 02115 unsigned int len; /* store the length of the string */ 02116 unsigned int sta, end; 02117 02118 /* mode is same as fopen's modes */ 02119 DIR *dir; 02120 struct dirent *de; 02121 char path[MAX_PTCACHE_PATH]; 02122 char filename[MAX_PTCACHE_FILE]; 02123 char path_full[MAX_PTCACHE_FILE]; 02124 char ext[MAX_PTCACHE_PATH]; 02125 02126 if(!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) 02127 return; 02128 02129 if (pid->cache->flag & PTCACHE_IGNORE_CLEAR) 02130 return; 02131 02132 sta = pid->cache->startframe; 02133 end = pid->cache->endframe; 02134 02135 #ifndef DURIAN_POINTCACHE_LIB_OK 02136 /* don't allow clearing for linked objects */ 02137 if(pid->ob->id.lib) 02138 return; 02139 #endif 02140 02141 /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */ 02142 02143 /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */ 02144 switch (mode) { 02145 case PTCACHE_CLEAR_ALL: 02146 case PTCACHE_CLEAR_BEFORE: 02147 case PTCACHE_CLEAR_AFTER: 02148 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 02149 ptcache_path(pid, path); 02150 02151 len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */ 02152 02153 dir = opendir(path); 02154 if (dir==NULL) 02155 return; 02156 02157 BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index); 02158 02159 while ((de = readdir(dir)) != NULL) { 02160 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ 02161 if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ 02162 if (mode == PTCACHE_CLEAR_ALL) { 02163 pid->cache->last_exact = MIN2(pid->cache->startframe, 0); 02164 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); 02165 BLI_delete(path_full, 0, 0); 02166 } else { 02167 /* read the number of the file */ 02168 unsigned int frame, len2 = (int)strlen(de->d_name); 02169 char num[7]; 02170 02171 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ 02172 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); 02173 frame = atoi(num); 02174 02175 if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || 02176 (mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) { 02177 02178 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); 02179 BLI_delete(path_full, 0, 0); 02180 if(pid->cache->cached_frames && frame >=sta && frame <= end) 02181 pid->cache->cached_frames[frame-sta] = 0; 02182 } 02183 } 02184 } 02185 } 02186 } 02187 } 02188 closedir(dir); 02189 02190 if(mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames) 02191 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); 02192 } 02193 else { 02194 PTCacheMem *pm= pid->cache->mem_cache.first; 02195 PTCacheMem *link= NULL; 02196 02197 if(mode == PTCACHE_CLEAR_ALL) { 02198 /*we want startframe if the cache starts before zero*/ 02199 pid->cache->last_exact = MIN2(pid->cache->startframe, 0); 02200 for(; pm; pm=pm->next) { 02201 ptcache_data_free(pm); 02202 ptcache_extra_free(pm); 02203 } 02204 BLI_freelistN(&pid->cache->mem_cache); 02205 02206 if(pid->cache->cached_frames) 02207 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); 02208 } else { 02209 while(pm) { 02210 if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || 02211 (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { 02212 link = pm; 02213 if(pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end) 02214 pid->cache->cached_frames[pm->frame-sta] = 0; 02215 ptcache_data_free(pm); 02216 ptcache_extra_free(pm); 02217 pm = pm->next; 02218 BLI_freelinkN(&pid->cache->mem_cache, link); 02219 } 02220 else 02221 pm = pm->next; 02222 } 02223 } 02224 } 02225 break; 02226 02227 case PTCACHE_CLEAR_FRAME: 02228 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 02229 if(BKE_ptcache_id_exist(pid, cfra)) { 02230 ptcache_filename(pid, filename, cfra, 1, 1); /* no path */ 02231 BLI_delete(filename, 0, 0); 02232 } 02233 } 02234 else { 02235 PTCacheMem *pm = pid->cache->mem_cache.first; 02236 02237 for(; pm; pm=pm->next) { 02238 if(pm->frame == cfra) { 02239 ptcache_data_free(pm); 02240 ptcache_extra_free(pm); 02241 BLI_freelinkN(&pid->cache->mem_cache, pm); 02242 break; 02243 } 02244 } 02245 } 02246 if(pid->cache->cached_frames && cfra>=sta && cfra<=end) 02247 pid->cache->cached_frames[cfra-sta] = 0; 02248 break; 02249 } 02250 02251 BKE_ptcache_update_info(pid); 02252 } 02253 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) 02254 { 02255 if(!pid->cache) 02256 return 0; 02257 02258 if(cfra<pid->cache->startframe || cfra > pid->cache->endframe) 02259 return 0; 02260 02261 if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0) 02262 return 0; 02263 02264 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 02265 char filename[MAX_PTCACHE_FILE]; 02266 02267 ptcache_filename(pid, filename, cfra, 1, 1); 02268 02269 return BLI_exists(filename); 02270 } 02271 else { 02272 PTCacheMem *pm = pid->cache->mem_cache.first; 02273 02274 for(; pm; pm=pm->next) { 02275 if(pm->frame==cfra) 02276 return 1; 02277 } 02278 return 0; 02279 } 02280 } 02281 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale) 02282 { 02283 /* Object *ob; */ /* UNUSED */ 02284 PointCache *cache; 02285 /* float offset; unused for now */ 02286 float time, nexttime; 02287 02288 /* TODO: this has to be sorter out once bsystem_time gets redone, */ 02289 /* now caches can handle interpolating etc. too - jahka */ 02290 02291 /* time handling for point cache: 02292 * - simulation time is scaled by result of bsystem_time 02293 * - for offsetting time only time offset is taken into account, since 02294 * that's always the same and can't be animated. a timeoffset which 02295 * varies over time is not simpe to support. 02296 * - field and motion blur offsets are currently ignored, proper solution 02297 * is probably to interpolate results from two frames for that .. 02298 */ 02299 02300 /* ob= pid->ob; */ /* UNUSED */ 02301 cache= pid->cache; 02302 02303 if(timescale) { 02304 time= BKE_curframe(scene); 02305 nexttime= BKE_frame_to_ctime(scene, CFRA+1); 02306 02307 *timescale= MAX2(nexttime - time, 0.0f); 02308 } 02309 02310 if(startframe && endframe) { 02311 *startframe= cache->startframe; 02312 *endframe= cache->endframe; 02313 02314 /* TODO: time handling with object offsets and simulated vs. cached 02315 * particles isn't particularly easy, so for now what you see is what 02316 * you get. In the future point cache could handle the whole particle 02317 * system timing. */ 02318 #if 0 02319 if ((ob->partype & PARSLOW)==0) { 02320 offset= ob->sf; 02321 02322 *startframe += (int)(offset+0.5f); 02323 *endframe += (int)(offset+0.5f); 02324 } 02325 #endif 02326 } 02327 02328 /* verify cached_frames array is up to date */ 02329 if(cache->cached_frames) { 02330 if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { 02331 MEM_freeN(cache->cached_frames); 02332 cache->cached_frames = NULL; 02333 } 02334 } 02335 02336 if(cache->cached_frames==NULL && cache->endframe > cache->startframe) { 02337 unsigned int sta=cache->startframe; 02338 unsigned int end=cache->endframe; 02339 02340 cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); 02341 02342 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 02343 /* mode is same as fopen's modes */ 02344 DIR *dir; 02345 struct dirent *de; 02346 char path[MAX_PTCACHE_PATH]; 02347 char filename[MAX_PTCACHE_FILE]; 02348 char ext[MAX_PTCACHE_PATH]; 02349 unsigned int len; /* store the length of the string */ 02350 02351 ptcache_path(pid, path); 02352 02353 len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */ 02354 02355 dir = opendir(path); 02356 if (dir==NULL) 02357 return; 02358 02359 BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index); 02360 02361 while ((de = readdir(dir)) != NULL) { 02362 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ 02363 if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ 02364 /* read the number of the file */ 02365 unsigned int frame, len2 = (int)strlen(de->d_name); 02366 char num[7]; 02367 02368 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ 02369 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); 02370 frame = atoi(num); 02371 02372 if(frame >= sta && frame <= end) 02373 cache->cached_frames[frame-sta] = 1; 02374 } 02375 } 02376 } 02377 } 02378 closedir(dir); 02379 } 02380 else { 02381 PTCacheMem *pm= pid->cache->mem_cache.first; 02382 02383 while(pm) { 02384 if(pm->frame >= sta && pm->frame <= end) 02385 cache->cached_frames[pm->frame-sta] = 1; 02386 pm = pm->next; 02387 } 02388 } 02389 } 02390 } 02391 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) 02392 { 02393 PointCache *cache; 02394 int reset, clear, after; 02395 02396 if(!pid->cache) 02397 return 0; 02398 02399 cache= pid->cache; 02400 reset= 0; 02401 clear= 0; 02402 after= 0; 02403 02404 if(mode == PTCACHE_RESET_DEPSGRAPH) { 02405 if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { 02406 if(cache->flag & PTCACHE_QUICK_CACHE) 02407 clear= 1; 02408 02409 after= 1; 02410 } 02411 02412 cache->flag |= PTCACHE_OUTDATED; 02413 } 02414 else if(mode == PTCACHE_RESET_BAKED) { 02415 if(!BKE_ptcache_get_continue_physics()) { 02416 reset= 1; 02417 clear= 1; 02418 } 02419 else 02420 cache->flag |= PTCACHE_OUTDATED; 02421 } 02422 else if(mode == PTCACHE_RESET_OUTDATED) { 02423 reset = 1; 02424 02425 if(cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) { 02426 clear= 1; 02427 cache->flag &= ~PTCACHE_OUTDATED; 02428 } 02429 } 02430 02431 if(reset) { 02432 BKE_ptcache_invalidate(cache); 02433 cache->flag &= ~PTCACHE_REDO_NEEDED; 02434 02435 if(pid->type == PTCACHE_TYPE_CLOTH) 02436 cloth_free_modifier(pid->calldata); 02437 else if(pid->type == PTCACHE_TYPE_SOFTBODY) 02438 sbFreeSimulation(pid->calldata); 02439 else if(pid->type == PTCACHE_TYPE_PARTICLES) 02440 psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); 02441 else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) 02442 smokeModifier_reset(pid->calldata); 02443 else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) 02444 smokeModifier_reset_turbulence(pid->calldata); 02445 else if(pid->type == PTCACHE_TYPE_DYNAMICPAINT) 02446 dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata); 02447 } 02448 if(clear) 02449 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02450 else if(after) 02451 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA); 02452 02453 return (reset || clear || after); 02454 } 02455 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) 02456 { 02457 PTCacheID pid; 02458 ParticleSystem *psys; 02459 ModifierData *md; 02460 int reset, skip; 02461 02462 reset= 0; 02463 skip= 0; 02464 02465 if(ob->soft) { 02466 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); 02467 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02468 } 02469 02470 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 02471 /* children or just redo can be calculated without reseting anything */ 02472 if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) 02473 skip = 1; 02474 /* Baked cloth hair has to be checked too, because we don't want to reset */ 02475 /* particles or cloth in that case -jahka */ 02476 else if(psys->clmd) { 02477 BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd); 02478 if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 02479 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02480 else 02481 skip = 1; 02482 } 02483 02484 if(skip == 0 && psys->part) { 02485 BKE_ptcache_id_from_particles(&pid, ob, psys); 02486 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02487 } 02488 } 02489 02490 for(md=ob->modifiers.first; md; md=md->next) { 02491 if(md->type == eModifierType_Cloth) { 02492 BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md); 02493 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02494 } 02495 if(md->type == eModifierType_Smoke) { 02496 SmokeModifierData *smd = (SmokeModifierData *)md; 02497 if(smd->type & MOD_SMOKE_TYPE_DOMAIN) 02498 { 02499 BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md); 02500 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02501 } 02502 } 02503 if(md->type == eModifierType_DynamicPaint) { 02504 DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; 02505 if(pmd->canvas) 02506 { 02507 DynamicPaintSurface *surface = pmd->canvas->surfaces.first; 02508 02509 for (; surface; surface=surface->next) { 02510 BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface); 02511 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02512 } 02513 } 02514 } 02515 } 02516 02517 if (ob->type == OB_ARMATURE) 02518 BIK_clear_cache(ob->pose); 02519 02520 return reset; 02521 } 02522 02523 /* Use this when quitting blender, with unsaved files */ 02524 void BKE_ptcache_remove(void) 02525 { 02526 char path[MAX_PTCACHE_PATH]; 02527 char path_full[MAX_PTCACHE_PATH]; 02528 int rmdir = 1; 02529 02530 ptcache_path(NULL, path); 02531 02532 if (BLI_exists(path)) { 02533 /* The pointcache dir exists? - remove all pointcache */ 02534 02535 DIR *dir; 02536 struct dirent *de; 02537 02538 dir = opendir(path); 02539 if (dir==NULL) 02540 return; 02541 02542 while ((de = readdir(dir)) != NULL) { 02543 if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) { 02544 /* do nothing */ 02545 } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/ 02546 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); 02547 BLI_delete(path_full, 0, 0); 02548 } else { 02549 rmdir = 0; /* unknown file, dont remove the dir */ 02550 } 02551 } 02552 02553 closedir(dir); 02554 } else { 02555 rmdir = 0; /* path dosnt exist */ 02556 } 02557 02558 if (rmdir) { 02559 BLI_delete(path, 1, 0); 02560 } 02561 } 02562 02563 /* Continuous Interaction */ 02564 02565 static int CONTINUE_PHYSICS = 0; 02566 02567 void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable) 02568 { 02569 Object *ob; 02570 02571 if(CONTINUE_PHYSICS != enable) { 02572 CONTINUE_PHYSICS = enable; 02573 02574 if(CONTINUE_PHYSICS == 0) { 02575 for(ob=bmain->object.first; ob; ob=ob->id.next) 02576 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) 02577 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 02578 } 02579 } 02580 } 02581 02582 int BKE_ptcache_get_continue_physics(void) 02583 { 02584 return CONTINUE_PHYSICS; 02585 } 02586 02587 /* Point Cache handling */ 02588 02589 PointCache *BKE_ptcache_add(ListBase *ptcaches) 02590 { 02591 PointCache *cache; 02592 02593 cache= MEM_callocN(sizeof(PointCache), "PointCache"); 02594 cache->startframe= 1; 02595 cache->endframe= 250; 02596 cache->step= 10; 02597 cache->index = -1; 02598 02599 BLI_addtail(ptcaches, cache); 02600 02601 return cache; 02602 } 02603 02604 void BKE_ptcache_free_mem(ListBase *mem_cache) 02605 { 02606 PTCacheMem *pm = mem_cache->first; 02607 02608 if(pm) { 02609 for(; pm; pm=pm->next) { 02610 ptcache_data_free(pm); 02611 ptcache_extra_free(pm); 02612 } 02613 02614 BLI_freelistN(mem_cache); 02615 } 02616 } 02617 void BKE_ptcache_free(PointCache *cache) 02618 { 02619 BKE_ptcache_free_mem(&cache->mem_cache); 02620 if(cache->edit && cache->free_edit) 02621 cache->free_edit(cache->edit); 02622 if(cache->cached_frames) 02623 MEM_freeN(cache->cached_frames); 02624 MEM_freeN(cache); 02625 } 02626 void BKE_ptcache_free_list(ListBase *ptcaches) 02627 { 02628 PointCache *cache = ptcaches->first; 02629 02630 while(cache) { 02631 BLI_remlink(ptcaches, cache); 02632 BKE_ptcache_free(cache); 02633 cache = ptcaches->first; 02634 } 02635 } 02636 02637 static PointCache *ptcache_copy(PointCache *cache) 02638 { 02639 PointCache *ncache; 02640 02641 ncache= MEM_dupallocN(cache); 02642 02643 /* hmm, should these be copied over instead? */ 02644 ncache->mem_cache.first = NULL; 02645 ncache->mem_cache.last = NULL; 02646 ncache->cached_frames = NULL; 02647 ncache->edit = NULL; 02648 02649 ncache->flag= 0; 02650 ncache->simframe= 0; 02651 02652 return ncache; 02653 } 02654 /* returns first point cache */ 02655 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old) 02656 { 02657 PointCache *cache = ptcaches_old->first; 02658 02659 ptcaches_new->first = ptcaches_new->last = NULL; 02660 02661 for(; cache; cache=cache->next) 02662 BLI_addtail(ptcaches_new, ptcache_copy(cache)); 02663 02664 return ptcaches_new->first; 02665 } 02666 02667 02668 /* Baking */ 02669 void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene) 02670 { 02671 PTCacheBaker baker; 02672 02673 baker.bake=0; 02674 baker.break_data=NULL; 02675 baker.break_test=NULL; 02676 baker.pid=NULL; 02677 baker.progressbar=NULL; 02678 baker.progressend=NULL; 02679 baker.progresscontext=NULL; 02680 baker.render=0; 02681 baker.anim_init = 0; 02682 baker.main=bmain; 02683 baker.scene=scene; 02684 baker.quick_step=scene->physics_settings.quick_cache_step; 02685 02686 BKE_ptcache_bake(&baker); 02687 } 02688 02689 /* Simulation thread, no need for interlocks as data written in both threads 02690 are only unitary integers (I/O assumed to be atomic for them) */ 02691 typedef struct { 02692 int break_operation; 02693 int thread_ended; 02694 int endframe; 02695 int step; 02696 int *cfra_ptr; 02697 Main *main; 02698 Scene *scene; 02699 } ptcache_bake_data; 02700 02701 static void ptcache_dt_to_str(char *str, double dtime) 02702 { 02703 if(dtime > 60.0) { 02704 if(dtime > 3600.0) 02705 sprintf(str, "%ih %im %is", (int)(dtime/3600), ((int)(dtime/60))%60, ((int)dtime) % 60); 02706 else 02707 sprintf(str, "%im %is", ((int)(dtime/60))%60, ((int)dtime) % 60); 02708 } 02709 else 02710 sprintf(str, "%is", ((int)dtime) % 60); 02711 } 02712 02713 static void *ptcache_bake_thread(void *ptr) 02714 { 02715 int usetimer = 0, sfra, efra; 02716 double stime, ptime, ctime, fetd; 02717 char run[32], cur[32], etd[32]; 02718 02719 ptcache_bake_data *data = (ptcache_bake_data*)ptr; 02720 02721 stime = ptime = PIL_check_seconds_timer(); 02722 sfra = *data->cfra_ptr; 02723 efra = data->endframe; 02724 02725 for(; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) { 02726 scene_update_for_newframe(data->main, data->scene, data->scene->lay); 02727 if(G.background) { 02728 printf("bake: frame %d :: %d\n", (int)*data->cfra_ptr, data->endframe); 02729 } 02730 else { 02731 ctime = PIL_check_seconds_timer(); 02732 02733 fetd = (ctime-ptime)*(efra-*data->cfra_ptr)/data->step; 02734 02735 if(usetimer || fetd > 60.0) { 02736 usetimer = 1; 02737 02738 ptcache_dt_to_str(cur, ctime-ptime); 02739 ptcache_dt_to_str(run, ctime-stime); 02740 ptcache_dt_to_str(etd, fetd); 02741 02742 printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s \r", run, *data->cfra_ptr-sfra+1, efra-sfra+1, ctime-ptime, etd); 02743 } 02744 ptime = ctime; 02745 } 02746 } 02747 02748 if(usetimer) { 02749 ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime); 02750 printf("Bake %s %s (%i frames simulated). \n", (data->break_operation ? "canceled after" : "finished in"), run, *data->cfra_ptr-sfra); 02751 } 02752 02753 data->thread_ended = TRUE; 02754 return NULL; 02755 } 02756 02757 /* if bake is not given run simulations to current frame */ 02758 void BKE_ptcache_bake(PTCacheBaker* baker) 02759 { 02760 Main *bmain = baker->main; 02761 Scene *scene = baker->scene; 02762 Scene *sce_iter; /* SETLOOPER macro only */ 02763 Base *base; 02764 ListBase pidlist; 02765 PTCacheID *pid = baker->pid; 02766 PointCache *cache = NULL; 02767 float frameleno = scene->r.framelen; 02768 int cfrao = CFRA; 02769 int startframe = MAXFRAME; 02770 int bake = baker->bake; 02771 int render = baker->render; 02772 ListBase threads; 02773 ptcache_bake_data thread_data; 02774 int progress, old_progress; 02775 02776 thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA; 02777 thread_data.step = baker->quick_step; 02778 thread_data.cfra_ptr = &CFRA; 02779 thread_data.scene = baker->scene; 02780 thread_data.main = baker->main; 02781 02782 G.afbreek = 0; 02783 02784 /* set caches to baking mode and figure out start frame */ 02785 if(pid) { 02786 /* cache/bake a single object */ 02787 cache = pid->cache; 02788 if((cache->flag & PTCACHE_BAKED)==0) { 02789 if(pid->type==PTCACHE_TYPE_PARTICLES) { 02790 ParticleSystem *psys= pid->calldata; 02791 02792 /* a bit confusing, could make this work better in the UI */ 02793 if(psys->part->type == PART_EMITTER) 02794 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); 02795 } 02796 else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) { 02797 /* get all pids from the object and search for smoke low res */ 02798 ListBase pidlist2; 02799 PTCacheID *pid2; 02800 BKE_ptcache_ids_from_object(&pidlist2, pid->ob, scene, MAX_DUPLI_RECUR); 02801 for(pid2=pidlist2.first; pid2; pid2=pid2->next) { 02802 if(pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) 02803 { 02804 if(pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) { 02805 if(bake || pid2->cache->flag & PTCACHE_REDO_NEEDED) 02806 BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0); 02807 if(bake) { 02808 pid2->cache->flag |= PTCACHE_BAKING; 02809 pid2->cache->flag &= ~PTCACHE_BAKED; 02810 } 02811 } 02812 } 02813 } 02814 BLI_freelistN(&pidlist2); 02815 } 02816 02817 if(bake || cache->flag & PTCACHE_REDO_NEEDED) 02818 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02819 02820 startframe = MAX2(cache->last_exact, cache->startframe); 02821 02822 if(bake) { 02823 thread_data.endframe = cache->endframe; 02824 cache->flag |= PTCACHE_BAKING; 02825 } 02826 else { 02827 thread_data.endframe = MIN2(thread_data.endframe, cache->endframe); 02828 } 02829 02830 cache->flag &= ~PTCACHE_BAKED; 02831 } 02832 } 02833 else for(SETLOOPER(scene, sce_iter, base)) { 02834 /* cache/bake everything in the scene */ 02835 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); 02836 02837 for(pid=pidlist.first; pid; pid=pid->next) { 02838 cache = pid->cache; 02839 if((cache->flag & PTCACHE_BAKED)==0) { 02840 if(pid->type==PTCACHE_TYPE_PARTICLES) { 02841 ParticleSystem *psys = (ParticleSystem*)pid->calldata; 02842 /* skip hair & keyed particles */ 02843 if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED) 02844 continue; 02845 02846 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); 02847 } 02848 02849 if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) 02850 && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake)) 02851 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02852 02853 startframe = MIN2(startframe, cache->startframe); 02854 02855 if(bake || render) { 02856 cache->flag |= PTCACHE_BAKING; 02857 02858 if(bake) 02859 thread_data.endframe = MAX2(thread_data.endframe, cache->endframe); 02860 } 02861 02862 cache->flag &= ~PTCACHE_BAKED; 02863 02864 } 02865 } 02866 BLI_freelistN(&pidlist); 02867 } 02868 02869 CFRA = startframe; 02870 scene->r.framelen = 1.0; 02871 thread_data.break_operation = FALSE; 02872 thread_data.thread_ended = FALSE; 02873 old_progress = -1; 02874 02875 WM_cursor_wait(1); 02876 02877 if(G.background) { 02878 ptcache_bake_thread((void*)&thread_data); 02879 } 02880 else { 02881 BLI_init_threads(&threads, ptcache_bake_thread, 1); 02882 BLI_insert_thread(&threads, (void*)&thread_data); 02883 02884 while (thread_data.thread_ended == FALSE) { 02885 02886 if(bake) 02887 progress = (int)(100.0f * (float)(CFRA - startframe)/(float)(thread_data.endframe-startframe)); 02888 else 02889 progress = CFRA; 02890 02891 /* NOTE: baking should not redraw whole ui as this slows things down */ 02892 if ((baker->progressbar) && (progress != old_progress)) { 02893 baker->progressbar(baker->progresscontext, progress); 02894 old_progress = progress; 02895 } 02896 02897 /* Delay to lessen CPU load from UI thread */ 02898 PIL_sleep_ms(200); 02899 02900 /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ 02901 if(blender_test_break() && !thread_data.break_operation) { 02902 thread_data.break_operation = TRUE; 02903 if (baker->progressend) 02904 baker->progressend(baker->progresscontext); 02905 WM_cursor_wait(1); 02906 } 02907 } 02908 02909 BLI_end_threads(&threads); 02910 } 02911 /* clear baking flag */ 02912 if(pid) { 02913 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); 02914 cache->flag |= PTCACHE_SIMULATION_VALID; 02915 if(bake) { 02916 cache->flag |= PTCACHE_BAKED; 02917 /* write info file */ 02918 if(cache->flag & PTCACHE_DISK_CACHE) 02919 BKE_ptcache_write(pid, 0); 02920 } 02921 } 02922 else for(SETLOOPER(scene, sce_iter, base)) { 02923 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); 02924 02925 for(pid=pidlist.first; pid; pid=pid->next) { 02926 /* skip hair particles */ 02927 if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR) 02928 continue; 02929 02930 cache = pid->cache; 02931 02932 if(thread_data.step > 1) 02933 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); 02934 else 02935 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); 02936 02937 cache->flag |= PTCACHE_SIMULATION_VALID; 02938 02939 if(bake) { 02940 cache->flag |= PTCACHE_BAKED; 02941 if(cache->flag & PTCACHE_DISK_CACHE) 02942 BKE_ptcache_write(pid, 0); 02943 } 02944 } 02945 BLI_freelistN(&pidlist); 02946 } 02947 02948 scene->r.framelen = frameleno; 02949 CFRA = cfrao; 02950 02951 if(bake) /* already on cfra unless baking */ 02952 scene_update_for_newframe(bmain, scene, scene->lay); 02953 02954 if (thread_data.break_operation) 02955 WM_cursor_wait(0); 02956 else if (baker->progressend) 02957 baker->progressend(baker->progresscontext); 02958 02959 WM_cursor_wait(0); 02960 02961 /* TODO: call redraw all windows somehow */ 02962 } 02963 /* Helpers */ 02964 void BKE_ptcache_disk_to_mem(PTCacheID *pid) 02965 { 02966 PointCache *cache = pid->cache; 02967 PTCacheMem *pm = NULL; 02968 int baked = cache->flag & PTCACHE_BAKED; 02969 int cfra, sfra = cache->startframe, efra = cache->endframe; 02970 02971 /* Remove possible bake flag to allow clear */ 02972 cache->flag &= ~PTCACHE_BAKED; 02973 02974 /* PTCACHE_DISK_CACHE flag was cleared already */ 02975 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02976 02977 /* restore possible bake flag */ 02978 cache->flag |= baked; 02979 02980 for(cfra=sfra; cfra <= efra; cfra++) { 02981 pm = ptcache_disk_frame_to_mem(pid, cfra); 02982 02983 if(pm) 02984 BLI_addtail(&pid->cache->mem_cache, pm); 02985 } 02986 } 02987 void BKE_ptcache_mem_to_disk(PTCacheID *pid) 02988 { 02989 PointCache *cache = pid->cache; 02990 PTCacheMem *pm = cache->mem_cache.first; 02991 int baked = cache->flag & PTCACHE_BAKED; 02992 02993 /* Remove possible bake flag to allow clear */ 02994 cache->flag &= ~PTCACHE_BAKED; 02995 02996 /* PTCACHE_DISK_CACHE flag was set already */ 02997 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02998 02999 /* restore possible bake flag */ 03000 cache->flag |= baked; 03001 03002 for(; pm; pm=pm->next) { 03003 if(ptcache_mem_frame_to_disk(pid, pm)==0) { 03004 cache->flag &= ~PTCACHE_DISK_CACHE; 03005 break; 03006 } 03007 } 03008 03009 /* write info file */ 03010 if(cache->flag & PTCACHE_BAKED) 03011 BKE_ptcache_write(pid, 0); 03012 } 03013 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) 03014 { 03015 PointCache *cache = pid->cache; 03016 int last_exact = cache->last_exact; 03017 03018 if (!G.relbase_valid){ 03019 cache->flag &= ~PTCACHE_DISK_CACHE; 03020 if (G.f & G_DEBUG) 03021 printf("File must be saved before using disk cache!\n"); 03022 return; 03023 } 03024 03025 if(cache->cached_frames) { 03026 MEM_freeN(cache->cached_frames); 03027 cache->cached_frames=NULL; 03028 } 03029 03030 if(cache->flag & PTCACHE_DISK_CACHE) 03031 BKE_ptcache_mem_to_disk(pid); 03032 else 03033 BKE_ptcache_disk_to_mem(pid); 03034 03035 cache->flag ^= PTCACHE_DISK_CACHE; 03036 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 03037 cache->flag ^= PTCACHE_DISK_CACHE; 03038 03039 cache->last_exact = last_exact; 03040 03041 BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL); 03042 03043 BKE_ptcache_update_info(pid); 03044 } 03045 03046 void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const char *name_dst) 03047 { 03048 char old_name[80]; 03049 int len; /* store the length of the string */ 03050 /* mode is same as fopen's modes */ 03051 DIR *dir; 03052 struct dirent *de; 03053 char path[MAX_PTCACHE_PATH]; 03054 char old_filename[MAX_PTCACHE_FILE]; 03055 char new_path_full[MAX_PTCACHE_FILE]; 03056 char old_path_full[MAX_PTCACHE_FILE]; 03057 char ext[MAX_PTCACHE_PATH]; 03058 03059 /* save old name */ 03060 BLI_strncpy(old_name, pid->cache->name, sizeof(old_name)); 03061 03062 /* get "from" filename */ 03063 BLI_strncpy(pid->cache->name, name_src, sizeof(pid->cache->name)); 03064 03065 len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */ 03066 03067 ptcache_path(pid, path); 03068 dir = opendir(path); 03069 if(dir==NULL) { 03070 BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name)); 03071 return; 03072 } 03073 03074 BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index); 03075 03076 /* put new name into cache */ 03077 BLI_strncpy(pid->cache->name, name_dst, sizeof(pid->cache->name)); 03078 03079 while ((de = readdir(dir)) != NULL) { 03080 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ 03081 if (strncmp(old_filename, de->d_name, len ) == 0) { /* do we have the right prefix */ 03082 /* read the number of the file */ 03083 int frame, len2 = (int)strlen(de->d_name); 03084 char num[7]; 03085 03086 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ 03087 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); 03088 frame = atoi(num); 03089 03090 BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name); 03091 ptcache_filename(pid, new_path_full, frame, 1, 1); 03092 BLI_rename(old_path_full, new_path_full); 03093 } 03094 } 03095 } 03096 } 03097 closedir(dir); 03098 03099 BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name)); 03100 } 03101 03102 void BKE_ptcache_load_external(PTCacheID *pid) 03103 { 03104 /*todo*/ 03105 PointCache *cache = pid->cache; 03106 int len; /* store the length of the string */ 03107 int info = 0; 03108 int start = MAXFRAME; 03109 int end = -1; 03110 03111 /* mode is same as fopen's modes */ 03112 DIR *dir; 03113 struct dirent *de; 03114 char path[MAX_PTCACHE_PATH]; 03115 char filename[MAX_PTCACHE_FILE]; 03116 char ext[MAX_PTCACHE_PATH]; 03117 03118 if(!cache) 03119 return; 03120 03121 ptcache_path(pid, path); 03122 03123 len = ptcache_filename(pid, filename, 1, 0, 0); /* no path */ 03124 03125 dir = opendir(path); 03126 if (dir==NULL) 03127 return; 03128 03129 if(cache->index >= 0) 03130 BLI_snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index); 03131 else 03132 BLI_strncpy(ext, PTCACHE_EXT, sizeof(ext)); 03133 03134 while ((de = readdir(dir)) != NULL) { 03135 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ 03136 if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ 03137 /* read the number of the file */ 03138 int frame, len2 = (int)strlen(de->d_name); 03139 char num[7]; 03140 03141 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ 03142 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); 03143 frame = atoi(num); 03144 03145 if(frame) { 03146 start = MIN2(start, frame); 03147 end = MAX2(end, frame); 03148 } 03149 else 03150 info = 1; 03151 } 03152 } 03153 } 03154 } 03155 closedir(dir); 03156 03157 if(start != MAXFRAME) { 03158 PTCacheFile *pf; 03159 03160 cache->startframe = start; 03161 cache->endframe = end; 03162 cache->totpoint = 0; 03163 03164 if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) 03165 ; /*necessary info in every file*/ 03166 /* read totpoint from info file (frame 0) */ 03167 else if(info) { 03168 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0); 03169 03170 if(pf) { 03171 if(ptcache_file_header_begin_read(pf)) { 03172 if(pf->type == pid->type && pid->read_header(pf)) { 03173 cache->totpoint = pf->totpoint; 03174 cache->flag |= PTCACHE_READ_INFO; 03175 } 03176 else { 03177 cache->totpoint = 0; 03178 } 03179 } 03180 ptcache_file_close(pf); 03181 } 03182 } 03183 /* or from any old format cache file */ 03184 else { 03185 float old_data[14]; 03186 int elemsize = ptcache_old_elemsize(pid); 03187 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe); 03188 03189 if(pf) { 03190 while(ptcache_file_read(pf, old_data, 1, elemsize)) 03191 cache->totpoint++; 03192 03193 ptcache_file_close(pf); 03194 } 03195 } 03196 cache->flag |= (PTCACHE_BAKED|PTCACHE_DISK_CACHE|PTCACHE_SIMULATION_VALID); 03197 cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED); 03198 } 03199 03200 BKE_ptcache_update_info(pid); 03201 } 03202 03203 void BKE_ptcache_update_info(PTCacheID *pid) 03204 { 03205 PointCache *cache = pid->cache; 03206 PTCacheExtra *extra = NULL; 03207 int totframes = 0; 03208 char mem_info[64]; 03209 03210 if(cache->flag & PTCACHE_EXTERNAL) { 03211 int cfra = cache->startframe; 03212 03213 for(; cfra<=cache->endframe; cfra++) { 03214 if(BKE_ptcache_id_exist(pid, cfra)) 03215 totframes++; 03216 } 03217 03218 /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ 03219 if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) 03220 BLI_snprintf(cache->info, sizeof(cache->info), "%i frames found!", totframes); 03221 else if(totframes && cache->totpoint) 03222 BLI_snprintf(cache->info, sizeof(cache->info), "%i points found!", cache->totpoint); 03223 else 03224 BLI_snprintf(cache->info, sizeof(cache->info), "No valid data to read!"); 03225 return; 03226 } 03227 03228 if(cache->flag & PTCACHE_DISK_CACHE) { 03229 if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) 03230 { 03231 int totpoint = pid->totpoint(pid->calldata, 0); 03232 03233 if(cache->totpoint > totpoint) 03234 BLI_snprintf(mem_info, sizeof(mem_info), "%i cells + High Resolution cached", totpoint); 03235 else 03236 BLI_snprintf(mem_info, sizeof(mem_info), "%i cells cached", totpoint); 03237 } 03238 else { 03239 int cfra = cache->startframe; 03240 03241 for(; cfra<=cache->endframe; cfra++) { 03242 if(BKE_ptcache_id_exist(pid, cfra)) 03243 totframes++; 03244 } 03245 03246 BLI_snprintf(mem_info, sizeof(mem_info), "%i frames on disk", totframes); 03247 } 03248 } 03249 else { 03250 PTCacheMem *pm = cache->mem_cache.first; 03251 float bytes = 0.0f; 03252 int i, mb; 03253 03254 for(; pm; pm=pm->next) { 03255 for(i=0; i<BPHYS_TOT_DATA; i++) 03256 bytes += MEM_allocN_len(pm->data[i]); 03257 03258 for(extra=pm->extradata.first; extra; extra=extra->next) { 03259 bytes += MEM_allocN_len(extra->data); 03260 bytes += sizeof(PTCacheExtra); 03261 } 03262 03263 bytes += sizeof(PTCacheMem); 03264 03265 totframes++; 03266 } 03267 03268 mb = (bytes > 1024.0f * 1024.0f); 03269 03270 BLI_snprintf(mem_info, sizeof(mem_info), "%i frames in memory (%.1f %s)", 03271 totframes, 03272 bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), 03273 mb ? "Mb" : "kb"); 03274 } 03275 03276 if(cache->flag & PTCACHE_OUTDATED) { 03277 BLI_snprintf(cache->info, sizeof(cache->info), "%s, cache is outdated!", mem_info); 03278 } 03279 else if(cache->flag & PTCACHE_FRAMES_SKIPPED) { 03280 BLI_snprintf(cache->info, sizeof(cache->info), "%s, not exact since frame %i.", mem_info, cache->last_exact); 03281 } 03282 else { 03283 BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info); 03284 } 03285 } 03286 03287 void BKE_ptcache_validate(PointCache *cache, int framenr) 03288 { 03289 if(cache) { 03290 cache->flag |= PTCACHE_SIMULATION_VALID; 03291 cache->simframe = framenr; 03292 } 03293 } 03294 void BKE_ptcache_invalidate(PointCache *cache) 03295 { 03296 if(cache) { 03297 cache->flag &= ~PTCACHE_SIMULATION_VALID; 03298 cache->simframe = 0; 03299 cache->last_exact = MIN2(cache->startframe, 0); 03300 } 03301 } 03302