|
Blender
V2.59
|
00001 /* 00002 * $Id: pointcache.c 38372 2011-07-13 18:40:21Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * Contributor(s): Campbell Barton <ideasman42@gmail.com> 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdlib.h> 00034 #include <stdio.h> 00035 #include <string.h> 00036 #include <sys/stat.h> 00037 #include <sys/types.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "DNA_ID.h" 00042 #include "DNA_cloth_types.h" 00043 #include "DNA_modifier_types.h" 00044 #include "DNA_object_types.h" 00045 #include "DNA_object_force.h" 00046 #include "DNA_particle_types.h" 00047 #include "DNA_scene_types.h" 00048 #include "DNA_smoke_types.h" 00049 00050 #include "BLI_blenlib.h" 00051 #include "BLI_threads.h" 00052 #include "BLI_math.h" 00053 #include "BLI_utildefines.h" 00054 00055 #include "PIL_time.h" 00056 00057 #include "WM_api.h" 00058 00059 #include "BKE_anim.h" 00060 #include "BKE_blender.h" 00061 #include "BKE_cloth.h" 00062 #include "BKE_depsgraph.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, 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 VECCOPY(keys[1].co, bp->pos); 00189 VECCOPY(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 VECCOPY(bp->pos, keys->co); 00208 VECCOPY(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 VECCOPY(keys[1].co, vert->x); 00489 VECCOPY(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 VECCOPY(vert->x, keys->co); 00508 VECCOPY(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 void 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 #else // WITH_SMOKE 00657 static int ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; }; 00658 static void ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) {} 00659 static int ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; } 00660 #endif // WITH_SMOKE 00661 00662 /* Creating ID's */ 00663 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) 00664 { 00665 memset(pid, 0, sizeof(PTCacheID)); 00666 00667 pid->ob= ob; 00668 pid->calldata= sb; 00669 pid->type= PTCACHE_TYPE_SOFTBODY; 00670 pid->cache= sb->pointcache; 00671 pid->cache_ptr= &sb->pointcache; 00672 pid->ptcaches= &sb->ptcaches; 00673 pid->totpoint= pid->totwrite= ptcache_softbody_totpoint; 00674 00675 pid->write_point = ptcache_softbody_write; 00676 pid->read_point = ptcache_softbody_read; 00677 pid->interpolate_point = ptcache_softbody_interpolate; 00678 00679 pid->write_stream = NULL; 00680 pid->read_stream = NULL; 00681 00682 pid->write_extra_data = NULL; 00683 pid->read_extra_data = NULL; 00684 pid->interpolate_extra_data = NULL; 00685 00686 pid->write_header = ptcache_basic_header_write; 00687 pid->read_header = ptcache_basic_header_read; 00688 00689 pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); 00690 pid->info_types= 0; 00691 00692 pid->stack_index = pid->cache->index; 00693 } 00694 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) 00695 { 00696 memset(pid, 0, sizeof(PTCacheID)); 00697 00698 pid->ob= ob; 00699 pid->calldata= psys; 00700 pid->type= PTCACHE_TYPE_PARTICLES; 00701 pid->stack_index= psys->pointcache->index; 00702 pid->cache= psys->pointcache; 00703 pid->cache_ptr= &psys->pointcache; 00704 pid->ptcaches= &psys->ptcaches; 00705 00706 if(psys->part->type != PART_HAIR) 00707 pid->flag |= PTCACHE_VEL_PER_SEC; 00708 00709 pid->totpoint = ptcache_particle_totpoint; 00710 pid->totwrite = ptcache_particle_totwrite; 00711 00712 pid->write_point = ptcache_particle_write; 00713 pid->read_point = ptcache_particle_read; 00714 pid->interpolate_point = ptcache_particle_interpolate; 00715 00716 pid->write_stream = NULL; 00717 pid->read_stream = NULL; 00718 00719 pid->write_extra_data = NULL; 00720 pid->read_extra_data = NULL; 00721 pid->interpolate_extra_data = NULL; 00722 00723 pid->write_header = ptcache_basic_header_write; 00724 pid->read_header = ptcache_basic_header_read; 00725 00726 pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX); 00727 00728 if(psys->part->phystype == PART_PHYS_BOIDS) 00729 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS); 00730 else if(psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) { 00731 pid->write_extra_data = ptcache_particle_extra_write; 00732 pid->read_extra_data = ptcache_particle_extra_read; 00733 } 00734 00735 if(psys->part->rotmode!=PART_ROT_VEL 00736 || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) 00737 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION); 00738 00739 if(psys->part->flag & PART_ROT_DYN) 00740 pid->data_types|= (1<<BPHYS_DATA_ROTATION); 00741 00742 pid->info_types= (1<<BPHYS_DATA_TIMES); 00743 } 00744 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd) 00745 { 00746 memset(pid, 0, sizeof(PTCacheID)); 00747 00748 pid->ob= ob; 00749 pid->calldata= clmd; 00750 pid->type= PTCACHE_TYPE_CLOTH; 00751 pid->stack_index= clmd->point_cache->index; 00752 pid->cache= clmd->point_cache; 00753 pid->cache_ptr= &clmd->point_cache; 00754 pid->ptcaches= &clmd->ptcaches; 00755 pid->totpoint= pid->totwrite= ptcache_cloth_totpoint; 00756 00757 pid->write_point = ptcache_cloth_write; 00758 pid->read_point = ptcache_cloth_read; 00759 pid->interpolate_point = ptcache_cloth_interpolate; 00760 00761 pid->write_stream = NULL; 00762 pid->read_stream = NULL; 00763 00764 pid->write_extra_data = NULL; 00765 pid->read_extra_data = NULL; 00766 pid->interpolate_extra_data = NULL; 00767 00768 pid->write_header = ptcache_basic_header_write; 00769 pid->read_header = ptcache_basic_header_read; 00770 00771 pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST); 00772 pid->info_types= 0; 00773 } 00774 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) 00775 { 00776 SmokeDomainSettings *sds = smd->domain; 00777 00778 memset(pid, 0, sizeof(PTCacheID)); 00779 00780 pid->ob= ob; 00781 pid->calldata= smd; 00782 00783 pid->type= PTCACHE_TYPE_SMOKE_DOMAIN; 00784 pid->stack_index= sds->point_cache[0]->index; 00785 00786 pid->cache= sds->point_cache[0]; 00787 pid->cache_ptr= &(sds->point_cache[0]); 00788 pid->ptcaches= &(sds->ptcaches[0]); 00789 00790 pid->totpoint= pid->totwrite= ptcache_smoke_totpoint; 00791 00792 pid->write_point = NULL; 00793 pid->read_point = NULL; 00794 pid->interpolate_point = NULL; 00795 00796 pid->read_stream = ptcache_smoke_read; 00797 pid->write_stream = ptcache_smoke_write; 00798 00799 pid->write_extra_data = NULL; 00800 pid->read_extra_data = NULL; 00801 pid->interpolate_extra_data = NULL; 00802 00803 pid->write_header = ptcache_basic_header_write; 00804 pid->read_header = ptcache_basic_header_read; 00805 00806 pid->data_types= 0; 00807 pid->info_types= 0; 00808 00809 if(sds->fluid) 00810 pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW); 00811 if(sds->wt) 00812 pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH); 00813 } 00814 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) 00815 { 00816 PTCacheID *pid; 00817 ParticleSystem *psys; 00818 ModifierData *md; 00819 00820 lb->first= lb->last= NULL; 00821 00822 if(ob->soft) { 00823 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 00824 BKE_ptcache_id_from_softbody(pid, ob, ob->soft); 00825 BLI_addtail(lb, pid); 00826 } 00827 00828 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 00829 if(psys->part==NULL) 00830 continue; 00831 00832 /* check to make sure point cache is actually used by the particles */ 00833 if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) 00834 continue; 00835 00836 /* hair needs to be included in id-list for cache edit mode to work */ 00837 /* if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */ 00838 /* continue; */ 00839 00840 if(psys->part->type == PART_FLUID) 00841 continue; 00842 00843 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 00844 BKE_ptcache_id_from_particles(pid, ob, psys); 00845 BLI_addtail(lb, pid); 00846 } 00847 00848 for(md=ob->modifiers.first; md; md=md->next) { 00849 if(md->type == eModifierType_Cloth) { 00850 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 00851 BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md); 00852 BLI_addtail(lb, pid); 00853 } 00854 if(md->type == eModifierType_Smoke) { 00855 SmokeModifierData *smd = (SmokeModifierData *)md; 00856 if(smd->type & MOD_SMOKE_TYPE_DOMAIN) 00857 { 00858 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); 00859 BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md); 00860 BLI_addtail(lb, pid); 00861 } 00862 } 00863 } 00864 00865 if(scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) { 00866 ListBase *lb_dupli_ob; 00867 00868 if((lb_dupli_ob=object_duplilist(scene, ob))) { 00869 DupliObject *dob; 00870 for(dob= lb_dupli_ob->first; dob; dob= dob->next) { 00871 if(dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */ 00872 ListBase lb_dupli_pid; 00873 BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis); 00874 BLI_movelisttolist(lb, &lb_dupli_pid); 00875 if(lb_dupli_pid.first) 00876 printf("Adding Dupli\n"); 00877 } 00878 } 00879 00880 free_object_duplilist(lb_dupli_ob); /* does restore */ 00881 } 00882 } 00883 } 00884 00885 /* File handling */ 00886 00887 /* Takes an Object ID and returns a unique name 00888 - id: object id 00889 - cfra: frame for the cache, can be negative 00890 - stack_index: index in the modifier stack. we can have cache for more then one stack_index 00891 */ 00892 00893 #define MAX_PTCACHE_PATH FILE_MAX 00894 #define MAX_PTCACHE_FILE ((FILE_MAXDIR+FILE_MAXFILE)*2) 00895 00896 static int ptcache_path(PTCacheID *pid, char *filename) 00897 { 00898 Library *lib= (pid->ob)? pid->ob->id.lib: NULL; 00899 const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name; 00900 size_t i; 00901 00902 if(pid->cache->flag & PTCACHE_EXTERNAL) { 00903 strcpy(filename, pid->cache->path); 00904 00905 if(strncmp(filename, "//", 2)==0) 00906 BLI_path_abs(filename, blendfilename); 00907 00908 return BLI_add_slash(filename); /* new strlen() */ 00909 } 00910 else if (G.relbase_valid || lib) { 00911 char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */ 00912 00913 BLI_split_dirfile(blendfilename, NULL, file); 00914 i = strlen(file); 00915 00916 /* remove .blend */ 00917 if (i > 6) 00918 file[i-6] = '\0'; 00919 00920 snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */ 00921 BLI_path_abs(filename, blendfilename); 00922 return BLI_add_slash(filename); /* new strlen() */ 00923 } 00924 00925 /* use the temp path. this is weak but better then not using point cache at all */ 00926 /* btempdir is assumed to exist and ALWAYS has a trailing slash */ 00927 snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", btempdir, abs(getpid())); 00928 00929 return BLI_add_slash(filename); /* new strlen() */ 00930 } 00931 00932 static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext) 00933 { 00934 int len=0; 00935 char *idname; 00936 char *newname; 00937 filename[0] = '\0'; 00938 newname = filename; 00939 00940 if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */ 00941 00942 /* start with temp dir */ 00943 if (do_path) { 00944 len = ptcache_path(pid, filename); 00945 newname += len; 00946 } 00947 if(pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) { 00948 idname = (pid->ob->id.name+2); 00949 /* convert chars to hex so they are always a valid filename */ 00950 while('\0' != *idname) { 00951 snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++)); 00952 newname+=2; 00953 len += 2; 00954 } 00955 } 00956 else { 00957 int temp = (int)strlen(pid->cache->name); 00958 strcpy(newname, pid->cache->name); 00959 newname+=temp; 00960 len += temp; 00961 } 00962 00963 if (do_ext) { 00964 00965 if(pid->cache->index < 0) 00966 pid->cache->index = pid->stack_index = object_insert_ptcache(pid->ob); 00967 00968 if(pid->cache->flag & PTCACHE_EXTERNAL) { 00969 if(pid->cache->index >= 0) 00970 snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */ 00971 else 00972 snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */ 00973 } 00974 else { 00975 snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */ 00976 } 00977 len += 16; 00978 } 00979 00980 return len; /* make sure the above string is always 16 chars */ 00981 } 00982 00983 /* youll need to close yourself after! */ 00984 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) 00985 { 00986 PTCacheFile *pf; 00987 FILE *fp = NULL; 00988 char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; 00989 00990 #ifndef DURIAN_POINTCACHE_LIB_OK 00991 /* don't allow writing for linked objects */ 00992 if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE) 00993 return NULL; 00994 #endif 00995 if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */ 00996 00997 ptcache_filename(pid, filename, cfra, 1, 1); 00998 00999 if (mode==PTCACHE_FILE_READ) { 01000 if (!BLI_exists(filename)) { 01001 return NULL; 01002 } 01003 fp = fopen(filename, "rb"); 01004 } else if (mode==PTCACHE_FILE_WRITE) { 01005 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */ 01006 fp = fopen(filename, "wb"); 01007 } else if (mode==PTCACHE_FILE_UPDATE) { 01008 BLI_make_existing_file(filename); 01009 fp = fopen(filename, "rb+"); 01010 } 01011 01012 if (!fp) 01013 return NULL; 01014 01015 pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile"); 01016 pf->fp= fp; 01017 pf->old_format = 0; 01018 pf->frame = cfra; 01019 01020 return pf; 01021 } 01022 static void ptcache_file_close(PTCacheFile *pf) 01023 { 01024 if(pf) { 01025 fclose(pf->fp); 01026 MEM_freeN(pf); 01027 } 01028 } 01029 01030 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len) 01031 { 01032 int r = 0; 01033 unsigned char compressed = 0; 01034 size_t in_len; 01035 #ifdef WITH_LZO 01036 size_t out_len = len; 01037 #endif 01038 unsigned char *in; 01039 unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); 01040 01041 ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); 01042 if(compressed) { 01043 unsigned int size; 01044 ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); 01045 in_len = (size_t)size; 01046 if(in_len==0) { 01047 /* do nothing */ 01048 } 01049 else { 01050 in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); 01051 ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); 01052 #ifdef WITH_LZO 01053 if(compressed == 1) 01054 r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); 01055 #endif 01056 #ifdef WITH_LZMA 01057 if(compressed == 2) 01058 { 01059 size_t sizeOfIt; 01060 size_t leni = in_len, leno = out_len; 01061 ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); 01062 sizeOfIt = (size_t)size; 01063 ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); 01064 r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); 01065 } 01066 #endif 01067 MEM_freeN(in); 01068 } 01069 } 01070 else { 01071 ptcache_file_read(pf, result, len, sizeof(unsigned char)); 01072 } 01073 01074 MEM_freeN(props); 01075 01076 return r; 01077 } 01078 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) 01079 { 01080 int r = 0; 01081 unsigned char compressed = 0; 01082 size_t out_len= 0; 01083 unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); 01084 size_t sizeOfIt = 5; 01085 01086 (void)mode; /* unused when building w/o compression */ 01087 01088 #ifdef WITH_LZO 01089 out_len= LZO_OUT_LEN(in_len); 01090 if(mode == 1) { 01091 LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); 01092 01093 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); 01094 if (!(r == LZO_E_OK) || (out_len >= in_len)) 01095 compressed = 0; 01096 else 01097 compressed = 1; 01098 } 01099 #endif 01100 #ifdef WITH_LZMA 01101 if(mode == 2) { 01102 01103 r = LzmaCompress(out, &out_len, in, in_len,//assume sizeof(char)==1.... 01104 props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); 01105 01106 if(!(r == SZ_OK) || (out_len >= in_len)) 01107 compressed = 0; 01108 else 01109 compressed = 2; 01110 } 01111 #endif 01112 01113 ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); 01114 if(compressed) { 01115 unsigned int size = out_len; 01116 ptcache_file_write(pf, &size, 1, sizeof(unsigned int)); 01117 ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); 01118 } 01119 else 01120 ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); 01121 01122 if(compressed == 2) 01123 { 01124 unsigned int size = sizeOfIt; 01125 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int)); 01126 ptcache_file_write(pf, props, size, sizeof(unsigned char)); 01127 } 01128 01129 MEM_freeN(props); 01130 01131 return r; 01132 } 01133 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size) 01134 { 01135 return (fread(f, size, tot, pf->fp) == tot); 01136 } 01137 static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size) 01138 { 01139 return (fwrite(f, size, tot, pf->fp) == tot); 01140 } 01141 static int ptcache_file_data_read(PTCacheFile *pf) 01142 { 01143 int i; 01144 01145 for(i=0; i<BPHYS_TOT_DATA; i++) { 01146 if((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) 01147 return 0; 01148 } 01149 01150 return 1; 01151 } 01152 static int ptcache_file_data_write(PTCacheFile *pf) 01153 { 01154 int i; 01155 01156 for(i=0; i<BPHYS_TOT_DATA; i++) { 01157 if((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) 01158 return 0; 01159 } 01160 01161 return 1; 01162 } 01163 static int ptcache_file_header_begin_read(PTCacheFile *pf) 01164 { 01165 unsigned int typeflag=0; 01166 int error=0; 01167 char bphysics[8]; 01168 01169 pf->data_types = 0; 01170 01171 if(fread(bphysics, sizeof(char), 8, pf->fp) != 8) 01172 error = 1; 01173 01174 if(!error && strncmp(bphysics, "BPHYSICS", 8)) 01175 error = 1; 01176 01177 if(!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp)) 01178 error = 1; 01179 01180 pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK); 01181 pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK); 01182 01183 /* if there was an error set file as it was */ 01184 if(error) 01185 fseek(pf->fp, 0, SEEK_SET); 01186 01187 return !error; 01188 } 01189 static int ptcache_file_header_begin_write(PTCacheFile *pf) 01190 { 01191 const char *bphysics = "BPHYSICS"; 01192 unsigned int typeflag = pf->type + pf->flag; 01193 01194 if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) 01195 return 0; 01196 01197 if(!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp)) 01198 return 0; 01199 01200 return 1; 01201 } 01202 01203 /* Data pointer handling */ 01204 int BKE_ptcache_data_size(int data_type) 01205 { 01206 return ptcache_data_size[data_type]; 01207 } 01208 01209 static void ptcache_file_pointers_init(PTCacheFile *pf) 01210 { 01211 int data_types = pf->data_types; 01212 01213 pf->cur[BPHYS_DATA_INDEX] = (data_types & (1<<BPHYS_DATA_INDEX)) ? &pf->data.index : NULL; 01214 pf->cur[BPHYS_DATA_LOCATION] = (data_types & (1<<BPHYS_DATA_LOCATION)) ? &pf->data.loc : NULL; 01215 pf->cur[BPHYS_DATA_VELOCITY] = (data_types & (1<<BPHYS_DATA_VELOCITY)) ? &pf->data.vel : NULL; 01216 pf->cur[BPHYS_DATA_ROTATION] = (data_types & (1<<BPHYS_DATA_ROTATION)) ? &pf->data.rot : NULL; 01217 pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))? &pf->data.ave : NULL; 01218 pf->cur[BPHYS_DATA_SIZE] = (data_types & (1<<BPHYS_DATA_SIZE)) ? &pf->data.size : NULL; 01219 pf->cur[BPHYS_DATA_TIMES] = (data_types & (1<<BPHYS_DATA_TIMES)) ? &pf->data.times : NULL; 01220 pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1<<BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL; 01221 } 01222 01223 /* Check to see if point number "index" is in pm, uses binary search for index data. */ 01224 int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index) 01225 { 01226 if(pm->data[BPHYS_DATA_INDEX]) { 01227 unsigned int *data = pm->data[BPHYS_DATA_INDEX]; 01228 unsigned int mid, low = 0, high = pm->totpoint - 1; 01229 01230 if(index < *data || index > *(data+high)) 01231 return -1; 01232 01233 /* check simple case for continuous indexes first */ 01234 if(index-*data < high && data[index-*data] == index) 01235 return index-*data; 01236 01237 while(low <= high) { 01238 mid= (low + high)/2; 01239 01240 if(data[mid] > index) 01241 high = mid - 1; 01242 else if(data[mid] < index) 01243 low = mid + 1; 01244 else 01245 return mid; 01246 } 01247 01248 return -1; 01249 } 01250 else { 01251 return (index < pm->totpoint ? index : -1); 01252 } 01253 } 01254 01255 void BKE_ptcache_mem_pointers_init(PTCacheMem *pm) 01256 { 01257 int data_types = pm->data_types; 01258 int i; 01259 01260 for(i=0; i<BPHYS_TOT_DATA; i++) 01261 pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL); 01262 } 01263 01264 void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm) 01265 { 01266 int i; 01267 01268 for(i=0; i<BPHYS_TOT_DATA; i++) { 01269 if(pm->cur[i]) 01270 pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; 01271 } 01272 } 01273 int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm) 01274 { 01275 int data_types = pm->data_types; 01276 int i, index = BKE_ptcache_mem_index_find(pm, point_index); 01277 01278 if(index < 0) { 01279 /* Can't give proper location without reallocation, so don't give any location. 01280 * Some points will be cached improperly, but this only happens with simulation 01281 * steps bigger than cache->step, so the cache has to be recalculated anyways 01282 * at some point. 01283 */ 01284 return 0; 01285 } 01286 01287 for(i=0; i<BPHYS_TOT_DATA; i++) 01288 pm->cur[i] = data_types & (1<<i) ? (char*)pm->data[i] + index * ptcache_data_size[i] : NULL; 01289 01290 return 1; 01291 } 01292 static void ptcache_data_alloc(PTCacheMem *pm) 01293 { 01294 int data_types = pm->data_types; 01295 int totpoint = pm->totpoint; 01296 int i; 01297 01298 for(i=0; i<BPHYS_TOT_DATA; i++) { 01299 if(data_types & (1<<i)) 01300 pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data"); 01301 } 01302 } 01303 static void ptcache_data_free(PTCacheMem *pm) 01304 { 01305 void **data = pm->data; 01306 int i; 01307 01308 for(i=0; i<BPHYS_TOT_DATA; i++) { 01309 if(data[i]) 01310 MEM_freeN(data[i]); 01311 } 01312 } 01313 static void ptcache_data_copy(void *from[], void *to[]) 01314 { 01315 int i; 01316 for(i=0; i<BPHYS_TOT_DATA; i++) { 01317 /* note, durian file 03.4b_comp crashes if to[i] is not tested 01318 * its NULL, not sure if this should be fixed elsewhere but for now its needed */ 01319 if(from[i] && to[i]) 01320 memcpy(to[i], from[i], ptcache_data_size[i]); 01321 } 01322 } 01323 01324 static void ptcache_extra_free(PTCacheMem *pm) 01325 { 01326 PTCacheExtra *extra = pm->extradata.first; 01327 01328 if(extra) { 01329 for(; extra; extra=extra->next) { 01330 if(extra->data) 01331 MEM_freeN(extra->data); 01332 } 01333 01334 BLI_freelistN(&pm->extradata); 01335 } 01336 } 01337 static int ptcache_old_elemsize(PTCacheID *pid) 01338 { 01339 if(pid->type==PTCACHE_TYPE_SOFTBODY) 01340 return 6 * sizeof(float); 01341 else if(pid->type==PTCACHE_TYPE_PARTICLES) 01342 return sizeof(ParticleKey); 01343 else if(pid->type==PTCACHE_TYPE_CLOTH) 01344 return 9 * sizeof(float); 01345 01346 return 0; 01347 } 01348 01349 static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2) 01350 { 01351 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01352 int cfra1=frame-1, cfra2=frame+1; 01353 01354 while(cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) 01355 cfra1--; 01356 01357 if(cfra1 < pid->cache->startframe) 01358 cfra1 = 0; 01359 01360 while(cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) 01361 cfra2++; 01362 01363 if(cfra2 > pid->cache->endframe) 01364 cfra2 = 0; 01365 01366 if(cfra1 && !cfra2) { 01367 *fra1 = 0; 01368 *fra2 = cfra1; 01369 } 01370 else { 01371 *fra1 = cfra1; 01372 *fra2 = cfra2; 01373 } 01374 } 01375 else if(pid->cache->mem_cache.first) { 01376 PTCacheMem *pm = pid->cache->mem_cache.first; 01377 PTCacheMem *pm2 = pid->cache->mem_cache.last; 01378 01379 while(pm->next && pm->next->frame < frame) 01380 pm= pm->next; 01381 01382 if(pm2->frame < frame) { 01383 pm2 = NULL; 01384 } 01385 else { 01386 while(pm2->prev && pm2->prev->frame > frame) { 01387 pm2= pm2->prev; 01388 } 01389 } 01390 01391 if(!pm2) { 01392 *fra1 = 0; 01393 *fra2 = pm->frame; 01394 } 01395 else { 01396 *fra1 = pm->frame; 01397 *fra2 = pm2->frame; 01398 } 01399 } 01400 } 01401 01402 static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) 01403 { 01404 PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); 01405 PTCacheMem *pm = NULL; 01406 unsigned int i, error = 0; 01407 01408 if(pf == NULL) 01409 return NULL; 01410 01411 if(!ptcache_file_header_begin_read(pf)) 01412 error = 1; 01413 01414 if(!error && (pf->type != pid->type || !pid->read_header(pf))) 01415 error = 1; 01416 01417 if(!error) { 01418 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); 01419 01420 pm->totpoint = pf->totpoint; 01421 pm->data_types = pf->data_types; 01422 pm->frame = pf->frame; 01423 01424 ptcache_data_alloc(pm); 01425 01426 if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) { 01427 for(i=0; i<BPHYS_TOT_DATA; i++) { 01428 unsigned int out_len = pm->totpoint*ptcache_data_size[i]; 01429 if(pf->data_types & (1<<i)) 01430 ptcache_file_compressed_read(pf, (unsigned char*)(pm->data[i]), out_len); 01431 } 01432 } 01433 else { 01434 BKE_ptcache_mem_pointers_init(pm); 01435 ptcache_file_pointers_init(pf); 01436 01437 for(i=0; i<pm->totpoint; i++) { 01438 if(!ptcache_file_data_read(pf)) { 01439 error = 1; 01440 break; 01441 } 01442 ptcache_data_copy(pf->cur, pm->cur); 01443 BKE_ptcache_mem_pointers_incr(pm); 01444 } 01445 } 01446 } 01447 01448 if(!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) { 01449 unsigned int extratype = 0; 01450 01451 while(ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) { 01452 PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata"); 01453 01454 extra->type = extratype; 01455 01456 ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int)); 01457 01458 extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data"); 01459 01460 if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) 01461 ptcache_file_compressed_read(pf, (unsigned char*)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]); 01462 else 01463 ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); 01464 01465 BLI_addtail(&pm->extradata, extra); 01466 } 01467 } 01468 01469 if(error && pm) { 01470 ptcache_data_free(pm); 01471 ptcache_extra_free(pm); 01472 MEM_freeN(pm); 01473 pm = NULL; 01474 } 01475 01476 ptcache_file_close(pf); 01477 01478 if (error && G.f & G_DEBUG) 01479 printf("Error reading from disk cache\n"); 01480 01481 return pm; 01482 } 01483 static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm) 01484 { 01485 PTCacheFile *pf = NULL; 01486 unsigned int i, error = 0; 01487 01488 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame); 01489 01490 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); 01491 01492 if(pf==NULL) { 01493 if (G.f & G_DEBUG) 01494 printf("Error opening disk cache file for writing\n"); 01495 return 0; 01496 } 01497 01498 pf->data_types = pm->data_types; 01499 pf->totpoint = pm->totpoint; 01500 pf->type = pid->type; 01501 pf->flag = 0; 01502 01503 if(pm->extradata.first) 01504 pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA; 01505 01506 if(pid->cache->compression) 01507 pf->flag |= PTCACHE_TYPEFLAG_COMPRESS; 01508 01509 if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) 01510 error = 1; 01511 01512 if(!error) { 01513 if(pid->cache->compression) { 01514 for(i=0; i<BPHYS_TOT_DATA; i++) { 01515 if(pm->data[i]) { 01516 unsigned int in_len = pm->totpoint*ptcache_data_size[i]; 01517 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); 01518 ptcache_file_compressed_write(pf, (unsigned char*)(pm->data[i]), in_len, out, pid->cache->compression); 01519 MEM_freeN(out); 01520 } 01521 } 01522 } 01523 else { 01524 BKE_ptcache_mem_pointers_init(pm); 01525 ptcache_file_pointers_init(pf); 01526 01527 for(i=0; i<pm->totpoint; i++) { 01528 ptcache_data_copy(pm->cur, pf->cur); 01529 if(!ptcache_file_data_write(pf)) { 01530 error = 1; 01531 break; 01532 } 01533 BKE_ptcache_mem_pointers_incr(pm); 01534 } 01535 } 01536 } 01537 01538 if(!error && pm->extradata.first) { 01539 PTCacheExtra *extra = pm->extradata.first; 01540 01541 for(; extra; extra=extra->next) { 01542 if(extra->data == NULL || extra->totdata == 0) 01543 continue; 01544 01545 ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int)); 01546 ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int)); 01547 01548 if(pid->cache->compression) { 01549 unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type]; 01550 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); 01551 ptcache_file_compressed_write(pf, (unsigned char*)(extra->data), in_len, out, pid->cache->compression); 01552 MEM_freeN(out); 01553 } 01554 else { 01555 ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); 01556 } 01557 } 01558 } 01559 01560 ptcache_file_close(pf); 01561 01562 if (error && G.f & G_DEBUG) 01563 printf("Error writing to disk cache\n"); 01564 01565 return error==0; 01566 } 01567 01568 static int ptcache_read_stream(PTCacheID *pid, int cfra) 01569 { 01570 PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); 01571 int error = 0; 01572 01573 if(pid->read_stream == NULL) 01574 return 0; 01575 01576 if(pf == NULL) { 01577 if (G.f & G_DEBUG) 01578 printf("Error opening disk cache file for reading\n"); 01579 return 0; 01580 } 01581 01582 if(!ptcache_file_header_begin_read(pf)) 01583 error = 1; 01584 01585 if(!error && (pf->type != pid->type || !pid->read_header(pf))) 01586 error = 1; 01587 01588 if(!error && pf->totpoint != pid->totpoint(pid->calldata, cfra)) 01589 error = 1; 01590 01591 if(!error) { 01592 ptcache_file_pointers_init(pf); 01593 01594 // we have stream reading here 01595 pid->read_stream(pf, pid->calldata); 01596 } 01597 01598 ptcache_file_close(pf); 01599 01600 return error == 0; 01601 } 01602 static int ptcache_read(PTCacheID *pid, int cfra) 01603 { 01604 PTCacheMem *pm = NULL; 01605 int i; 01606 int *index = &i; 01607 01608 /* get a memory cache to read from */ 01609 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01610 pm = ptcache_disk_frame_to_mem(pid, cfra); 01611 } 01612 else { 01613 pm = pid->cache->mem_cache.first; 01614 01615 while(pm && pm->frame != cfra) 01616 pm = pm->next; 01617 } 01618 01619 /* read the cache */ 01620 if(pm) { 01621 int totpoint = pm->totpoint; 01622 01623 if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) 01624 totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra)); 01625 01626 BKE_ptcache_mem_pointers_init(pm); 01627 01628 for(i=0; i<totpoint; i++) { 01629 if(pm->data_types & (1<<BPHYS_DATA_INDEX)) 01630 index = pm->cur[BPHYS_DATA_INDEX]; 01631 01632 pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL); 01633 01634 BKE_ptcache_mem_pointers_incr(pm); 01635 } 01636 01637 if(pid->read_extra_data && pm->extradata.first) 01638 pid->read_extra_data(pid->calldata, pm, (float)pm->frame); 01639 01640 /* clean up temporary memory cache */ 01641 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01642 ptcache_data_free(pm); 01643 ptcache_extra_free(pm); 01644 MEM_freeN(pm); 01645 } 01646 } 01647 01648 return 1; 01649 } 01650 static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) 01651 { 01652 PTCacheMem *pm = NULL; 01653 int i; 01654 int *index = &i; 01655 01656 /* get a memory cache to read from */ 01657 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01658 pm = ptcache_disk_frame_to_mem(pid, cfra2); 01659 } 01660 else { 01661 pm = pid->cache->mem_cache.first; 01662 01663 while(pm && pm->frame != cfra2) 01664 pm = pm->next; 01665 } 01666 01667 /* read the cache */ 01668 if(pm) { 01669 int totpoint = pm->totpoint; 01670 01671 if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) 01672 totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra)); 01673 01674 BKE_ptcache_mem_pointers_init(pm); 01675 01676 for(i=0; i<totpoint; i++) { 01677 if(pm->data_types & (1<<BPHYS_DATA_INDEX)) 01678 index = pm->cur[BPHYS_DATA_INDEX]; 01679 01680 pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL); 01681 BKE_ptcache_mem_pointers_incr(pm); 01682 } 01683 01684 if(pid->interpolate_extra_data && pm->extradata.first) 01685 pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2); 01686 01687 /* clean up temporary memory cache */ 01688 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01689 ptcache_data_free(pm); 01690 ptcache_extra_free(pm); 01691 MEM_freeN(pm); 01692 } 01693 } 01694 01695 return 1; 01696 } 01697 /* reads cache from disk or memory */ 01698 /* possible to get old or interpolated result */ 01699 int BKE_ptcache_read(PTCacheID *pid, float cfra) 01700 { 01701 int cfrai = (int)cfra, cfra1=0, cfra2=0; 01702 int ret = 0; 01703 01704 /* nothing to read to */ 01705 if(pid->totpoint(pid->calldata, cfrai) == 0) 01706 return 0; 01707 01708 if(pid->cache->flag & PTCACHE_READ_INFO) { 01709 pid->cache->flag &= ~PTCACHE_READ_INFO; 01710 ptcache_read(pid, 0); 01711 } 01712 01713 /* first check if we have the actual frame cached */ 01714 if(cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai)) 01715 cfra1 = cfrai; 01716 01717 /* no exact cache frame found so try to find cached frames around cfra */ 01718 if(cfra1 == 0) 01719 ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2); 01720 01721 if(cfra1 == 0 && cfra2 == 0) 01722 return 0; 01723 01724 /* don't read old cache if already simulated past cached frame */ 01725 if(cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) 01726 return 0; 01727 if(cfra1 && cfra1 == cfra2) 01728 return 0; 01729 01730 if(cfra1) { 01731 if(pid->read_stream) 01732 ptcache_read_stream(pid, cfra1); 01733 else if(pid->read_point) 01734 ptcache_read(pid, cfra1); 01735 } 01736 01737 if(cfra2) { 01738 if(pid->read_stream) 01739 ptcache_read_stream(pid, cfra2); 01740 else if(pid->read_point) { 01741 if(cfra1 && cfra2 && pid->interpolate_point) 01742 ptcache_interpolate(pid, cfra, cfra1, cfra2); 01743 else 01744 ptcache_read(pid, cfra2); 01745 } 01746 } 01747 01748 if(cfra1) 01749 ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT); 01750 else if(cfra2) { 01751 ret = PTCACHE_READ_OLD; 01752 pid->cache->simframe = cfra2; 01753 } 01754 01755 if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) { 01756 cfrai = (int)cfra; 01757 /* clear invalid cache frames so that better stuff can be simulated */ 01758 if(pid->cache->flag & PTCACHE_OUTDATED) { 01759 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai); 01760 } 01761 else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) { 01762 if(cfra <= pid->cache->last_exact) 01763 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; 01764 01765 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact)); 01766 } 01767 } 01768 01769 return ret; 01770 } 01771 static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint) 01772 { 01773 PTCacheFile *pf = NULL; 01774 int error = 0; 01775 01776 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra); 01777 01778 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); 01779 01780 if(pf==NULL) { 01781 if (G.f & G_DEBUG) 01782 printf("Error opening disk cache file for writing\n"); 01783 return 0; 01784 } 01785 01786 pf->data_types = pid->data_types; 01787 pf->totpoint = totpoint; 01788 pf->type = pid->type; 01789 pf->flag = 0; 01790 01791 if(!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))) 01792 error = 1; 01793 01794 if(!error && pid->write_stream) 01795 pid->write_stream(pf, pid->calldata); 01796 01797 ptcache_file_close(pf); 01798 01799 if (error && G.f & G_DEBUG) 01800 printf("Error writing to disk cache\n"); 01801 01802 return error == 0; 01803 } 01804 static int ptcache_write(PTCacheID *pid, int cfra, int overwrite) 01805 { 01806 PointCache *cache = pid->cache; 01807 PTCacheMem *pm=NULL, *pm2=NULL; 01808 int totpoint = pid->totpoint(pid->calldata, cfra); 01809 int i, error = 0; 01810 01811 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); 01812 01813 pm->totpoint = pid->totwrite(pid->calldata, cfra); 01814 pm->data_types = cfra ? pid->data_types : pid->info_types; 01815 01816 ptcache_data_alloc(pm); 01817 BKE_ptcache_mem_pointers_init(pm); 01818 01819 if(overwrite) { 01820 if(cache->flag & PTCACHE_DISK_CACHE) { 01821 int fra = cfra-1; 01822 01823 while(fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra)) 01824 fra--; 01825 01826 pm2 = ptcache_disk_frame_to_mem(pid, fra); 01827 } 01828 else 01829 pm2 = cache->mem_cache.last; 01830 } 01831 01832 if(pid->write_point) { 01833 for(i=0; i<totpoint; i++) { 01834 int write = pid->write_point(i, pid->calldata, pm->cur, cfra); 01835 if(write) { 01836 BKE_ptcache_mem_pointers_incr(pm); 01837 01838 /* newly born particles have to be copied to previous cached frame */ 01839 if(overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2)) 01840 pid->write_point(i, pid->calldata, pm2->cur, cfra); 01841 } 01842 } 01843 } 01844 01845 if(pid->write_extra_data) 01846 pid->write_extra_data(pid->calldata, pm, cfra); 01847 01848 pm->frame = cfra; 01849 01850 if(cache->flag & PTCACHE_DISK_CACHE) { 01851 error += !ptcache_mem_frame_to_disk(pid, pm); 01852 01853 // if(pm) /* pm is always set */ 01854 { 01855 ptcache_data_free(pm); 01856 ptcache_extra_free(pm); 01857 MEM_freeN(pm); 01858 } 01859 01860 if(pm2) { 01861 error += !ptcache_mem_frame_to_disk(pid, pm2); 01862 ptcache_data_free(pm2); 01863 ptcache_extra_free(pm2); 01864 MEM_freeN(pm2); 01865 } 01866 } 01867 else { 01868 BLI_addtail(&cache->mem_cache, pm); 01869 } 01870 01871 return error; 01872 } 01873 static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite) 01874 { 01875 PointCache *cache = pid->cache; 01876 int ofra = 0, efra = cache->endframe; 01877 01878 /* allways start from scratch on the first frame */ 01879 if(cfra && cfra == cache->startframe) { 01880 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); 01881 cache->flag &= ~PTCACHE_REDO_NEEDED; 01882 return 1; 01883 } 01884 01885 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01886 if(cfra==0 && cache->startframe > 0) 01887 return 1; 01888 01889 /* find last cached frame */ 01890 while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) 01891 efra--; 01892 01893 /* find second last cached frame */ 01894 ofra = efra-1; 01895 while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) 01896 ofra--; 01897 } 01898 else { 01899 PTCacheMem *pm = cache->mem_cache.last; 01900 /* don't write info file in memory */ 01901 if(cfra == 0) 01902 return 0; 01903 01904 if(pm == NULL) 01905 return 1; 01906 01907 efra = pm->frame; 01908 ofra = (pm->prev ? pm->prev->frame : efra - cache->step); 01909 } 01910 01911 if(efra >= cache->startframe && cfra > efra) { 01912 if(ofra >= cache->startframe && efra - ofra < cache->step) { 01913 /* overwrite previous frame */ 01914 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra); 01915 *overwrite = 1; 01916 } 01917 return 1; 01918 } 01919 01920 return 0; 01921 } 01922 /* writes cache to disk or memory */ 01923 int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra) 01924 { 01925 PointCache *cache = pid->cache; 01926 int totpoint = pid->totpoint(pid->calldata, cfra); 01927 int overwrite = 0, error = 0; 01928 01929 if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) 01930 return 0; 01931 01932 if(ptcache_write_needed(pid, cfra, &overwrite)==0) 01933 return 0; 01934 01935 if(pid->write_stream) { 01936 ptcache_write_stream(pid, cfra, totpoint); 01937 } 01938 else if(pid->write_point) { 01939 error += ptcache_write(pid, cfra, overwrite); 01940 } 01941 01942 /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */ 01943 if(cfra - cache->last_exact == 1 || cfra == cache->startframe) { 01944 cache->last_exact = cfra; 01945 cache->flag &= ~PTCACHE_FRAMES_SKIPPED; 01946 } 01947 /* Don't mark skipped when writing info file (frame 0) */ 01948 else if(cfra) 01949 cache->flag |= PTCACHE_FRAMES_SKIPPED; 01950 01951 /* Update timeline cache display */ 01952 if(cfra && cache->cached_frames) 01953 cache->cached_frames[cfra-cache->startframe] = 1; 01954 01955 BKE_ptcache_update_info(pid); 01956 01957 return !error; 01958 } 01959 /* youll need to close yourself after! 01960 * mode - PTCACHE_CLEAR_ALL, 01961 01962 */ 01963 /* Clears & resets */ 01964 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) 01965 { 01966 unsigned int len; /* store the length of the string */ 01967 unsigned int sta, end; 01968 01969 /* mode is same as fopen's modes */ 01970 DIR *dir; 01971 struct dirent *de; 01972 char path[MAX_PTCACHE_PATH]; 01973 char filename[MAX_PTCACHE_FILE]; 01974 char path_full[MAX_PTCACHE_FILE]; 01975 char ext[MAX_PTCACHE_PATH]; 01976 01977 if(!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) 01978 return; 01979 01980 sta = pid->cache->startframe; 01981 end = pid->cache->endframe; 01982 01983 #ifndef DURIAN_POINTCACHE_LIB_OK 01984 /* don't allow clearing for linked objects */ 01985 if(pid->ob->id.lib) 01986 return; 01987 #endif 01988 01989 /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */ 01990 01991 /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */ 01992 switch (mode) { 01993 case PTCACHE_CLEAR_ALL: 01994 case PTCACHE_CLEAR_BEFORE: 01995 case PTCACHE_CLEAR_AFTER: 01996 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 01997 ptcache_path(pid, path); 01998 01999 len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */ 02000 02001 dir = opendir(path); 02002 if (dir==NULL) 02003 return; 02004 02005 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); 02006 02007 while ((de = readdir(dir)) != NULL) { 02008 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ 02009 if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ 02010 if (mode == PTCACHE_CLEAR_ALL) { 02011 pid->cache->last_exact = MIN2(pid->cache->startframe, 0); 02012 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); 02013 BLI_delete(path_full, 0, 0); 02014 } else { 02015 /* read the number of the file */ 02016 unsigned int frame, len2 = (int)strlen(de->d_name); 02017 char num[7]; 02018 02019 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ 02020 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); 02021 frame = atoi(num); 02022 02023 if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || 02024 (mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) { 02025 02026 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); 02027 BLI_delete(path_full, 0, 0); 02028 if(pid->cache->cached_frames && frame >=sta && frame <= end) 02029 pid->cache->cached_frames[frame-sta] = 0; 02030 } 02031 } 02032 } 02033 } 02034 } 02035 } 02036 closedir(dir); 02037 02038 if(mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames) 02039 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); 02040 } 02041 else { 02042 PTCacheMem *pm= pid->cache->mem_cache.first; 02043 PTCacheMem *link= NULL; 02044 02045 if(mode == PTCACHE_CLEAR_ALL) { 02046 /*we want startframe if the cache starts before zero*/ 02047 pid->cache->last_exact = MIN2(pid->cache->startframe, 0); 02048 for(; pm; pm=pm->next) { 02049 ptcache_data_free(pm); 02050 ptcache_extra_free(pm); 02051 } 02052 BLI_freelistN(&pid->cache->mem_cache); 02053 02054 if(pid->cache->cached_frames) 02055 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); 02056 } else { 02057 while(pm) { 02058 if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || 02059 (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) { 02060 link = pm; 02061 if(pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end) 02062 pid->cache->cached_frames[pm->frame-sta] = 0; 02063 ptcache_data_free(pm); 02064 ptcache_extra_free(pm); 02065 pm = pm->next; 02066 BLI_freelinkN(&pid->cache->mem_cache, link); 02067 } 02068 else 02069 pm = pm->next; 02070 } 02071 } 02072 } 02073 break; 02074 02075 case PTCACHE_CLEAR_FRAME: 02076 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 02077 if(BKE_ptcache_id_exist(pid, cfra)) { 02078 ptcache_filename(pid, filename, cfra, 1, 1); /* no path */ 02079 BLI_delete(filename, 0, 0); 02080 } 02081 } 02082 else { 02083 PTCacheMem *pm = pid->cache->mem_cache.first; 02084 02085 for(; pm; pm=pm->next) { 02086 if(pm->frame == cfra) { 02087 ptcache_data_free(pm); 02088 ptcache_extra_free(pm); 02089 BLI_freelinkN(&pid->cache->mem_cache, pm); 02090 break; 02091 } 02092 } 02093 } 02094 if(pid->cache->cached_frames && cfra>=sta && cfra<=end) 02095 pid->cache->cached_frames[cfra-sta] = 0; 02096 break; 02097 } 02098 02099 BKE_ptcache_update_info(pid); 02100 } 02101 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) 02102 { 02103 if(!pid->cache) 02104 return 0; 02105 02106 if(cfra<pid->cache->startframe || cfra > pid->cache->endframe) 02107 return 0; 02108 02109 if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0) 02110 return 0; 02111 02112 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 02113 char filename[MAX_PTCACHE_FILE]; 02114 02115 ptcache_filename(pid, filename, cfra, 1, 1); 02116 02117 return BLI_exists(filename); 02118 } 02119 else { 02120 PTCacheMem *pm = pid->cache->mem_cache.first; 02121 02122 for(; pm; pm=pm->next) { 02123 if(pm->frame==cfra) 02124 return 1; 02125 } 02126 return 0; 02127 } 02128 } 02129 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale) 02130 { 02131 Object *ob; 02132 PointCache *cache; 02133 /* float offset; unused for now */ 02134 float time, nexttime; 02135 02136 /* TODO: this has to be sorter out once bsystem_time gets redone, */ 02137 /* now caches can handle interpolating etc. too - jahka */ 02138 02139 /* time handling for point cache: 02140 * - simulation time is scaled by result of bsystem_time 02141 * - for offsetting time only time offset is taken into account, since 02142 * that's always the same and can't be animated. a timeoffset which 02143 * varies over time is not simpe to support. 02144 * - field and motion blur offsets are currently ignored, proper solution 02145 * is probably to interpolate results from two frames for that .. 02146 */ 02147 02148 ob= pid->ob; 02149 cache= pid->cache; 02150 02151 if(timescale) { 02152 time= bsystem_time(scene, ob, cfra, 0.0f); 02153 nexttime= bsystem_time(scene, ob, cfra+1.0f, 0.0f); 02154 02155 *timescale= MAX2(nexttime - time, 0.0f); 02156 } 02157 02158 if(startframe && endframe) { 02159 *startframe= cache->startframe; 02160 *endframe= cache->endframe; 02161 02162 /* TODO: time handling with object offsets and simulated vs. cached 02163 * particles isn't particularly easy, so for now what you see is what 02164 * you get. In the future point cache could handle the whole particle 02165 * system timing. */ 02166 #if 0 02167 if ((ob->partype & PARSLOW)==0) { 02168 offset= give_timeoffset(ob); 02169 02170 *startframe += (int)(offset+0.5f); 02171 *endframe += (int)(offset+0.5f); 02172 } 02173 #endif 02174 } 02175 02176 /* verify cached_frames array is up to date */ 02177 if(cache->cached_frames) { 02178 if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { 02179 MEM_freeN(cache->cached_frames); 02180 cache->cached_frames = NULL; 02181 } 02182 } 02183 02184 if(cache->cached_frames==NULL && cache->endframe > cache->startframe) { 02185 unsigned int sta=cache->startframe; 02186 unsigned int end=cache->endframe; 02187 02188 cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); 02189 02190 if(pid->cache->flag & PTCACHE_DISK_CACHE) { 02191 /* mode is same as fopen's modes */ 02192 DIR *dir; 02193 struct dirent *de; 02194 char path[MAX_PTCACHE_PATH]; 02195 char filename[MAX_PTCACHE_FILE]; 02196 char ext[MAX_PTCACHE_PATH]; 02197 unsigned int len; /* store the length of the string */ 02198 02199 ptcache_path(pid, path); 02200 02201 len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */ 02202 02203 dir = opendir(path); 02204 if (dir==NULL) 02205 return; 02206 02207 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); 02208 02209 while ((de = readdir(dir)) != NULL) { 02210 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ 02211 if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ 02212 /* read the number of the file */ 02213 unsigned int frame, len2 = (int)strlen(de->d_name); 02214 char num[7]; 02215 02216 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ 02217 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); 02218 frame = atoi(num); 02219 02220 if(frame >= sta && frame <= end) 02221 cache->cached_frames[frame-sta] = 1; 02222 } 02223 } 02224 } 02225 } 02226 closedir(dir); 02227 } 02228 else { 02229 PTCacheMem *pm= pid->cache->mem_cache.first; 02230 02231 while(pm) { 02232 if(pm->frame >= sta && pm->frame <= end) 02233 cache->cached_frames[pm->frame-sta] = 1; 02234 pm = pm->next; 02235 } 02236 } 02237 } 02238 } 02239 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) 02240 { 02241 PointCache *cache; 02242 int reset, clear, after; 02243 02244 if(!pid->cache) 02245 return 0; 02246 02247 cache= pid->cache; 02248 reset= 0; 02249 clear= 0; 02250 after= 0; 02251 02252 if(mode == PTCACHE_RESET_DEPSGRAPH) { 02253 if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { 02254 if(cache->flag & PTCACHE_QUICK_CACHE) 02255 clear= 1; 02256 02257 after= 1; 02258 } 02259 02260 cache->flag |= PTCACHE_OUTDATED; 02261 } 02262 else if(mode == PTCACHE_RESET_BAKED) { 02263 if(!BKE_ptcache_get_continue_physics()) { 02264 reset= 1; 02265 clear= 1; 02266 } 02267 else 02268 cache->flag |= PTCACHE_OUTDATED; 02269 } 02270 else if(mode == PTCACHE_RESET_OUTDATED) { 02271 reset = 1; 02272 02273 if(cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) { 02274 clear= 1; 02275 cache->flag &= ~PTCACHE_OUTDATED; 02276 } 02277 } 02278 02279 if(reset) { 02280 BKE_ptcache_invalidate(cache); 02281 cache->flag &= ~PTCACHE_REDO_NEEDED; 02282 02283 if(pid->type == PTCACHE_TYPE_CLOTH) 02284 cloth_free_modifier(pid->calldata); 02285 else if(pid->type == PTCACHE_TYPE_SOFTBODY) 02286 sbFreeSimulation(pid->calldata); 02287 else if(pid->type == PTCACHE_TYPE_PARTICLES) 02288 psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); 02289 else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) 02290 smokeModifier_reset(pid->calldata); 02291 else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) 02292 smokeModifier_reset_turbulence(pid->calldata); 02293 } 02294 if(clear) 02295 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02296 else if(after) 02297 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA); 02298 02299 return (reset || clear || after); 02300 } 02301 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) 02302 { 02303 PTCacheID pid; 02304 ParticleSystem *psys; 02305 ModifierData *md; 02306 int reset, skip; 02307 02308 reset= 0; 02309 skip= 0; 02310 02311 if(ob->soft) { 02312 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); 02313 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02314 } 02315 02316 for(psys=ob->particlesystem.first; psys; psys=psys->next) { 02317 /* children or just redo can be calculated without reseting anything */ 02318 if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) 02319 skip = 1; 02320 /* Baked cloth hair has to be checked too, because we don't want to reset */ 02321 /* particles or cloth in that case -jahka */ 02322 else if(psys->clmd) { 02323 BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd); 02324 if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 02325 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02326 else 02327 skip = 1; 02328 } 02329 02330 if(skip == 0 && psys->part) { 02331 BKE_ptcache_id_from_particles(&pid, ob, psys); 02332 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02333 } 02334 } 02335 02336 for(md=ob->modifiers.first; md; md=md->next) { 02337 if(md->type == eModifierType_Cloth) { 02338 BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md); 02339 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02340 } 02341 if(md->type == eModifierType_Smoke) { 02342 SmokeModifierData *smd = (SmokeModifierData *)md; 02343 if(smd->type & MOD_SMOKE_TYPE_DOMAIN) 02344 { 02345 BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md); 02346 reset |= BKE_ptcache_id_reset(scene, &pid, mode); 02347 } 02348 } 02349 } 02350 02351 if (ob->type == OB_ARMATURE) 02352 BIK_clear_cache(ob->pose); 02353 02354 return reset; 02355 } 02356 02357 /* Use this when quitting blender, with unsaved files */ 02358 void BKE_ptcache_remove(void) 02359 { 02360 char path[MAX_PTCACHE_PATH]; 02361 char path_full[MAX_PTCACHE_PATH]; 02362 int rmdir = 1; 02363 02364 ptcache_path(NULL, path); 02365 02366 if (BLI_exist(path)) { 02367 /* The pointcache dir exists? - remove all pointcache */ 02368 02369 DIR *dir; 02370 struct dirent *de; 02371 02372 dir = opendir(path); 02373 if (dir==NULL) 02374 return; 02375 02376 while ((de = readdir(dir)) != NULL) { 02377 if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) { 02378 /* do nothing */ 02379 } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/ 02380 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); 02381 BLI_delete(path_full, 0, 0); 02382 } else { 02383 rmdir = 0; /* unknown file, dont remove the dir */ 02384 } 02385 } 02386 02387 closedir(dir); 02388 } else { 02389 rmdir = 0; /* path dosnt exist */ 02390 } 02391 02392 if (rmdir) { 02393 BLI_delete(path, 1, 0); 02394 } 02395 } 02396 02397 /* Continuous Interaction */ 02398 02399 static int CONTINUE_PHYSICS = 0; 02400 02401 void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable) 02402 { 02403 Object *ob; 02404 02405 if(CONTINUE_PHYSICS != enable) { 02406 CONTINUE_PHYSICS = enable; 02407 02408 if(CONTINUE_PHYSICS == 0) { 02409 for(ob=bmain->object.first; ob; ob=ob->id.next) 02410 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) 02411 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 02412 } 02413 } 02414 } 02415 02416 int BKE_ptcache_get_continue_physics(void) 02417 { 02418 return CONTINUE_PHYSICS; 02419 } 02420 02421 /* Point Cache handling */ 02422 02423 PointCache *BKE_ptcache_add(ListBase *ptcaches) 02424 { 02425 PointCache *cache; 02426 02427 cache= MEM_callocN(sizeof(PointCache), "PointCache"); 02428 cache->startframe= 1; 02429 cache->endframe= 250; 02430 cache->step= 10; 02431 cache->index = -1; 02432 02433 BLI_addtail(ptcaches, cache); 02434 02435 return cache; 02436 } 02437 02438 void BKE_ptcache_free_mem(ListBase *mem_cache) 02439 { 02440 PTCacheMem *pm = mem_cache->first; 02441 02442 if(pm) { 02443 for(; pm; pm=pm->next) { 02444 ptcache_data_free(pm); 02445 ptcache_extra_free(pm); 02446 } 02447 02448 BLI_freelistN(mem_cache); 02449 } 02450 } 02451 void BKE_ptcache_free(PointCache *cache) 02452 { 02453 BKE_ptcache_free_mem(&cache->mem_cache); 02454 if(cache->edit && cache->free_edit) 02455 cache->free_edit(cache->edit); 02456 if(cache->cached_frames) 02457 MEM_freeN(cache->cached_frames); 02458 MEM_freeN(cache); 02459 } 02460 void BKE_ptcache_free_list(ListBase *ptcaches) 02461 { 02462 PointCache *cache = ptcaches->first; 02463 02464 while(cache) { 02465 BLI_remlink(ptcaches, cache); 02466 BKE_ptcache_free(cache); 02467 cache = ptcaches->first; 02468 } 02469 } 02470 02471 static PointCache *ptcache_copy(PointCache *cache) 02472 { 02473 PointCache *ncache; 02474 02475 ncache= MEM_dupallocN(cache); 02476 02477 /* hmm, should these be copied over instead? */ 02478 ncache->mem_cache.first = NULL; 02479 ncache->mem_cache.last = NULL; 02480 ncache->cached_frames = NULL; 02481 ncache->edit = NULL; 02482 02483 ncache->flag= 0; 02484 ncache->simframe= 0; 02485 02486 return ncache; 02487 } 02488 /* returns first point cache */ 02489 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old) 02490 { 02491 PointCache *cache = ptcaches_old->first; 02492 02493 ptcaches_new->first = ptcaches_new->last = NULL; 02494 02495 for(; cache; cache=cache->next) 02496 BLI_addtail(ptcaches_new, ptcache_copy(cache)); 02497 02498 return ptcaches_new->first; 02499 } 02500 02501 02502 /* Baking */ 02503 void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene) 02504 { 02505 PTCacheBaker baker; 02506 02507 baker.bake=0; 02508 baker.break_data=NULL; 02509 baker.break_test=NULL; 02510 baker.pid=NULL; 02511 baker.progressbar=NULL; 02512 baker.progressend=NULL; 02513 baker.progresscontext=NULL; 02514 baker.render=0; 02515 baker.anim_init = 0; 02516 baker.main=bmain; 02517 baker.scene=scene; 02518 baker.quick_step=scene->physics_settings.quick_cache_step; 02519 02520 BKE_ptcache_bake(&baker); 02521 } 02522 02523 /* Simulation thread, no need for interlocks as data written in both threads 02524 are only unitary integers (I/O assumed to be atomic for them) */ 02525 typedef struct { 02526 int break_operation; 02527 int thread_ended; 02528 int endframe; 02529 int step; 02530 int *cfra_ptr; 02531 Main *main; 02532 Scene *scene; 02533 } ptcache_bake_data; 02534 02535 static void ptcache_dt_to_str(char *str, double dtime) 02536 { 02537 if(dtime > 60.0) { 02538 if(dtime > 3600.0) 02539 sprintf(str, "%ih %im %is", (int)(dtime/3600), ((int)(dtime/60))%60, ((int)dtime) % 60); 02540 else 02541 sprintf(str, "%im %is", ((int)(dtime/60))%60, ((int)dtime) % 60); 02542 } 02543 else 02544 sprintf(str, "%is", ((int)dtime) % 60); 02545 } 02546 02547 static void *ptcache_bake_thread(void *ptr) { 02548 int usetimer = 0, sfra, efra; 02549 double stime, ptime, ctime, fetd; 02550 char run[32], cur[32], etd[32]; 02551 02552 ptcache_bake_data *data = (ptcache_bake_data*)ptr; 02553 02554 stime = ptime = PIL_check_seconds_timer(); 02555 sfra = *data->cfra_ptr; 02556 efra = data->endframe; 02557 02558 for(; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) { 02559 scene_update_for_newframe(data->main, data->scene, data->scene->lay); 02560 if(G.background) { 02561 printf("bake: frame %d :: %d\n", (int)*data->cfra_ptr, data->endframe); 02562 } 02563 else { 02564 ctime = PIL_check_seconds_timer(); 02565 02566 fetd = (ctime-ptime)*(efra-*data->cfra_ptr)/data->step; 02567 02568 if(usetimer || fetd > 60.0) { 02569 usetimer = 1; 02570 02571 ptcache_dt_to_str(cur, ctime-ptime); 02572 ptcache_dt_to_str(run, ctime-stime); 02573 ptcache_dt_to_str(etd, fetd); 02574 02575 printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s \r", run, *data->cfra_ptr-sfra+1, efra-sfra+1, ctime-ptime, etd); 02576 } 02577 ptime = ctime; 02578 } 02579 } 02580 02581 if(usetimer) { 02582 ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime); 02583 printf("Bake %s %s (%i frames simulated). \n", (data->break_operation ? "canceled after" : "finished in"), run, *data->cfra_ptr-sfra); 02584 } 02585 02586 data->thread_ended = TRUE; 02587 return NULL; 02588 } 02589 02590 /* if bake is not given run simulations to current frame */ 02591 void BKE_ptcache_bake(PTCacheBaker* baker) 02592 { 02593 Main *bmain = baker->main; 02594 Scene *scene = baker->scene; 02595 Scene *sce_iter; /* SETLOOPER macro only */ 02596 Base *base; 02597 ListBase pidlist; 02598 PTCacheID *pid = baker->pid; 02599 PointCache *cache = NULL; 02600 float frameleno = scene->r.framelen; 02601 int cfrao = CFRA; 02602 int startframe = MAXFRAME; 02603 int bake = baker->bake; 02604 int render = baker->render; 02605 ListBase threads; 02606 ptcache_bake_data thread_data; 02607 int progress, old_progress; 02608 02609 thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA; 02610 thread_data.step = baker->quick_step; 02611 thread_data.cfra_ptr = &CFRA; 02612 thread_data.scene = baker->scene; 02613 thread_data.main = baker->main; 02614 02615 G.afbreek = 0; 02616 02617 /* set caches to baking mode and figure out start frame */ 02618 if(pid) { 02619 /* cache/bake a single object */ 02620 cache = pid->cache; 02621 if((cache->flag & PTCACHE_BAKED)==0) { 02622 if(pid->type==PTCACHE_TYPE_PARTICLES) { 02623 ParticleSystem *psys= pid->calldata; 02624 02625 /* a bit confusing, could make this work better in the UI */ 02626 if(psys->part->type == PART_EMITTER) 02627 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); 02628 } 02629 else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) { 02630 /* get all pids from the object and search for smoke low res */ 02631 ListBase pidlist2; 02632 PTCacheID *pid2; 02633 BKE_ptcache_ids_from_object(&pidlist2, pid->ob, scene, MAX_DUPLI_RECUR); 02634 for(pid2=pidlist2.first; pid2; pid2=pid2->next) { 02635 if(pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) 02636 { 02637 if(pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) { 02638 if(bake || pid2->cache->flag & PTCACHE_REDO_NEEDED) 02639 BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0); 02640 if(bake) { 02641 pid2->cache->flag |= PTCACHE_BAKING; 02642 pid2->cache->flag &= ~PTCACHE_BAKED; 02643 } 02644 } 02645 } 02646 } 02647 BLI_freelistN(&pidlist2); 02648 } 02649 02650 if(bake || cache->flag & PTCACHE_REDO_NEEDED) 02651 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02652 02653 startframe = MAX2(cache->last_exact, cache->startframe); 02654 02655 if(bake) { 02656 thread_data.endframe = cache->endframe; 02657 cache->flag |= PTCACHE_BAKING; 02658 } 02659 else { 02660 thread_data.endframe = MIN2(thread_data.endframe, cache->endframe); 02661 } 02662 02663 cache->flag &= ~PTCACHE_BAKED; 02664 } 02665 } 02666 else for(SETLOOPER(scene, sce_iter, base)) { 02667 /* cache/bake everything in the scene */ 02668 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); 02669 02670 for(pid=pidlist.first; pid; pid=pid->next) { 02671 cache = pid->cache; 02672 if((cache->flag & PTCACHE_BAKED)==0) { 02673 if(pid->type==PTCACHE_TYPE_PARTICLES) { 02674 ParticleSystem *psys = (ParticleSystem*)pid->calldata; 02675 /* skip hair & keyed particles */ 02676 if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED) 02677 continue; 02678 02679 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); 02680 } 02681 02682 if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) 02683 && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake)) 02684 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02685 02686 startframe = MIN2(startframe, cache->startframe); 02687 02688 if(bake || render) { 02689 cache->flag |= PTCACHE_BAKING; 02690 02691 if(bake) 02692 thread_data.endframe = MAX2(thread_data.endframe, cache->endframe); 02693 } 02694 02695 cache->flag &= ~PTCACHE_BAKED; 02696 02697 } 02698 } 02699 BLI_freelistN(&pidlist); 02700 } 02701 02702 CFRA = startframe; 02703 scene->r.framelen = 1.0; 02704 thread_data.break_operation = FALSE; 02705 thread_data.thread_ended = FALSE; 02706 old_progress = -1; 02707 02708 WM_cursor_wait(1); 02709 02710 if(G.background) { 02711 ptcache_bake_thread((void*)&thread_data); 02712 } 02713 else { 02714 BLI_init_threads(&threads, ptcache_bake_thread, 1); 02715 BLI_insert_thread(&threads, (void*)&thread_data); 02716 02717 while (thread_data.thread_ended == FALSE) { 02718 02719 if(bake) 02720 progress = (int)(100.0f * (float)(CFRA - startframe)/(float)(thread_data.endframe-startframe)); 02721 else 02722 progress = CFRA; 02723 02724 /* NOTE: baking should not redraw whole ui as this slows things down */ 02725 if ((baker->progressbar) && (progress != old_progress)) { 02726 baker->progressbar(baker->progresscontext, progress); 02727 old_progress = progress; 02728 } 02729 02730 /* Delay to lessen CPU load from UI thread */ 02731 PIL_sleep_ms(200); 02732 02733 /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ 02734 if(blender_test_break() && !thread_data.break_operation) { 02735 thread_data.break_operation = TRUE; 02736 if (baker->progressend) 02737 baker->progressend(baker->progresscontext); 02738 WM_cursor_wait(1); 02739 } 02740 } 02741 02742 BLI_end_threads(&threads); 02743 } 02744 /* clear baking flag */ 02745 if(pid) { 02746 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); 02747 cache->flag |= PTCACHE_SIMULATION_VALID; 02748 if(bake) { 02749 cache->flag |= PTCACHE_BAKED; 02750 /* write info file */ 02751 if(cache->flag & PTCACHE_DISK_CACHE) 02752 BKE_ptcache_write(pid, 0); 02753 } 02754 } 02755 else for(SETLOOPER(scene, sce_iter, base)) { 02756 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); 02757 02758 for(pid=pidlist.first; pid; pid=pid->next) { 02759 /* skip hair particles */ 02760 if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR) 02761 continue; 02762 02763 cache = pid->cache; 02764 02765 if(thread_data.step > 1) 02766 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); 02767 else 02768 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); 02769 02770 cache->flag |= PTCACHE_SIMULATION_VALID; 02771 02772 if(bake) { 02773 cache->flag |= PTCACHE_BAKED; 02774 if(cache->flag & PTCACHE_DISK_CACHE) 02775 BKE_ptcache_write(pid, 0); 02776 } 02777 } 02778 BLI_freelistN(&pidlist); 02779 } 02780 02781 scene->r.framelen = frameleno; 02782 CFRA = cfrao; 02783 02784 if(bake) /* already on cfra unless baking */ 02785 scene_update_for_newframe(bmain, scene, scene->lay); 02786 02787 if (thread_data.break_operation) 02788 WM_cursor_wait(0); 02789 else if (baker->progressend) 02790 baker->progressend(baker->progresscontext); 02791 02792 WM_cursor_wait(0); 02793 02794 /* TODO: call redraw all windows somehow */ 02795 } 02796 /* Helpers */ 02797 void BKE_ptcache_disk_to_mem(PTCacheID *pid) 02798 { 02799 PointCache *cache = pid->cache; 02800 PTCacheMem *pm = NULL; 02801 int baked = cache->flag & PTCACHE_BAKED; 02802 int cfra, sfra = cache->startframe, efra = cache->endframe; 02803 02804 /* Remove possible bake flag to allow clear */ 02805 cache->flag &= ~PTCACHE_BAKED; 02806 02807 /* PTCACHE_DISK_CACHE flag was cleared already */ 02808 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02809 02810 /* restore possible bake flag */ 02811 cache->flag |= baked; 02812 02813 for(cfra=sfra; cfra <= efra; cfra++) { 02814 pm = ptcache_disk_frame_to_mem(pid, cfra); 02815 02816 if(pm) 02817 BLI_addtail(&pid->cache->mem_cache, pm); 02818 } 02819 } 02820 void BKE_ptcache_mem_to_disk(PTCacheID *pid) 02821 { 02822 PointCache *cache = pid->cache; 02823 PTCacheMem *pm = cache->mem_cache.first; 02824 int baked = cache->flag & PTCACHE_BAKED; 02825 02826 /* Remove possible bake flag to allow clear */ 02827 cache->flag &= ~PTCACHE_BAKED; 02828 02829 /* PTCACHE_DISK_CACHE flag was set already */ 02830 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02831 02832 /* restore possible bake flag */ 02833 cache->flag |= baked; 02834 02835 for(; pm; pm=pm->next) { 02836 if(ptcache_mem_frame_to_disk(pid, pm)==0) { 02837 cache->flag &= ~PTCACHE_DISK_CACHE; 02838 break; 02839 } 02840 } 02841 02842 /* write info file */ 02843 if(cache->flag & PTCACHE_BAKED) 02844 BKE_ptcache_write(pid, 0); 02845 } 02846 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) 02847 { 02848 PointCache *cache = pid->cache; 02849 int last_exact = cache->last_exact; 02850 02851 if (!G.relbase_valid){ 02852 cache->flag &= ~PTCACHE_DISK_CACHE; 02853 if (G.f & G_DEBUG) 02854 printf("File must be saved before using disk cache!\n"); 02855 return; 02856 } 02857 02858 if(cache->cached_frames) { 02859 MEM_freeN(cache->cached_frames); 02860 cache->cached_frames=NULL; 02861 } 02862 02863 if(cache->flag & PTCACHE_DISK_CACHE) 02864 BKE_ptcache_mem_to_disk(pid); 02865 else 02866 BKE_ptcache_disk_to_mem(pid); 02867 02868 cache->flag ^= PTCACHE_DISK_CACHE; 02869 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); 02870 cache->flag ^= PTCACHE_DISK_CACHE; 02871 02872 cache->last_exact = last_exact; 02873 02874 BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL); 02875 02876 BKE_ptcache_update_info(pid); 02877 } 02878 02879 void BKE_ptcache_disk_cache_rename(PTCacheID *pid, char *from, char *to) 02880 { 02881 char old_name[80]; 02882 int len; /* store the length of the string */ 02883 /* mode is same as fopen's modes */ 02884 DIR *dir; 02885 struct dirent *de; 02886 char path[MAX_PTCACHE_PATH]; 02887 char old_filename[MAX_PTCACHE_FILE]; 02888 char new_path_full[MAX_PTCACHE_FILE]; 02889 char old_path_full[MAX_PTCACHE_FILE]; 02890 char ext[MAX_PTCACHE_PATH]; 02891 02892 /* save old name */ 02893 strcpy(old_name, pid->cache->name); 02894 02895 /* get "from" filename */ 02896 strcpy(pid->cache->name, from); 02897 02898 len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */ 02899 02900 ptcache_path(pid, path); 02901 dir = opendir(path); 02902 if(dir==NULL) { 02903 strcpy(pid->cache->name, old_name); 02904 return; 02905 } 02906 02907 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index); 02908 02909 /* put new name into cache */ 02910 strcpy(pid->cache->name, to); 02911 02912 while ((de = readdir(dir)) != NULL) { 02913 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ 02914 if (strncmp(old_filename, de->d_name, len ) == 0) { /* do we have the right prefix */ 02915 /* read the number of the file */ 02916 int frame, len2 = (int)strlen(de->d_name); 02917 char num[7]; 02918 02919 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ 02920 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); 02921 frame = atoi(num); 02922 02923 BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name); 02924 ptcache_filename(pid, new_path_full, frame, 1, 1); 02925 BLI_rename(old_path_full, new_path_full); 02926 } 02927 } 02928 } 02929 } 02930 closedir(dir); 02931 02932 strcpy(pid->cache->name, old_name); 02933 } 02934 02935 void BKE_ptcache_load_external(PTCacheID *pid) 02936 { 02937 /*todo*/ 02938 PointCache *cache = pid->cache; 02939 int len; /* store the length of the string */ 02940 int info = 0; 02941 int start = MAXFRAME; 02942 int end = -1; 02943 02944 /* mode is same as fopen's modes */ 02945 DIR *dir; 02946 struct dirent *de; 02947 char path[MAX_PTCACHE_PATH]; 02948 char filename[MAX_PTCACHE_FILE]; 02949 char ext[MAX_PTCACHE_PATH]; 02950 02951 if(!cache) 02952 return; 02953 02954 ptcache_path(pid, path); 02955 02956 len = ptcache_filename(pid, filename, 1, 0, 0); /* no path */ 02957 02958 dir = opendir(path); 02959 if (dir==NULL) 02960 return; 02961 02962 if(cache->index >= 0) 02963 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index); 02964 else 02965 strcpy(ext, PTCACHE_EXT); 02966 02967 while ((de = readdir(dir)) != NULL) { 02968 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ 02969 if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ 02970 /* read the number of the file */ 02971 int frame, len2 = (int)strlen(de->d_name); 02972 char num[7]; 02973 02974 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ 02975 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); 02976 frame = atoi(num); 02977 02978 if(frame) { 02979 start = MIN2(start, frame); 02980 end = MAX2(end, frame); 02981 } 02982 else 02983 info = 1; 02984 } 02985 } 02986 } 02987 } 02988 closedir(dir); 02989 02990 if(start != MAXFRAME) { 02991 PTCacheFile *pf; 02992 02993 cache->startframe = start; 02994 cache->endframe = end; 02995 cache->totpoint = 0; 02996 02997 if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) 02998 ; /*necessary info in every file*/ 02999 /* read totpoint from info file (frame 0) */ 03000 else if(info) { 03001 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0); 03002 03003 if(pf) { 03004 if(ptcache_file_header_begin_read(pf)) { 03005 if(pf->type == pid->type && pid->read_header(pf)) { 03006 cache->totpoint = pf->totpoint; 03007 cache->flag |= PTCACHE_READ_INFO; 03008 } 03009 else { 03010 cache->totpoint = 0; 03011 } 03012 } 03013 ptcache_file_close(pf); 03014 } 03015 } 03016 /* or from any old format cache file */ 03017 else { 03018 float old_data[14]; 03019 int elemsize = ptcache_old_elemsize(pid); 03020 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe); 03021 03022 if(pf) { 03023 while(ptcache_file_read(pf, old_data, 1, elemsize)) 03024 cache->totpoint++; 03025 03026 ptcache_file_close(pf); 03027 } 03028 } 03029 cache->flag |= (PTCACHE_BAKED|PTCACHE_DISK_CACHE|PTCACHE_SIMULATION_VALID); 03030 cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED); 03031 } 03032 03033 BKE_ptcache_update_info(pid); 03034 } 03035 03036 void BKE_ptcache_update_info(PTCacheID *pid) 03037 { 03038 PointCache *cache = pid->cache; 03039 PTCacheExtra *extra = NULL; 03040 int totframes = 0; 03041 char mem_info[64]; 03042 03043 if(cache->flag & PTCACHE_EXTERNAL) { 03044 int cfra = cache->startframe; 03045 03046 for(; cfra<=cache->endframe; cfra++) { 03047 if(BKE_ptcache_id_exist(pid, cfra)) 03048 totframes++; 03049 } 03050 03051 /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ 03052 if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) 03053 sprintf(cache->info, "%i frames found!", totframes); 03054 else if(totframes && cache->totpoint) 03055 sprintf(cache->info, "%i points found!", cache->totpoint); 03056 else 03057 sprintf(cache->info, "No valid data to read!"); 03058 return; 03059 } 03060 03061 if(cache->flag & PTCACHE_DISK_CACHE) { 03062 if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) 03063 { 03064 int totpoint = pid->totpoint(pid->calldata, 0); 03065 03066 if(cache->totpoint > totpoint) 03067 sprintf(mem_info, "%i cells + High Resolution cached", totpoint); 03068 else 03069 sprintf(mem_info, "%i cells cached", totpoint); 03070 } 03071 else { 03072 int cfra = cache->startframe; 03073 03074 for(; cfra<=cache->endframe; cfra++) { 03075 if(BKE_ptcache_id_exist(pid, cfra)) 03076 totframes++; 03077 } 03078 03079 sprintf(mem_info, "%i frames on disk", totframes); 03080 } 03081 } 03082 else { 03083 PTCacheMem *pm = cache->mem_cache.first; 03084 float bytes = 0.0f; 03085 int i, mb; 03086 03087 for(; pm; pm=pm->next) { 03088 for(i=0; i<BPHYS_TOT_DATA; i++) 03089 bytes += MEM_allocN_len(pm->data[i]); 03090 03091 for(extra=pm->extradata.first; extra; extra=extra->next) { 03092 bytes += MEM_allocN_len(extra->data); 03093 bytes += sizeof(PTCacheExtra); 03094 } 03095 03096 bytes += sizeof(PTCacheMem); 03097 03098 totframes++; 03099 } 03100 03101 mb = (bytes > 1024.0f * 1024.0f); 03102 03103 sprintf(mem_info, "%i frames in memory (%.1f %s)", 03104 totframes, 03105 bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), 03106 mb ? "Mb" : "kb"); 03107 } 03108 03109 if(cache->flag & PTCACHE_OUTDATED) { 03110 sprintf(cache->info, "%s, cache is outdated!", mem_info); 03111 } 03112 else if(cache->flag & PTCACHE_FRAMES_SKIPPED) { 03113 sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact); 03114 } 03115 else 03116 sprintf(cache->info, "%s.", mem_info); 03117 } 03118 03119 void BKE_ptcache_validate(PointCache *cache, int framenr) 03120 { 03121 if(cache) { 03122 cache->flag |= PTCACHE_SIMULATION_VALID; 03123 cache->simframe = framenr; 03124 } 03125 } 03126 void BKE_ptcache_invalidate(PointCache *cache) 03127 { 03128 if(cache) { 03129 cache->flag &= ~PTCACHE_SIMULATION_VALID; 03130 cache->simframe = 0; 03131 cache->last_exact = MIN2(cache->startframe, 0); 03132 } 03133 } 03134