From 286c2ca80be4ae46dc220ada2fcc5bf636d5ff49 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 20 Aug 2009 00:33:59 +0000 Subject: Smoke: * cache for low res (deactivating high res for now) * new way of view3d rendering of smoke (no longer 3 axes) -using 3dtexture now (introduced into gpu/intern) * introducing LZO and LZMA libs into extern (makefiles missing for now) * reducing memory usage after simulating for the frame ended (freeing temporary buffers) * splitting smoke into 2 modifier for the cache-sake (it cannot handle more than 1 cache on the same modifier-index) * no color on gui anymore * fixing non-power-of-2 resolutions (hopefully) * fixing select-deselect of domain drawing bug * fixing drawobject.c coding style (making Ton happy) ;-) HINT #1: If scons doesn't work -> cmakefiles are up-to-date, couldn't test scons (but i tried to mantain them, too) CODERS HINT #1: we really need a way to disable adding all modifiers through "Add Modifiers" dropdown! WARNING #1: before applying this commit, deactivate your SMOKE DOMAIN in your old files and save them then. You can open them then savely after that. WARNING #2: File and cache format of smoke can be changed, this is not final! --- source/blender/blenkernel/BKE_pointcache.h | 6 +- source/blender/blenkernel/BKE_smoke.h | 17 +- source/blender/blenkernel/CMakeLists.txt | 2 + source/blender/blenkernel/SConscript | 2 + source/blender/blenkernel/intern/modifier.c | 79 +- source/blender/blenkernel/intern/pointcache.c | 271 ++++-- source/blender/blenkernel/intern/smoke.c | 1063 ++++++++++------------- source/blender/blenkernel/intern/smokehighres.c | 137 +++ 8 files changed, 907 insertions(+), 670 deletions(-) create mode 100644 source/blender/blenkernel/intern/smokehighres.c (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 5d9dddfe30d..531487549da 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -60,8 +60,8 @@ #define PTCACHE_TYPE_SOFTBODY 0 #define PTCACHE_TYPE_PARTICLES 1 #define PTCACHE_TYPE_CLOTH 2 -#define PTCACHE_TYPE_SMOKE_DOMAIN_LOW 3 -#define PTCACHE_TYPE_SMOKE_DOMAIN_HIGH 4 +#define PTCACHE_TYPE_SMOKE_DOMAIN 3 +#define PTCACHE_TYPE_SMOKE_HIGHRES 4 /* PTCache read return code */ #define PTCACHE_READ_EXACT 1 @@ -158,7 +158,7 @@ void BKE_ptcache_make_particle_key(struct ParticleKey *key, int index, void **da void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb); void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys); void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd); -void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd, int num); +void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd); void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h index 8dc38640e9a..bd8581112f8 100644 --- a/source/blender/blenkernel/BKE_smoke.h +++ b/source/blender/blenkernel/BKE_smoke.h @@ -32,24 +32,17 @@ #ifndef BKE_SMOKE_H_ #define BKE_SMOKE_H_ +typedef int (*bresenham_callback) (float *input, int res[3], int *pixel, float *tRay); + void smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, int useRenderParams, int isFinalCalc); void smokeModifier_free (struct SmokeModifierData *smd); void smokeModifier_reset(struct SmokeModifierData *smd); void smokeModifier_createType(struct SmokeModifierData *smd); -void smoke_set_tray(struct SmokeModifierData *smd, size_t index, float transparency); -float smoke_get_tray(struct SmokeModifierData *smd, size_t index); -float smoke_get_tvox(struct SmokeModifierData *smd, size_t index); -void smoke_set_tvox(struct SmokeModifierData *smd, size_t index, float tvox); - -void smoke_set_bigtray(struct SmokeModifierData *smd, size_t index, float transparency); -float smoke_get_bigtray(struct SmokeModifierData *smd, size_t index); -float smoke_get_bigtvox(struct SmokeModifierData *smd, size_t index); -void smoke_set_bigtvox(struct SmokeModifierData *smd, size_t index, float tvox); +// high res modifier +void smokeHRModifier_do(struct SmokeHRModifierData *shrmd, struct Scene *scene, struct Object *ob, int useRenderParams, int isFinalCalc); +void smokeHRModifier_free(struct SmokeHRModifierData *shrmd); -long long smoke_get_mem_req(int xres, int yres, int zres, int amplify); -void smoke_prepare_View(struct SmokeModifierData *smd, float *light); -void smoke_prepare_bigView(struct SmokeModifierData *smd, float *light); #endif /* BKE_SMOKE_H_ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 8d1df98c5b4..17079205423 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -34,6 +34,8 @@ SET(INC ../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern ../../../intern/bsp/extern ../blenfont ../../../intern/audaspace/intern + ../../../extern/lzo/minilzo + ../../../extern/lzma ${ZLIB_INC} ) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index fdc7782a0b1..0c7922de6ff 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -11,6 +11,8 @@ incs += ' #/extern/bullet2/src' incs += ' #/intern/opennl/extern #/intern/bsp/extern' incs += ' ../gpu #/extern/glew/include' incs += ' #/intern/smoke/extern' +incs += ' #/extern/lzo/minilzo' +incs += ' #/extern/lzma' incs += ' #/intern/audaspace/intern' incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 53d1baa5c9c..1e2560bf809 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5801,26 +5801,6 @@ static void smokeModifier_initData(ModifierData *md) smd->coll = NULL; smd->type = 0; smd->time = -1; - - /* - smd->fluid = NULL; - smd->maxres = 48; - smd->amplify = 4; - smd->omega = 0.5; - smd->time = 0; - smd->flags = 0; - smd->noise = MOD_SMOKE_NOISEWAVE; - smd->visibility = 1; - - // init 3dview buffer - smd->tvox = NULL; - smd->tray = NULL; - smd->tvoxbig = NULL; - smd->traybig = NULL; - smd->viewsettings = 0; - smd->bind = NULL; - smd->max_textures = 0; - */ } static void smokeModifier_freeData(ModifierData *md) @@ -5884,6 +5864,50 @@ static void smokeModifier_updateDepgraph( */ } + +/* Smoke High Resolution */ + +static void smokeHRModifier_initData(ModifierData *md) +{ + SmokeHRModifierData *shrmd = (SmokeHRModifierData*) md; + + shrmd->wt = NULL; + shrmd->time = -1; + shrmd->strength = 2.0f; + shrmd->amplify = 1; + shrmd->noise = MOD_SMOKE_NOISEWAVE; + shrmd->point_cache = BKE_ptcache_add(&shrmd->ptcaches); + shrmd->point_cache->flag |= PTCACHE_DISK_CACHE; + shrmd->point_cache->step = 1; +} + +static void smokeHRModifier_freeData(ModifierData *md) +{ + SmokeHRModifierData *shrmd = (SmokeHRModifierData*) md; + + smokeHRModifier_free (shrmd); +} + +static void smokeHRModifier_deformVerts( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) +{ + SmokeHRModifierData *shrmd = (SmokeHRModifierData*) md; + smokeHRModifier_do(shrmd, md->scene, ob, useRenderParams, isFinalCalc); +} + +static int smokeHRModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + +static void smokeHRModifier_updateDepgraph( + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, + DagNode *obNode) +{ + ; +} + /* Cloth */ static void clothModifier_initData(ModifierData *md) @@ -8580,10 +8604,23 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->type = eModifierTypeType_OnlyDeform; mti->initData = smokeModifier_initData; mti->freeData = smokeModifier_freeData; - mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_UsesPointCache + | eModifierTypeFlag_Single; mti->deformVerts = smokeModifier_deformVerts; mti->dependsOnTime = smokeModifier_dependsOnTime; mti->updateDepgraph = smokeModifier_updateDepgraph; + + mti = INIT_TYPE(SmokeHR); + mti->type = eModifierTypeType_OnlyDeform; + mti->initData = smokeHRModifier_initData; + mti->freeData = smokeHRModifier_freeData; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_UsesPointCache + | eModifierTypeFlag_Single; + mti->deformVerts = smokeHRModifier_deformVerts; + mti->dependsOnTime = smokeHRModifier_dependsOnTime; + mti->updateDepgraph = smokeHRModifier_updateDepgraph; mti = INIT_TYPE(Cloth); mti->type = eModifierTypeType_Nonconstructive; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 09170d92866..ca27bde039b 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -59,7 +59,12 @@ #include "BLI_blenlib.h" +/* both in intern */ #include "smoke_API.h" +#include "minilzo.h" + +#include "LzmaLib.h" + /* needed for directory lookup */ #ifndef WIN32 @@ -469,43 +474,116 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p pid->info_types= (1<domain; - if(sds->fluid) - { + if(sds->fluid) { return sds->res[0]*sds->res[1]*sds->res[2]; } else return 0; } +static int ptcache_totpoint_smoke_turbulence(void *smoke_v) +{ + SmokeHRModifierData *shrmd= (SmokeHRModifierData *)smoke_v; + + if(shrmd->wt) { + /* + unsigned int res[3]; + + smoke_turbulence_get_res(sds->wt, res); + return res[0]*res[1]*res[2]; + */ + return 0; + } + else + return 0; +} + // forward decleration static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size); +static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) +{ + int r; + unsigned char compressed; + LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); + unsigned int out_len = LZO_OUT_LEN(in_len); + unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); + size_t sizeOfIt = 5; + + if(mode == 1) { + r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); + if (!(r == LZO_E_OK) || (out_len >= in_len)) + compressed = 0; + else + compressed = 1; + } + else if(mode == 2) { + + r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1.... + props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); + + if(!(r == SZ_OK) || (out_len >= in_len)) + compressed = 0; + else + compressed = 2; + } + + ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); + if(compressed) { + ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int)); + ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); + } + else + ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); + + if(compressed == 2) + { + ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int)); + ptcache_file_write(pf, props, sizeOfIt, sizeof(unsigned char)); + } + + MEM_freeN(props); + + return r; +} + static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; - if(sds->fluid) - { + if(sds->fluid) { size_t res = sds->res[0]*sds->res[1]*sds->res[2]; - float *dens, *densold, *heat, *heatold, *vx, *vy, *vz; - - smoke_export(sds->fluid, &dens, &densold, &heat, &heatold, &vx, &vy, &vz); - - ptcache_file_write(pf, dens, res, sizeof(float)); - ptcache_file_write(pf, densold, res, sizeof(float)); - ptcache_file_write(pf, heat, res, sizeof(float)); - ptcache_file_write(pf, heatold, res, sizeof(float)); - ptcache_file_write(pf, vx, res, sizeof(float)); - ptcache_file_write(pf, vy, res, sizeof(float)); - ptcache_file_write(pf, vz, res, sizeof(float)); + float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold; + unsigned char *obstacles; + unsigned int in_len = sizeof(float)*(unsigned int)res; + unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); + int mode = res >= 1000000 ? 2 : 1; + + smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); + + ptcache_compress_write(pf, (unsigned char *)sds->view3d, in_len*4, out, mode); + ptcache_compress_write(pf, (unsigned char *)dens, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)densold, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)heat, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)heatold, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)vx, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)vy, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)vz, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)vxold, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)vyold, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)vzold, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); + ptcache_file_write(pf, &dt, 1, sizeof(float)); + ptcache_file_write(pf, &dx, 1, sizeof(float)); + + MEM_freeN(out); return 1; } @@ -513,32 +591,134 @@ static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v) return 0; } +static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) +{ + SmokeModifierData *smd= (SmokeModifierData *)smoke_v; + SmokeDomainSettings *sds = smd->domain; + /* + if(sds->wt) { + unsigned int res_big[3]; + size_t res = sds->res[0]*sds->res[1]*sds->res[2]; + float *dens, *densold, *tcu, *tcv, *tcw; + unsigned int in_len = sizeof(float)*(unsigned int)res; + unsigned int in_len_big = sizeof(float) * (unsigned int)res_big; + unsigned char *out; + int mode; + + smoke_turbulence_get_res(sds->wt, res_big); + mode = res_big[0]*res_big[1]*res_big[2] >= 1000000 ? 2 : 1; + + smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); + + out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer"); + + ptcache_compress_write(pf, (unsigned char *)dens, in_len_big, out, mode); + ptcache_compress_write(pf, (unsigned char *)densold, in_len_big, out, mode); + + MEM_freeN(out); + out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer"); + ptcache_compress_write(pf, (unsigned char *)tcu, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)tcv, in_len, out, mode); + ptcache_compress_write(pf, (unsigned char *)tcw, in_len, out, mode); + MEM_freeN(out); + + return 1; + } +*/ + return 0; +} + // forward decleration static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size); +static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigned int len) +{ + int r; + unsigned char compressed = 0; + unsigned int in_len; + unsigned int out_len = len; + unsigned char *in; + unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); + size_t sizeOfIt = 5; + + ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); + if(compressed) { + ptcache_file_read(pf, &in_len, 1, sizeof(unsigned int)); + in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); + ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); + + if(compressed == 1) + r = lzo1x_decompress(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); + else if(compressed == 2) + { + size_t leni = in_len, leno = out_len; + ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int)); + ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); + r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); + } + + MEM_freeN(in); + } + else { + ptcache_file_read(pf, result, len, sizeof(unsigned char)); + } + + MEM_freeN(props); + + return r; +} + static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; - if(sds->fluid) - { + if(sds->fluid) { size_t res = sds->res[0]*sds->res[1]*sds->res[2]; - float *dens, *densold, *heat, *heatold, *vx, *vy, *vz; + float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold; + unsigned char *obstacles; + unsigned int out_len = (unsigned int)res * sizeof(float); - smoke_export(sds->fluid, &dens, &densold, &heat, &heatold, &vx, &vy, &vz); - - ptcache_file_read(pf, dens, res, sizeof(float)); - ptcache_file_read(pf, densold, res, sizeof(float)); - ptcache_file_read(pf, heat, res, sizeof(float)); - ptcache_file_read(pf, heatold, res, sizeof(float)); - ptcache_file_read(pf, vx, res, sizeof(float)); - ptcache_file_read(pf, vy, res, sizeof(float)); - ptcache_file_read(pf, vz, res, sizeof(float)); + smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); + + ptcache_compress_read(pf, (unsigned char *)sds->view3d, out_len*4); + ptcache_compress_read(pf, (unsigned char*)dens, out_len); + ptcache_compress_read(pf, (unsigned char*)densold, out_len); + ptcache_compress_read(pf, (unsigned char*)heat, out_len); + ptcache_compress_read(pf, (unsigned char*)heatold, out_len); + ptcache_compress_read(pf, (unsigned char*)vx, out_len); + ptcache_compress_read(pf, (unsigned char*)vy, out_len); + ptcache_compress_read(pf, (unsigned char*)vz, out_len); + ptcache_compress_read(pf, (unsigned char*)vxold, out_len); + ptcache_compress_read(pf, (unsigned char*)vyold, out_len); + ptcache_compress_read(pf, (unsigned char*)vzold, out_len); + ptcache_compress_read(pf, (unsigned char*)obstacles, (unsigned int)res); + ptcache_file_read(pf, &dt, 1, sizeof(float)); + ptcache_file_read(pf, &dx, 1, sizeof(float)); + } +} + +static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v) +{ + SmokeModifierData *smd= (SmokeModifierData *)smoke_v; + SmokeDomainSettings *sds = smd->domain; + /* + if(sds->fluid) { + unsigned int res[3]; + float *dens, *densold, *tcu, *tcv, *tcw; + unsigned int out_len = sizeof(float)*(unsigned int)res; + + smoke_turbulence_get_res(sds->wt, res); + + smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); + + ptcache_compress_read(pf, (unsigned char*)dens, out_len); } + */ } -void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd, int num) + +void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) { SmokeDomainSettings *sds = smd->domain; @@ -547,24 +727,21 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo pid->ob= ob; pid->calldata= smd; - // if(num == 0) - pid->type= PTCACHE_TYPE_SMOKE_DOMAIN_LOW; - // else if(num == 1) - // pid->type= PTCACHE_TYPE_SMOKE_DOMAIN_HIGH; - + pid->type= PTCACHE_TYPE_SMOKE_DOMAIN; pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)smd); pid->cache= sds->point_cache; pid->cache_ptr= &sds->point_cache; pid->ptcaches= &sds->ptcaches; - pid->totpoint= pid->totwrite= ptcache_totpoint_smoke; pid->write_elem= NULL; pid->read_elem= NULL; + pid->read_stream = ptcache_read_smoke; pid->write_stream = ptcache_write_smoke; + pid->interpolate_elem= NULL; pid->write_header= ptcache_write_basic_header; @@ -573,7 +750,6 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo pid->data_types= (1<info_types= 0; } -#endif // XXX smoke poitcache stuff breaks compiling void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd) { @@ -633,18 +809,15 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob) BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md); BLI_addtail(lb, pid); } - /* - // enabled on next commit if(md->type == eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData *)md; if(smd->type & MOD_SMOKE_TYPE_DOMAIN) { pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md, 0); + BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md); BLI_addtail(lb, pid); } } - */ } } @@ -1140,13 +1313,13 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) if(use_old) { if(pid->read_elem && ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize)) pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1); - else + else if(pid->read_elem) { error = 1; break; } } else { if(pid->read_elem && (pm || ptcache_file_read_data(pf))) pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL); - else + else if(pid->read_elem) { error = 1; break; } } @@ -1185,7 +1358,7 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) else { error = 1; break; } } - else + else if(pid->read_elem) { error = 1; break; } } else { @@ -1197,7 +1370,7 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) else { error = 1; break; } } - else + else if(pid->read_elem) { error = 1; break; } } @@ -1639,8 +1812,11 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) sbFreeSimulation(pid->calldata); else if(pid->type == PTCACHE_TYPE_PARTICLES) psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); - else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN_LOW) + else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) + { smokeModifier_reset(pid->calldata); + printf("reset PTCACHE_TYPE_SMOKE_DOMAIN\n"); + } } if(clear) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); @@ -1689,17 +1865,14 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } - /* - // enabled on next commit if(md->type == eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData *)md; if(smd->type & MOD_SMOKE_TYPE_DOMAIN) { - BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md, 0); + BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } } - */ } return reset; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 22ea41276ff..6449ae10eee 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -54,10 +54,13 @@ #include "BKE_DerivedMesh.h" #include "BKE_modifier.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" +#include "BKE_smoke.h" #include "BKE_utildefines.h" #include "DNA_customdata_types.h" #include "DNA_group_types.h" +#include "DNA_lamp_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -120,9 +123,9 @@ struct DerivedMesh; struct SmokeModifierData; // forward declerations -static void get_cell(struct SmokeModifierData *smd, float *pos, int *cell, int correct); -static void get_bigcell(struct SmokeModifierData *smd, float *pos, int *cell, int correct); +void get_cell(float *p0, int res[3], float dx, float *pos, int *cell, int correct); void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *tris, int numfaces, int numtris, int **tridivs, float cell_len); +void smoke_prepare_View(SmokeModifierData *smd, float framenr, float *light, int have_light); #define TRI_UVOFFSET (1./4.) @@ -205,17 +208,18 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive // TODO: put in failsafe if res<=0 - dg // printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]); - // dt max is 0.1 smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, 0.1); - smd->domain->wt = smoke_turbulence_init(smd->domain->res, (smd->domain->flags & MOD_SMOKE_HIGHRES) ? (smd->domain->amplify + 1) : 0, smd->domain->noise); smd->time = scene->r.cfra; smd->domain->firstframe = smd->time; - - smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta)); - if(smd->domain->wt) - smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength)); + if(!smd->domain->view3d) + { + // TVox is for transparency + smd->domain->view3d = MEM_callocN(sizeof(float)*smd->domain->res[0]*smd->domain->res[1]*smd->domain->res[2]*4, "Smoke_tVox"); + } + + smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta)); return 1; } @@ -256,7 +260,8 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive SmokeCollSettings *scs = smd->coll; MVert *mvert = dm->getVertArray(dm); MFace *mface = dm->getFaceArray(dm); - size_t i = 0, divs = 0; + size_t i = 0; + int divs = 0; int *tridivs = NULL; float cell_len = 1.0 / 50.0; // for res = 50 size_t newdivs = 0; @@ -507,27 +512,14 @@ void smokeModifier_freeDomain(SmokeModifierData *smd) if(smd->domain) { // free visualisation buffers - if(smd->domain->bind) - { - glDeleteTextures(smd->domain->max_textures, (GLuint *)smd->domain->bind); - MEM_freeN(smd->domain->bind); - } - smd->domain->max_textures = 0; // unnecessary but let's be sure - - if(smd->domain->tray) - MEM_freeN(smd->domain->tray); - if(smd->domain->tvox) - MEM_freeN(smd->domain->tvox); - if(smd->domain->traybig) - MEM_freeN(smd->domain->traybig); - if(smd->domain->tvoxbig) - MEM_freeN(smd->domain->tvoxbig); - + if(smd->domain->view3d) + MEM_freeN(smd->domain->view3d); + if(smd->domain->fluid) smoke_free(smd->domain->fluid); - if(smd->domain->wt) - smoke_turbulence_free(smd->domain->wt); + BKE_ptcache_free_list(&smd->domain->ptcaches); + smd->domain->point_cache = NULL; MEM_freeN(smd->domain); smd->domain = NULL; @@ -582,44 +574,24 @@ void smokeModifier_reset(struct SmokeModifierData *smd) { if(smd->domain) { - // free visualisation buffers - if(smd->domain->bind) - { - glDeleteTextures(smd->domain->max_textures, (GLuint *)smd->domain->bind); - MEM_freeN(smd->domain->bind); - smd->domain->bind = NULL; - } - smd->domain->max_textures = 0; - if(smd->domain->viewsettings < MOD_SMOKE_VIEW_USEBIG) - smd->domain->viewsettings = 0; - else - smd->domain->viewsettings = MOD_SMOKE_VIEW_USEBIG; - - if(smd->domain->tray) - MEM_freeN(smd->domain->tray); - if(smd->domain->tvox) - MEM_freeN(smd->domain->tvox); - if(smd->domain->traybig) - MEM_freeN(smd->domain->traybig); - if(smd->domain->tvoxbig) - MEM_freeN(smd->domain->tvoxbig); - - smd->domain->tvox = NULL; - smd->domain->tray = NULL; - smd->domain->tvoxbig = NULL; - smd->domain->traybig = NULL; + if(smd->domain->view3d) + MEM_freeN(smd->domain->view3d); + smd->domain->view3d = NULL; + + smd->domain->tex = NULL; if(smd->domain->fluid) { smoke_free(smd->domain->fluid); smd->domain->fluid = NULL; } - - if(smd->domain->wt) - { - smoke_turbulence_free(smd->domain->wt); - smd->domain->wt = NULL; - } + + smd->domain->point_cache->flag &= ~PTCACHE_SIMULATION_VALID; + smd->domain->point_cache->flag |= PTCACHE_OUTDATED; + smd->domain->point_cache->simframe= 0; + smd->domain->point_cache->last_exact= 0; + + printf("reset_domain\n"); } else if(smd->flow) { @@ -677,31 +649,24 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->smd = smd; + smd->domain->point_cache = BKE_ptcache_add(&smd->domain->ptcaches); + smd->domain->point_cache->flag |= PTCACHE_DISK_CACHE; + smd->domain->point_cache->step = 1; + /* set some standard values */ smd->domain->fluid = NULL; - smd->domain->wt = NULL; smd->domain->eff_group = NULL; smd->domain->fluid_group = NULL; smd->domain->coll_group = NULL; smd->domain->maxres = 32; - smd->domain->amplify = 1; - smd->domain->omega = 1.0; smd->domain->alpha = -0.001; smd->domain->beta = 0.1; smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG; - smd->domain->strength = 2.0; - smd->domain->noise = MOD_SMOKE_NOISEWAVE; - smd->domain->visibility = 1; smd->domain->diss_speed = 5; // init 3dview buffer - smd->domain->tvox = NULL; - smd->domain->tray = NULL; - smd->domain->tvoxbig = NULL; - smd->domain->traybig = NULL; - smd->domain->viewsettings = 0; - smd->domain->bind = NULL; - smd->domain->max_textures = 0; + smd->domain->view3d = NULL; + smd->domain->tex = NULL; } else if(smd->type & MOD_SMOKE_TYPE_FLOW) { @@ -736,15 +701,15 @@ void smokeModifier_createType(struct SmokeModifierData *smd) } // forward declaration -void smoke_calc_transparency(struct SmokeModifierData *smd, float *light, int big); +void smoke_simulate_domain(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm); void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { - if(scene->r.cfra >= smd->time) - smokeModifier_init(smd, ob, scene, dm); - if((smd->type & MOD_SMOKE_TYPE_FLOW)) { + if(scene->r.cfra >= smd->time) + smokeModifier_init(smd, ob, scene, dm); + if(scene->r.cfra > smd->time) { // XXX TODO @@ -764,6 +729,9 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } else if(smd->type & MOD_SMOKE_TYPE_COLL) { + if(scene->r.cfra >= smd->time) + smokeModifier_init(smd, ob, scene, dm); + if(scene->r.cfra > smd->time) { // XXX TODO @@ -786,459 +754,484 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } else if(smd->type & MOD_SMOKE_TYPE_DOMAIN) { + PointCache *cache; + PTCacheID pid; + float timescale; + int cache_result = 0; + int startframe, endframe, framenr; SmokeDomainSettings *sds = smd->domain; + float light[3] = {0.0,0.0,0.0}; + int have_lamp = 0; + + printf("smd->type & MOD_SMOKE_TYPE_DOMAIN\n"); + + framenr = scene->r.cfra; + + cache = sds->point_cache; + + BKE_ptcache_id_from_smoke(&pid, ob, smd); + BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); + + /* handle continuous simulation with the play button */ + if(BKE_ptcache_get_continue_physics()) + { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + cache->last_exact= 0; + + smokeModifier_init(smd, ob, scene, dm); + + smoke_simulate_domain(smd, scene, ob, dm); + + return; + } - if(scene->r.cfra > smd->time) + if(framenr < startframe) { - GroupObject *go = NULL; - Base *base = NULL; - - tstart(); - - if(sds->flags & MOD_SMOKE_DISSOLVE) - { - smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); - - if(sds->wt) - smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); - } + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + cache->last_exact= 0; - /* reset view for new frame */ - if(sds->viewsettings < MOD_SMOKE_VIEW_USEBIG) - sds->viewsettings = 0; - else - sds->viewsettings = MOD_SMOKE_VIEW_USEBIG; + // we got back in time, reset smoke in this case (TODO: use cache later) + // smd->time = scene->r.cfra; + // smokeModifier_reset(smd); - // do flows and fluids - if(1) - { - Object *otherobj = NULL; - ModifierData *md = NULL; + return; + } + else if(framenr > endframe) + { + framenr = endframe; + } - if(sds->fluid_group) // we use groups since we have 2 domains - go = sds->fluid_group->gobject.first; - else - base = scene->base.first; + if(!(cache->flag & PTCACHE_SIMULATION_VALID)) + { + // printf("reseting\n"); + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + } + + smokeModifier_init(smd, ob, scene, dm); - while(base || go) - { - otherobj = NULL; + /* try to read from cache */ + cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); + printf("cache_result: %d\n", cache_result); + + if(cache_result == PTCACHE_READ_EXACT) + { + SmokeDomainSettings *sds = smd->domain; + + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; + sds->v3dnum = framenr; + + // printf("PTCACHE_READ_EXACT\n"); + return; + } + else if(cache_result==PTCACHE_READ_OLD) + { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); + + // printf("PTCACHE_READ_OLD\n"); + + cache->flag |= PTCACHE_SIMULATION_VALID; + } + else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) + { + /* if baked and nothing in cache, do nothing */ + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + cache->last_exact= 0; + + // printf("PTCACHE_BAKED\n"); + return; + } + else if((cache_result==0) && (startframe!=framenr) && !(cache->flag & PTCACHE_SIMULATION_VALID)) + { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + cache->last_exact= 0; + + return; + } + + /* do simulation */ + + // low res + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; + + smoke_simulate_domain(smd, scene, ob, dm); + + { + // float light[3] = {0.0,0.0,0.0}; // TODO: take real LAMP coordinates - dg + Base *base_tmp = NULL; - if(sds->fluid_group) + for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) + { + if(base_tmp->object->type == OB_LAMP) + { + Lamp *la = (Lamp *)base_tmp->object->data; + + if(la->type == LA_LOCAL) { - if(go->ob) - otherobj = go->ob; + VECCOPY(light, base_tmp->object->obmat[3]); + have_lamp = 1; + break; } - else - otherobj = base->object; + } + } + } - if(!otherobj) - { - if(sds->fluid_group) - go = go->next; - else - base= base->next; + smoke_prepare_View(smd, (float)framenr, light, have_lamp); - continue; - } + BKE_ptcache_write_cache(&pid, framenr); + + printf("Writing cache_low\n"); + - md = modifiers_findByType(otherobj, eModifierType_Smoke); + tend(); + printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); + } +} + +void smoke_simulate_domain(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) +{ + GroupObject *go = NULL; + Base *base = NULL; + SmokeDomainSettings *sds = smd->domain; + + tstart(); + + if(sds->flags & MOD_SMOKE_DISSOLVE) + smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); + + // do flows and fluids + if(1) + { + Object *otherobj = NULL; + ModifierData *md = NULL; + + if(sds->fluid_group) // we use groups since we have 2 domains + go = sds->fluid_group->gobject.first; + else + base = scene->base.first; + + while(base || go) + { + otherobj = NULL; + + if(sds->fluid_group) + { + if(go->ob) + otherobj = go->ob; + } + else + otherobj = base->object; + + if(!otherobj) + { + if(sds->fluid_group) + go = go->next; + else + base= base->next; + + continue; + } + + md = modifiers_findByType(otherobj, eModifierType_Smoke); + + // check for active smoke modifier + if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) + { + SmokeModifierData *smd2 = (SmokeModifierData *)md; + + // check for initialized smoke object + if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) + { + // we got nice flow object + SmokeFlowSettings *sfs = smd2->flow; - // check for active smoke modifier - if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) + if(sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected { - SmokeModifierData *smd2 = (SmokeModifierData *)md; + ParticleSystem *psys = sfs->psys; + ParticleSettings *part=psys->part; + ParticleData *pa = NULL; + int p = 0; + float *density = smoke_get_density(sds->fluid); + // float *bigdensity = smoke_turbulence_get_density(sds->wt); + float *heat = smoke_get_heat(sds->fluid); + float *velocity_x = smoke_get_velocity_x(sds->fluid); + float *velocity_y = smoke_get_velocity_y(sds->fluid); + float *velocity_z = smoke_get_velocity_z(sds->fluid); + unsigned char *obstacle = smoke_get_obstacle(sds->fluid); + + // debug printf("found flow psys\n"); - // check for initialized smoke object - if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) + // mostly copied from particle code + for(p=0, pa=psys->particles; ptotpart; p++, pa++) { - // we got nice flow object - SmokeFlowSettings *sfs = smd2->flow; + int cell[3]; + size_t i = 0; + size_t index = 0; + int badcell = 0; - if(sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected + if(pa->alive == PARS_KILLED) continue; + else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; + else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; + else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; + + // VECCOPY(pos, pa->state.co); + // Mat4MulVecfl (ob->imat, pos); + + // 1. get corresponding cell + get_cell(sds->p0, sds->res, sds->dx, pa->state.co, cell, 0); + + // check if cell is valid (in the domain boundary) + for(i = 0; i < 3; i++) { - ParticleSystem *psys = sfs->psys; - ParticleSettings *part=psys->part; - ParticleData *pa = NULL; - int p = 0; - float *density = smoke_get_density(sds->fluid); - float *bigdensity = smoke_turbulence_get_density(sds->wt); - float *heat = smoke_get_heat(sds->fluid); - float *velocity_x = smoke_get_velocity_x(sds->fluid); - float *velocity_y = smoke_get_velocity_y(sds->fluid); - float *velocity_z = smoke_get_velocity_z(sds->fluid); - unsigned char *obstacle = smoke_get_obstacle(sds->fluid); - int bigres[3]; - - printf("found flow psys\n"); - - // mostly copied from particle code - for(p=0, pa=psys->particles; ptotpart; p++, pa++) + if((cell[i] > sds->res[i] - 1) || (cell[i] < 0)) { - int cell[3]; - size_t i = 0; - size_t index = 0; - int badcell = 0; - - if(pa->alive == PARS_KILLED) continue; - else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; - else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; - - // VECCOPY(pos, pa->state.co); - // Mat4MulVecfl (ob->imat, pos); - - // 1. get corresponding cell - get_cell(smd, pa->state.co, cell, 0); - - // check if cell is valid (in the domain boundary) - for(i = 0; i < 3; i++) - { - if((cell[i] > sds->res[i] - 1) || (cell[i] < 0)) - { - badcell = 1; - break; - } - } - - if(badcell) - continue; - - // 2. set cell values (heat, density and velocity) - index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - - if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index] & 2)) // this is inflow - { - // heat[index] += sfs->temp * 0.1; - // density[index] += sfs->density * 0.1; - - heat[index] = sfs->temp; - density[index] = sfs->density; - - /* - velocity_x[index] = pa->state.vel[0]; - velocity_y[index] = pa->state.vel[1]; - velocity_z[index] = pa->state.vel[2]; - */ - obstacle[index] |= 2; - - // we need different handling for the high-res feature - if(bigdensity) - { - // init all surrounding cells according to amplification, too - int i, j, k; - - smoke_turbulence_get_res(smd->domain->wt, bigres); - - for(i = 0; i < smd->domain->amplify + 1; i++) - for(j = 0; j < smd->domain->amplify + 1; j++) - for(k = 0; k < smd->domain->amplify + 1; k++) - { - index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k); - bigdensity[index] = sfs->density; - } - } - } - else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow - { - heat[index] = 0.f; - density[index] = 0.f; - velocity_x[index] = 0.f; - velocity_y[index] = 0.f; - velocity_z[index] = 0.f; - - // we need different handling for the high-res feature - if(bigdensity) - { - // init all surrounding cells according to amplification, too - int i, j, k; - - smoke_turbulence_get_res(smd->domain->wt, bigres); - - for(i = 0; i < smd->domain->amplify + 1; i++) - for(j = 0; j < smd->domain->amplify + 1; j++) - for(k = 0; k < smd->domain->amplify + 1; k++) - { - index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k); - bigdensity[index] = 0.f; - } - } - } + badcell = 1; + break; } } - else + + if(badcell) + continue; + + // 2. set cell values (heat, density and velocity) + index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); + + if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index] & 2)) // this is inflow { - /* - for() - { - // no psys - BVHTreeNearest nearest; + // heat[index] += sfs->temp * 0.1; + // density[index] += sfs->density * 0.1; - nearest.index = -1; - nearest.dist = FLT_MAX; + heat[index] = sfs->temp; + density[index] = sfs->density; - BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh); - }*/ + /* + velocity_x[index] = pa->state.vel[0]; + velocity_y[index] = pa->state.vel[1]; + velocity_z[index] = pa->state.vel[2]; + */ + obstacle[index] |= 2; + } + else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow + { + heat[index] = 0.f; + density[index] = 0.f; + velocity_x[index] = 0.f; + velocity_y[index] = 0.f; + velocity_z[index] = 0.f; } - } + } } - - if(sds->fluid_group) - go = go->next; else - base= base->next; - } + { + /* + for() + { + // no psys + BVHTreeNearest nearest; + + nearest.index = -1; + nearest.dist = FLT_MAX; + + BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh); + }*/ + } + } } - // do effectors - /* - if(sds->eff_group) + if(sds->fluid_group) + go = go->next; + else + base= base->next; + } + } + + // do effectors + /* + if(sds->eff_group) + { + for(go = sds->eff_group->gobject.first; go; go = go->next) + { + if(go->ob) { - for(go = sds->eff_group->gobject.first; go; go = go->next) + if(ob->pd) { - if(go->ob) - { - if(ob->pd) - { - - } - } + } } - */ + } + } + */ + + // do collisions + if(1) + { + Object *otherobj = NULL; + ModifierData *md = NULL; + + if(sds->coll_group) // we use groups since we have 2 domains + go = sds->coll_group->gobject.first; + else + base = scene->base.first; + + while(base || go) + { + otherobj = NULL; - // do collisions - if(1) + if(sds->coll_group) { - Object *otherobj = NULL; - ModifierData *md = NULL; + if(go->ob) + otherobj = go->ob; + } + else + otherobj = base->object; - if(sds->coll_group) // we use groups since we have 2 domains - go = sds->coll_group->gobject.first; + if(!otherobj) + { + if(sds->coll_group) + go = go->next; else - base = scene->base.first; + base= base->next; - while(base || go) - { - otherobj = NULL; + continue; + } + + md = modifiers_findByType(otherobj, eModifierType_Smoke); + + // check for active smoke modifier + if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) + { + SmokeModifierData *smd2 = (SmokeModifierData *)md; - if(sds->coll_group) - { - if(go->ob) - otherobj = go->ob; - } - else - otherobj = base->object; + if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) + { + // we got nice collision object + SmokeCollSettings *scs = smd2->coll; + size_t i, j; + unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid); - if(!otherobj) + for(i = 0; i < scs->numpoints; i++) { - if(sds->coll_group) - go = go->next; - else - base= base->next; + int badcell = 0; + size_t index = 0; + int cell[3]; - continue; - } - - md = modifiers_findByType(otherobj, eModifierType_Smoke); + // 1. get corresponding cell + get_cell(sds->p0, sds->res, sds->dx, &scs->points[3 * i], cell, 0); - // check for active smoke modifier - if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) - { - SmokeModifierData *smd2 = (SmokeModifierData *)md; - - if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) - { - // we got nice collision object - SmokeCollSettings *scs = smd2->coll; - size_t i, j; - unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid); - - for(i = 0; i < scs->numpoints; i++) + // check if cell is valid (in the domain boundary) + for(j = 0; j < 3; j++) + if((cell[j] > sds->res[j] - 1) || (cell[j] < 0)) { - int badcell = 0; - size_t index = 0; - int cell[3]; - - // 1. get corresponding cell - get_cell(smd, &scs->points[3 * i], cell, 0); - - // check if cell is valid (in the domain boundary) - for(j = 0; j < 3; j++) - if((cell[j] > sds->res[j] - 1) || (cell[j] < 0)) - { - badcell = 1; - break; - } - - if(badcell) - continue; - - // 2. set cell values (heat, density and velocity) - index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); + badcell = 1; + break; + } - // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]); - // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index); - - obstacles[index] = 1; + if(badcell) + continue; - // for moving gobstacles - /* - const LbmFloat maxVelVal = 0.1666; - const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5; - - LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); { - const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; - USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); - if(usqr>maxusqr) { - // cutoff at maxVelVal - for(int jj=0; jj<3; jj++) { - if(objvel[jj]>0.) objvel[jj] = maxVelVal; - if(objvel[jj]<0.) objvel[jj] = -maxVelVal; - } - } } - - const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); - const LbmVec oldov=objvel; // debug - objvel = vec2L((*pNormals)[n]) *dp; - */ - } - } + // 2. set cell values (heat, density and velocity) + index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); + + // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]); + // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index); + + obstacles[index] = 1; + + // for moving gobstacles + /* + const LbmFloat maxVelVal = 0.1666; + const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5; + + LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec); { + const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5; + USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz); + if(usqr>maxusqr) { + // cutoff at maxVelVal + for(int jj=0; jj<3; jj++) { + if(objvel[jj]>0.) objvel[jj] = maxVelVal; + if(objvel[jj]<0.) objvel[jj] = -maxVelVal; + } + } } + + const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) ); + const LbmVec oldov=objvel; // debug + objvel = vec2L((*pNormals)[n]) *dp; + */ } - - if(sds->coll_group) - go = go->next; - else - base= base->next; } } - - // set new time - smd->time = scene->r.cfra; - - // simulate the actual smoke (c++ code in intern/smoke) - smoke_step(sds->fluid, smd->time); - if(sds->wt) - smoke_turbulence_step(sds->wt, sds->fluid); - tend(); - printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); - } - else if(scene->r.cfra < smd->time) - { - // we got back in time, reset smoke in this case (TODO: use cache later) - smd->time = scene->r.cfra; - smokeModifier_reset(smd); + if(sds->coll_group) + go = go->next; + else + base= base->next; } } + + // set new time + smd->time = scene->r.cfra; + + // simulate the actual smoke (c++ code in intern/smoke) + smoke_step(sds->fluid, smd->time); } +static int calc_voxel_transp(float *input, int res[3], int *pixel, float *tRay) +{ + const size_t index = smoke_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]); + + // T_ray *= T_vox + *tRay *= input[index*4]; + + return *tRay; +} + +// forward decleration +void smoke_calc_transparency(float *result, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb); + // update necessary information for 3dview -void smoke_prepare_View(SmokeModifierData *smd, float *light) +void smoke_prepare_View(SmokeModifierData *smd, float framenr, float *light, int have_light) { float *density = NULL; int x, y, z; - - if(!smd->domain->tray) - { - // TRay is for self shadowing - smd->domain->tray = MEM_callocN(sizeof(float)*smd->domain->res[0]*smd->domain->res[1]*smd->domain->res[2], "Smoke_tRay"); - } - if(!smd->domain->tvox) - { - // TVox is for tranaparency - smd->domain->tvox = MEM_callocN(sizeof(float)*smd->domain->res[0]*smd->domain->res[1]*smd->domain->res[2], "Smoke_tVox"); - } + size_t cells, i; + SmokeDomainSettings *sds = smd->domain; // update 3dview density = smoke_get_density(smd->domain->fluid); for(x = 0; x < smd->domain->res[0]; x++) - for(y = 0; y < smd->domain->res[1]; y++) - for(z = 0; z < smd->domain->res[2]; z++) - { - size_t index; - - index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z); - // Transparency computation - // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4 - // T_vox = exp(-C_ext * h) - // C_ext/sigma_t = density * C_ext - smoke_set_tvox(smd, index, exp(-density[index] * 7.0 * smd->domain->dx)); - } - smoke_calc_transparency(smd, light, 0); -} - -// update necessary information for 3dview ("high res" option) -void smoke_prepare_bigView(SmokeModifierData *smd, float *light) -{ - float *density = NULL; - size_t i = 0; - int bigres[3]; + for(y = 0; y < smd->domain->res[1]; y++) + for(z = 0; z < smd->domain->res[2]; z++) + { + size_t index; - smoke_turbulence_get_res(smd->domain->wt, bigres); + index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z); + // Transparency computation + // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4 + // T_vox = exp(-C_ext * h) + // C_ext/sigma_t = density * C_ext + smd->domain->view3d[index * 4] = smd->domain->view3d[index * 4 + 1] = + smd->domain->view3d[index * 4 + 2] = exp(-density[index] * 7.0 * smd->domain->dx); + smd->domain->view3d[index * 4 + 3] = 1.0 - smd->domain->view3d[index * 4]; + + } - if(!smd->domain->traybig) + if(have_light) { - // TRay is for self shadowing - smd->domain->traybig = MEM_callocN(sizeof(float)*bigres[0]*bigres[1]*bigres[2], "Smoke_tRayBig"); - } - if(!smd->domain->tvoxbig) - { - // TVox is for tranaparency - smd->domain->tvoxbig = MEM_callocN(sizeof(float)*bigres[0]*bigres[1]*bigres[2], "Smoke_tVoxBig"); - } + smoke_calc_transparency(sds->view3d, sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp); - density = smoke_turbulence_get_density(smd->domain->wt); - for (i = 0; i < bigres[0] * bigres[1] * bigres[2]; i++) - { - // Transparency computation - // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4 - // T_vox = exp(-C_ext * h) - // C_ext/sigma_t = density * C_ext - smoke_set_bigtvox(smd, i, exp(-density[i] * 7.0 * smd->domain->dx / (smd->domain->amplify + 1)) ); + cells = smd->domain->res[0]*smd->domain->res[1]*smd->domain->res[2]; + for(i = 0; i < cells; i++) + { + smd->domain->view3d[i * 4] = smd->domain->view3d[i * 4 + 1] = + smd->domain->view3d[i * 4 + 2] = smd->domain->view3d[i * 4 + 1] * smd->domain->view3d[i * 4 + 0]; + } } - smoke_calc_transparency(smd, light, 1); -} - - -float smoke_get_tvox(SmokeModifierData *smd, size_t index) -{ - return smd->domain->tvox[index]; -} - -void smoke_set_tvox(SmokeModifierData *smd, size_t index, float tvox) -{ - smd->domain->tvox[index] = tvox; -} - -float smoke_get_tray(SmokeModifierData *smd, size_t index) -{ - return smd->domain->tray[index]; -} - -void smoke_set_tray(SmokeModifierData *smd, size_t index, float transparency) -{ - smd->domain->tray[index] = transparency; -} - -float smoke_get_bigtvox(SmokeModifierData *smd, size_t index) -{ - return smd->domain->tvoxbig[index]; -} - -void smoke_set_bigtvox(SmokeModifierData *smd, size_t index, float tvox) -{ - smd->domain->tvoxbig[index] = tvox; -} - -float smoke_get_bigtray(SmokeModifierData *smd, size_t index) -{ - return smd->domain->traybig[index]; -} - -void smoke_set_bigtray(SmokeModifierData *smd, size_t index, float transparency) -{ - smd->domain->traybig[index] = transparency; + smd->domain->v3dnum = framenr; } long long smoke_get_mem_req(int xres, int yres, int zres, int amplify) @@ -1259,34 +1252,7 @@ long long smoke_get_mem_req(int xres, int yres, int zres, int amplify) return totalMB; } - -static void calc_voxel_transp(SmokeModifierData *smd, int *pixel, float *tRay) -{ - // printf("Pixel(%d, %d, %d)\n", pixel[0], pixel[1], pixel[2]); - const size_t index = smoke_get_index(pixel[0], smd->domain->res[0], pixel[1], smd->domain->res[1], pixel[2]); - - // T_ray *= T_vox - *tRay *= smoke_get_tvox(smd, index); -} - -static void calc_voxel_transp_big(SmokeModifierData *smd, int *pixel, float *tRay) -{ - int bigres[3]; - size_t index; - - smoke_turbulence_get_res(smd->domain->wt, bigres); - index = smoke_get_index(pixel[0], bigres[0], pixel[1], bigres[1], pixel[2]); - - /* - if(index > bigres[0]*bigres[1]*bigres[2]) - printf("pixel[0]: %d, [1]: %d, [2]: %d\n", pixel[0], pixel[1], pixel[2]); - */ - - // T_ray *= T_vox - *tRay *= smoke_get_bigtvox(smd, index); -} - -static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, int x2, int y2, int z2, float *tRay, int big) +static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, float *tRay, bresenham_callback cb, float *input, int res[3]) { int dx, dy, dz, i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2; int pixel[3]; @@ -1313,11 +1279,7 @@ static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, i err_1 = dy2 - l; err_2 = dz2 - l; for (i = 0; i < l; i++) { - if(!big) - calc_voxel_transp(smd, pixel, tRay); - else - calc_voxel_transp_big(smd, pixel, tRay); - if(*tRay < 0.0f) + if(cb(input, res, pixel, tRay) < 0.0) return; if (err_1 > 0) { pixel[1] += y_inc; @@ -1335,11 +1297,7 @@ static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, i err_1 = dx2 - m; err_2 = dz2 - m; for (i = 0; i < m; i++) { - if(!big) - calc_voxel_transp(smd, pixel, tRay); - else - calc_voxel_transp_big(smd, pixel, tRay); - if(*tRay < 0.0f) + if(cb(input, res, pixel, tRay) < 0.0f) return; if (err_1 > 0) { pixel[0] += x_inc; @@ -1357,11 +1315,7 @@ static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, i err_1 = dy2 - n; err_2 = dx2 - n; for (i = 0; i < n; i++) { - if(!big) - calc_voxel_transp(smd, pixel, tRay); - else - calc_voxel_transp_big(smd, pixel, tRay); - if(*tRay < 0.0f) + if(cb(input, res, pixel, tRay) < 0.0f) return; if (err_1 > 0) { pixel[1] += y_inc; @@ -1376,41 +1330,15 @@ static void bresenham_linie_3D(SmokeModifierData *smd, int x1, int y1, int z1, i pixel[2] += z_inc; } } - if(!big) - calc_voxel_transp(smd, pixel, tRay); - else - calc_voxel_transp_big(smd, pixel, tRay); + cb(input, res, pixel, tRay); } -static void get_cell(struct SmokeModifierData *smd, float *pos, int *cell, int correct) -{ - float tmp[3]; - - VECSUB(tmp, pos, smd->domain->p0); - VecMulf(tmp, 1.0 / smd->domain->dx); - - if(correct) - { - cell[0] = MIN2(smd->domain->res[0] - 1, MAX2(0, (int)floor(tmp[0]))); - cell[1] = MIN2(smd->domain->res[1] - 1, MAX2(0, (int)floor(tmp[1]))); - cell[2] = MIN2(smd->domain->res[2] - 1, MAX2(0, (int)floor(tmp[2]))); - } - else - { - cell[0] = (int)floor(tmp[0]); - cell[1] = (int)floor(tmp[1]); - cell[2] = (int)floor(tmp[2]); - } -} -static void get_bigcell(struct SmokeModifierData *smd, float *pos, int *cell, int correct) +static void get_cell(float *p0, int res[3], float dx, float *pos, int *cell, int correct) { float tmp[3]; - int res[3]; - smoke_turbulence_get_res(smd->domain->wt, res); - - VECSUB(tmp, pos, smd->domain->p0); - VecMulf(tmp, (smd->domain->amplify + 1)/ smd->domain->dx ); + VECSUB(tmp, pos, p0); + VecMulf(tmp, 1.0 / dx); if(correct) { @@ -1426,43 +1354,23 @@ static void get_bigcell(struct SmokeModifierData *smd, float *pos, int *cell, in } } - -void smoke_calc_transparency(struct SmokeModifierData *smd, float *light, int big) +void smoke_calc_transparency(float *result, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb) { int x, y, z; float bv[6]; - int res[3]; float bigfactor = 1.0; // x - bv[0] = smd->domain->p0[0]; - bv[1] = smd->domain->p1[0]; + bv[0] = p0[0]; + bv[1] = p1[0]; // y - bv[2] = smd->domain->p0[1]; - bv[3] = smd->domain->p1[1]; + bv[2] = p0[1]; + bv[3] = p1[1]; // z - bv[4] = smd->domain->p0[2]; - bv[5] = smd->domain->p1[2]; -/* - printf("bv[0]: %f, [1]: %f, [2]: %f, [3]: %f, [4]: %f, [5]: %f\n", bv[0], bv[1], bv[2], bv[3], bv[4], bv[5]); - - printf("p0[0]: %f, p0[1]: %f, p0[2]: %f\n", smd->domain->p0[0], smd->domain->p0[1], smd->domain->p0[2]); - printf("p1[0]: %f, p1[1]: %f, p1[2]: %f\n", smd->domain->p1[0], smd->domain->p1[1], smd->domain->p1[2]); - printf("dx: %f, amp: %d\n", smd->domain->dx, smd->domain->amplify); -*/ - if(!big) - { - res[0] = smd->domain->res[0]; - res[1] = smd->domain->res[1]; - res[2] = smd->domain->res[2]; - } - else - { - smoke_turbulence_get_res(smd->domain->wt, res); - bigfactor = 1.0 / (smd->domain->amplify + 1); - } + bv[4] = p0[2]; + bv[5] = p1[2]; -#pragma omp parallel for schedule(static) private(y, z) shared(big, smd, light, res, bigfactor) +// #pragma omp parallel for schedule(static) private(y, z) for(x = 0; x < res[0]; x++) for(y = 0; y < res[1]; y++) for(z = 0; z < res[2]; z++) @@ -1475,41 +1383,26 @@ void smoke_calc_transparency(struct SmokeModifierData *smd, float *light, int bi index = smoke_get_index(x, res[0], y, res[1], z); - // voxelCenter = m_voxelarray[i].GetCenter(); - voxelCenter[0] = smd->domain->p0[0] + smd->domain->dx * bigfactor * x + smd->domain->dx * bigfactor * 0.5; - voxelCenter[1] = smd->domain->p0[1] + smd->domain->dx * bigfactor * y + smd->domain->dx * bigfactor * 0.5; - voxelCenter[2] = smd->domain->p0[2] + smd->domain->dx * bigfactor * z + smd->domain->dx * bigfactor * 0.5; - - // printf("vc[0]: %f, vc[1]: %f, vc[2]: %f\n", voxelCenter[0], voxelCenter[1], voxelCenter[2]); - // printf("light[0]: %f, light[1]: %f, light[2]: %f\n", light[0], light[1], light[2]); + voxelCenter[0] = p0[0] + dx * x + dx * 0.5; + voxelCenter[1] = p0[1] + dx * y + dx * 0.5; + voxelCenter[2] = p0[2] + dx * z + dx * 0.5; // get starting position (in voxel coords) if(BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON) { // we're ouside - // printf("out: pos[0]: %f, pos[1]: %f, pos[2]: %f\n", pos[0], pos[1], pos[2]); - if(!big) - get_cell(smd, pos, cell, 1); - else - get_bigcell(smd, pos, cell, 1); + get_cell(p0, res, dx, pos, cell, 1); } else { - // printf("in: pos[0]: %f, pos[1]: %f, pos[2]: %f\n", light[0], light[1], light[2]); // we're inside - if(!big) - get_cell(smd, light, cell, 1); - else - get_bigcell(smd, light, cell, 1); + get_cell(p0, res, dx, light, cell, 1); } - // printf("cell - [0]: %d, [1]: %d, [2]: %d\n", cell[0], cell[1], cell[2]); - bresenham_linie_3D(smd, cell[0], cell[1], cell[2], x, y, z, &tRay, big); + bresenham_linie_3D(cell[0], cell[1], cell[2], x, y, z, &tRay, cb, result, res); - if(!big) - smoke_set_tray(smd, index, tRay); - else - smoke_set_bigtray(smd, index, tRay); + // convention -> from a RGBA float array, use G value for tRay + result[index*4 + 1] = tRay; } } diff --git a/source/blender/blenkernel/intern/smokehighres.c b/source/blender/blenkernel/intern/smokehighres.c new file mode 100644 index 00000000000..6a2e0549158 --- /dev/null +++ b/source/blender/blenkernel/intern/smokehighres.c @@ -0,0 +1,137 @@ +/** + * smokehighres.c + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Daniel Genrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* Part of the code copied from elbeem fluid library, copyright by Nils Thuerey */ + +#include "DNA_scene_types.h" +#include "DNA_listBase.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_smoke_types.h" + +#include "BKE_modifier.h" +#include "BKE_smoke.h" +#include "BKE_pointcache.h" + +#include "smoke_API.h" + +// we need different handling for the high-res feature +/* +if(bigdensity) +{ + // init all surrounding cells according to amplification, too + int i, j, k; + + smoke_turbulence_get_res(smd->domain->wt, bigres); + + for(i = 0; i < smd->domain->amplify + 1; i++) + for(j = 0; j < smd->domain->amplify + 1; j++) + for(k = 0; k < smd->domain->amplify + 1; k++) + { + index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k); + bigdensity[index] = sfs->density; + } +} +*/ + +static void smokeHRinit(SmokeHRModifierData *shrmd, SmokeDomainSettings *sds) +{ + if(!shrmd->wt) + { + shrmd->wt = smoke_turbulence_init(sds->res, shrmd->amplify + 1, shrmd->noise); + smoke_turbulence_initBlenderRNA(shrmd->wt, &shrmd->strength); + } +} + +void smokeHRModifier_free(SmokeHRModifierData *shrmd) +{ + if(shrmd->wt) + smoke_turbulence_free(shrmd->wt); + + BKE_ptcache_free_list(&shrmd->ptcaches); + shrmd->point_cache = NULL; +} + +void smokeHRModifier_do(SmokeHRModifierData *shrmd, Scene *scene, Object *ob, int useRenderParams, int isFinalCalc) +{ + ModifierData *md = NULL; + SmokeModifierData *smd = NULL; + SmokeDomainSettings *sds = NULL; + + // find underlaying smoke domain + smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke); + if(!(smd && smd->type == MOD_SMOKE_TYPE_DOMAIN)) + return; + + sds = smd->domain; + + smokeHRinit(shrmd, sds); + + // smoke_turbulence_dissolve(shrmd->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); + + // smoke_turbulence_step(shrmd->wt, sds->fluid); +} + + +// update necessary information for 3dview ("high res" option) +void smoke_prepare_bigView(SmokeHRModifierData *shrmd, float *light) +{ + float *density = NULL; + size_t i = 0; + int bigres[3]; +/* + smoke_turbulence_get_res(shrmd->wt, bigres); + + if(!smd->domain->traybig) + { + // TRay is for self shadowing + smd->domain->traybig = MEM_callocN(sizeof(float)*bigres[0]*bigres[1]*bigres[2], "Smoke_tRayBig"); + } + if(!smd->domain->tvoxbig) + { + // TVox is for tranaparency + smd->domain->tvoxbig = MEM_callocN(sizeof(float)*bigres[0]*bigres[1]*bigres[2], "Smoke_tVoxBig"); + } + + density = smoke_turbulence_get_density(smd->domain->wt); + for (i = 0; i < bigres[0] * bigres[1] * bigres[2]; i++) + { + // Transparency computation + // formula taken from "Visual Simulation of Smoke" / Fedkiw et al. pg. 4 + // T_vox = exp(-C_ext * h) + // C_ext/sigma_t = density * C_ext + smoke_set_bigtvox(smd, i, exp(-density[i] * 7.0 * smd->domain->dx / (smd->domain->amplify + 1)) ); + } + smoke_calc_transparency(smd, light, 1); + */ +} + + -- cgit v1.2.3