diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2009-08-20 04:33:59 +0400 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2009-08-20 04:33:59 +0400 |
commit | 286c2ca80be4ae46dc220ada2fcc5bf636d5ff49 (patch) | |
tree | 91492852f1b0f8d6bc70d8b88113325e218e7f9d /source | |
parent | c21627e31b0e82f28e35af51cec681897285ff78 (diff) |
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!
Diffstat (limited to 'source')
26 files changed, 1504 insertions, 1141 deletions
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<<BPHYS_DATA_TIMES); } -#if 0 // XXX smoke pointcache stuff breaks compiling now /* Smoke functions */ static int ptcache_totpoint_smoke(void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->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<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy pid->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; p<psys->totpart; 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; p<psys->totpart; 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); + */ +} + + diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 3e1b73e51be..fad45f1b6c3 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -65,20 +65,22 @@ extern "C" { #endif -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif -#ifndef M_PI_2 -#define M_PI_2 1.57079632679489661923 -#endif -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237309504880 -#endif -#ifndef M_SQRT1_2 -#define M_SQRT1_2 0.70710678118654752440 -#endif -#ifndef M_1_PI -#define M_1_PI 0.318309886183790671538 +# ifndef _WIN64 + #ifndef M_PI + #define M_PI 3.14159265358979323846 + #endif + #ifndef M_PI_2 + #define M_PI_2 1.57079632679489661923 + #endif + #ifndef M_SQRT2 + #define M_SQRT2 1.41421356237309504880 + #endif + #ifndef M_SQRT1_2 + #define M_SQRT1_2 0.70710678118654752440 + #endif + #ifndef M_1_PI + #define M_1_PI 0.318309886183790671538 + #endif #endif #define MAXPATHLEN MAX_PATH diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index db811b22460..71994b97521 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3669,8 +3669,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) else if (md->type==eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData*) md; - smd->point_cache = NULL; - if(smd->type==MOD_SMOKE_TYPE_DOMAIN) { smd->flow = NULL; @@ -3679,23 +3677,10 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) smd->domain->smd = smd; smd->domain->fluid = NULL; - smd->domain->wt = NULL; - smd->domain->tvox = NULL; - smd->domain->tray = NULL; - smd->domain->tvoxbig = NULL; - smd->domain->traybig = NULL; - smd->domain->bind = NULL; - smd->domain->max_textures= 0; - - // do_versions trick - if(smd->domain->strength < 1.0) - smd->domain->strength = 2.0; - - // reset 3dview - if(smd->domain->viewsettings < MOD_SMOKE_VIEW_USEBIG) - smd->domain->viewsettings = 0; - else - smd->domain->viewsettings = MOD_SMOKE_VIEW_USEBIG; + smd->domain->view3d = NULL; + smd->domain->tex = NULL; + + direct_link_pointcache_list(fd, &smd->domain->ptcaches, &smd->domain->point_cache); } else if(smd->type==MOD_SMOKE_TYPE_FLOW) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index ede7aacfea8..31fe0c01900 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1126,14 +1126,17 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) else if(md->type==eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData*) md; - if(smd->type==MOD_SMOKE_TYPE_DOMAIN) + if(smd->type & MOD_SMOKE_TYPE_DOMAIN) writestruct(wd, DATA, "SmokeDomainSettings", 1, smd->domain); - else if(smd->type==MOD_SMOKE_TYPE_FLOW) + else if(smd->type & MOD_SMOKE_TYPE_FLOW) writestruct(wd, DATA, "SmokeFlowSettings", 1, smd->flow); /* - else if(smd->type==MOD_SMOKE_TYPE_COLL) + else if(smd->type & MOD_SMOKE_TYPE_COLL) writestruct(wd, DATA, "SmokeCollSettings", 1, smd->coll); */ + + if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) + write_pointcaches(wd, &smd->domain->ptcaches); } else if(md->type==eModifierType_Fluidsim) { FluidsimModifierData *fluidmd = (FluidsimModifierData*) md; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 9983e24f2c9..16900d6d894 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -161,6 +161,13 @@ int ED_object_modifier_remove(ReportList *reports, Scene *scene, Object *ob, Mod DAG_scene_sort(scene); } + else if(md->type == eModifierType_Smoke) { + ModifierData *tmd = modifiers_findByType(ob, eModifierType_SmokeHR); + if(tmd) { + BLI_remlink(&ob->modifiers, tmd); + modifier_free(tmd); + } + } BLI_remlink(&ob->modifiers, md); modifier_free(md); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 530500cfafa..994bb0010d8 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -553,7 +553,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r "world", "object", "mesh", "armature", "lattice", "curve", "meta_ball", "lamp", "camera", "material", "material_slot", "texture", "texture_slot", "bone", "edit_bone", "particle_system", - "cloth", "soft_body", "fluid", "smoke", "collision", "brush", NULL}; + "cloth", "soft_body", "fluid", "smoke", "smoke_hr", "collision", "brush", NULL}; CTX_data_dir_set(result, dir); return 1; @@ -697,6 +697,16 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r return 1; } } + else if(CTX_data_equals(member, "smoke_hr")) { + PointerRNA *ptr= get_pointer_type(path, &RNA_Object); + + if(ptr && ptr->data) { + Object *ob= ptr->data; + ModifierData *md= modifiers_findByType(ob, eModifierType_SmokeHR); + CTX_data_pointer_set(result, &ob->id, &RNA_SmokeHRModifier, md); + return 1; + } + } else if(CTX_data_equals(member, "collision")) { PointerRNA *ptr= get_pointer_type(path, &RNA_Object); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 466b55ba862..55565c83f5e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -5309,356 +5309,20 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } /* draw code for smoke */ - if((md = modifiers_findByType(ob, eModifierType_Smoke))) - { - SmokeModifierData *smd = (SmokeModifierData *)md; - - // draw collision objects - if((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll) - { - /*SmokeCollSettings *scs = smd->coll; - if(scs->points) - { - size_t i; - - wmLoadMatrix(rv3d->viewmat); - - if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - - - // glPointSize(3.0); - bglBegin(GL_POINTS); - - for(i = 0; i < scs->numpoints; i++) - { - bglVertex3fv(&scs->points[3*i]); - } - - bglEnd(); - glPointSize(1.0); - - wmMultMatrix(ob->obmat); - glDisable(GL_BLEND); - glDepthMask(GL_TRUE); - if(col) cpack(col); - - } - */ - } - - // only draw domains - if(smd->domain && smd->domain->fluid) - { - int x, y, z, i; - float viewnormal[3]; - int mainaxis[3] = {0,0,0}; - float align = 0, signed_align = 0; - int max_textures = 0, counter_textures = 0; - float *buffer = NULL; - int res[3]; - float bigfactor = 1.0; - int big = (smd->domain->flags & MOD_SMOKE_HIGHRES) && (smd->domain->viewsettings & MOD_SMOKE_VIEW_USEBIG); - int new = 0; - int have_lamp = 0; - - // GUI sent redraw event - if(smd->domain->flags & MOD_SMOKE_VIEW_REDRAWNICE) - { - new = 1; - smd->domain->flags &= ~MOD_SMOKE_VIEW_REDRAWNICE; - } - - 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); - } - - wmLoadMatrix(rv3d->viewmat); - - if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */ - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - - // get view vector - VECCOPY(viewnormal, rv3d->viewinv[2]); - Normalize(viewnormal); - for(i = 0; i < 3; i++) - { - if(ABS(viewnormal[i]) > align) - { - mainaxis[0] = i; - align = ABS(viewnormal[i]); - signed_align = viewnormal[i]; - } - } - mainaxis[1] = (mainaxis[0] + 1) % 3; - mainaxis[2] = (mainaxis[0] + 2) % 3; - - if(!smd->domain->bind) - { - smd->domain->bind = MEM_callocN(sizeof(GLuint)*256, "Smoke_bind"); - if(big) - smd->domain->viewsettings |= MOD_SMOKE_VIEW_CHANGETOBIG; - new = 3; - } - - // check if view axis / mode has been changed - if(smd->domain->viewsettings) - { - if(big) - { - if(!(smd->domain->viewsettings & MOD_SMOKE_VIEW_BIG)) - new = 2; - else if(!(smd->domain->viewsettings & MOD_SMOKE_VIEW_CHANGETOBIG)) - new = 1; - - smd->domain->viewsettings |= MOD_SMOKE_VIEW_CHANGETOBIG; - } - else - { - if(!(smd->domain->viewsettings & MOD_SMOKE_VIEW_SMALL)) - new = 2; - else if(smd->domain->viewsettings & MOD_SMOKE_VIEW_CHANGETOBIG) - new = 1; - - smd->domain->viewsettings &= ~MOD_SMOKE_VIEW_CHANGETOBIG; - } - - if(!new) - { - if((mainaxis[0] == 0) && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_X)) - new = 1; - else if((mainaxis[0] == 1) && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_Y)) - new = 1; - else if((mainaxis[0] == 2) && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_Z)) - new = 1; - - // printf("check axis\n"); - } - } - else - new = 3; - - if(new > 1) - { - float light[3] = {0.0,0.0,0.0}; // TODO: take real LAMP coordinates - dg - Base *base_tmp = NULL; - - 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) - { - VECCOPY(light, base_tmp->object->obmat[3]); - have_lamp = 1; - break; - } - } - } - - if(!big && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_SMALL)) - { - smoke_prepare_View(smd, light); - // printf("prepared View!\n"); - } - else if(big && !(smd->domain->viewsettings & MOD_SMOKE_VIEW_BIG)) - { - smoke_prepare_bigView(smd, light); - // printf("prepared bigView!\n"); - } - } - - // printf("big: %d, new: %d\n", big, new); - - // only create buffer if we need to create new textures - if(new) - buffer = MEM_mallocN(sizeof(float)*res[mainaxis[1]]*res[mainaxis[2]]*4, "SmokeDrawBuffer"); - - if(buffer || smd->domain->viewsettings) - { - int mod_texture = 0; - - // printf("if(buffer || smd->domain->viewsettings)\n"); - - max_textures = (res[mainaxis[0]] > 256) ? 256 : res[mainaxis[0]]; - - if(!smd->domain->viewsettings) // new frame or new start - { - smd->domain->max_textures = max_textures; - glGenTextures(smd->domain->max_textures, (GLuint *)smd->domain->bind); - new = 1; - // printf("glGenTextures\n"); - } - else - { - if(new) - { - // printf("glDeleteTextures\n"); - glDeleteTextures(smd->domain->max_textures, (GLuint *)smd->domain->bind); - smd->domain->max_textures = max_textures; - glGenTextures(smd->domain->max_textures, (GLuint *)smd->domain->bind); - } - } - - mod_texture = MAX3(1, smd->domain->visibility, (int)(res[mainaxis[0]] / smd->domain->max_textures )); - - // align order of billboards to be front or backview (e.g. +x or -x axis) - if(signed_align < 0) - { - z = res[mainaxis[0]] - 1; - } - else - { - z = 0; - } - - for (; signed_align > 0 ? (z < res[mainaxis[0]]) : (z >= 0); signed_align > 0 ? z++ : z--) // 2 - { - float quad[4][3]; - - if(new) - { - for (y = 0; y < res[mainaxis[1]]; y++) // 1 - { - for (x = 0; x < res[mainaxis[2]]; x++) // 0 - { - size_t index; - size_t image_index; - float tray, tvox; - - image_index = smoke_get_index2d(y, res[mainaxis[1]], x); - - if(mainaxis[0] == 0) - { - // mainaxis[1] == 1, mainaxis[2] == 2 - index = smoke_get_index(z, res[mainaxis[0]], y, res[mainaxis[1]], x); - } - else if(mainaxis[0] == 1) - { - // mainaxis[1] == 2, mainaxis[2] == 0 - index = smoke_get_index(x, res[mainaxis[2]], z, res[mainaxis[0]], y); - } - else // mainaxis[0] == 2 - { - // mainaxis[1] == 0, mainaxis[2] == 1 - index = smoke_get_index(y, res[mainaxis[1]], x, res[mainaxis[2]], z); - } - - if(!big) - { - tvox = smoke_get_tvox(smd, index); - tray = smoke_get_tray(smd, index); - } - else - { - tvox = smoke_get_bigtvox(smd, index); - tray = smoke_get_bigtray(smd, index); - } - - if(!have_lamp) - tray = 1.0; - - // fill buffer with luminance and alpha - // 1 - T_vox - buffer[image_index*4 + 3] = 1.0 - tvox; // 0 = transparent => d.h. tvox = 1 - - // L_vox = Omega * L_light * (1 - T_vox) * T_ray - buffer[image_index*4] = buffer[image_index*4 + 1] = buffer[image_index*4 + 2] = smd->domain->omega * 1.0 * tvox * tray; - } - } - } - glBindTexture(GL_TEXTURE_2D, smd->domain->bind[counter_textures]); - glEnable(GL_TEXTURE_2D); - - if(new) - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res[mainaxis[1]], res[mainaxis[2]], 0, GL_RGBA, GL_FLOAT, buffer); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering - } - - if((z % mod_texture) == 0 ) - { - // botttom left - quad[3][mainaxis[0]] = smd->domain->p0[mainaxis[0]] + z * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5; - quad[3][mainaxis[1]] = smd->domain->p0[mainaxis[1]] + smd->domain->dx * bigfactor * 0.5; - quad[3][mainaxis[2]] = smd->domain->p0[mainaxis[2]] + smd->domain->dx * bigfactor * 0.5; - - // top right - quad[1][mainaxis[0]] = smd->domain->p0[mainaxis[0]] + z * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5; - quad[1][mainaxis[1]] = smd->domain->p0[mainaxis[1]] + (res[mainaxis[1]] - 1) * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5; - quad[1][mainaxis[2]] = smd->domain->p0[mainaxis[2]] + (res[mainaxis[2]] - 1) * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5; - - // top left - quad[2][mainaxis[0]] = smd->domain->p0[mainaxis[0]] + z * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5; - quad[2][mainaxis[1]] = smd->domain->p0[mainaxis[1]] + smd->domain->dx * bigfactor * 0.5; - quad[2][mainaxis[2]] = smd->domain->p0[mainaxis[2]] + (res[mainaxis[2]] - 1) * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5; - - // bottom right - quad[0][mainaxis[0]] = smd->domain->p0[mainaxis[0]] + z * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5; - quad[0][mainaxis[1]] = smd->domain->p0[mainaxis[1]] + (res[mainaxis[1]] - 1) * smd->domain->dx * bigfactor + smd->domain->dx * bigfactor * 0.5; - quad[0][mainaxis[2]] = smd->domain->p0[mainaxis[2]] + smd->domain->dx * bigfactor * 0.5; - - glBegin(GL_QUADS); // Start Drawing Quads - - glTexCoord2f(1.0f, 0.0f); - glVertex3fv(quad[0]); // Left And Up 1 Unit (Top Left) - glTexCoord2f(1.0f, 1.0f); - glVertex3fv(quad[1]); // Right And Up 1 Unit (Top Right) - glTexCoord2f(0.0f, 1.0f); - glVertex3fv(quad[2]); // Right And Down One Unit (Bottom Right) - glTexCoord2f(0.0f, 0.0f); - glVertex3fv(quad[3]); // Left And Down One Unit (Bottom Left) - - glEnd(); - } - counter_textures++; - } - } - if(buffer) - { - MEM_freeN(buffer); - buffer = NULL; - } - - // set correct flag for viewsettings - if(1) - { - // do not clear BIG/SMALL flag - smd->domain->viewsettings &= ~MOD_SMOKE_VIEW_X; - smd->domain->viewsettings &= ~MOD_SMOKE_VIEW_Y; - smd->domain->viewsettings &= ~MOD_SMOKE_VIEW_Z; - - // set what caches we have - if(big) - smd->domain->viewsettings |= MOD_SMOKE_VIEW_BIG; - else - smd->domain->viewsettings |= MOD_SMOKE_VIEW_SMALL; - - if(mainaxis[0] == 0) - smd->domain->viewsettings |= MOD_SMOKE_VIEW_X; - else if(mainaxis[0] == 1) - smd->domain->viewsettings |= MOD_SMOKE_VIEW_Y; - else if(mainaxis[0] == 2) - smd->domain->viewsettings |= MOD_SMOKE_VIEW_Z; + if(((SmokeHRModifierData *)(md = modifiers_findByType(ob, eModifierType_SmokeHR)) && (((SmokeHRModifierData *)md)->flags & MOD_SMOKE_SHOWHIGHRES))) { + // GPU_create_smoke(smd); + // draw_volume(scene, ar, v3d, base, smd->domain->tex, smd->domain->res); + // GPU_free_smoke(smd); + } + else { + md = modifiers_findByType(ob, eModifierType_Smoke); + if (md) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if(smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) { + GPU_create_smoke(smd); + draw_volume(scene, ar, v3d, base, smd->domain->tex, smd->domain->res); + GPU_free_smoke(smd); } - - wmMultMatrix(ob->obmat); - glDisable(GL_BLEND); - glDepthMask(GL_TRUE); - if(col) cpack(col); } } diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c new file mode 100644 index 00000000000..221003360f4 --- /dev/null +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -0,0 +1,304 @@ +/** + * $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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Daniel Genrich + * + * ***** END GPL LICENSE BLOCK ***** + */ + + +#include <string.h> +#include <math.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "MEM_guardedalloc.h" + +#include "IMB_imbuf.h" + + +#include "MTC_matrixops.h" + +#include "DNA_armature_types.h" +#include "DNA_boid_types.h" +#include "DNA_camera_types.h" +#include "DNA_curve_types.h" +#include "DNA_constraint_types.h" // for drawing constraint +#include "DNA_effect_types.h" +#include "DNA_lamp_types.h" +#include "DNA_lattice_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_meta_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_object_fluidsim.h" +#include "DNA_particle_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_smoke_types.h" +#include "DNA_userdef_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" +#include "BLI_edgehash.h" +#include "BLI_rand.h" + +#include "BKE_anim.h" //for the where_on_path function +#include "BKE_curve.h" +#include "BKE_constraint.h" // for the get_constraint_target function +#include "BKE_DerivedMesh.h" +#include "BKE_deform.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_font.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_key.h" +#include "BKE_lattice.h" +#include "BKE_mesh.h" +#include "BKE_material.h" +#include "BKE_mball.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_particle.h" +#include "BKE_property.h" +#include "BKE_smoke.h" +#include "BKE_unit.h" +#include "BKE_utildefines.h" +#include "smoke_API.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_draw.h" +#include "GPU_material.h" +#include "GPU_extensions.h" + +#include "ED_mesh.h" +#include "ED_particle.h" +#include "ED_screen.h" +#include "ED_types.h" +#include "ED_util.h" + +#include "UI_resources.h" +#include "UI_interface_icons.h" + +#include "WM_api.h" +#include "BLF_api.h" + +#include "GPU_extensions.h" + +#include "view3d_intern.h" // own include + +struct GPUTexture; + +/* draw slices of smoke is adapted from c++ code authored by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */ +static float cv[][3] = { + {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, + {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f} +}; + +// edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] +static float edges[12][2][3] = { + {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + + {{1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}}, + {{-1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}}, + {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}}, + {{1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}}, + + {{-1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, -1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, -1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, 1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}} +}; + +int intersect_edges(float *points, float a, float b, float c, float d) +{ + int i; + float t; + int numpoints = 0; + + for (i=0; i<12; i++) { + t = -(a*edges[i][0][0] + b*edges[i][0][1] + c*edges[i][0][2] + d) + / (a*edges[i][1][0] + b*edges[i][1][1] + c*edges[i][1][2]); + if ((t>0)&&(t<2)) { + points[numpoints * 3 + 0] = edges[i][0][0] + edges[i][1][0]*t; + points[numpoints * 3 + 1] = edges[i][0][1] + edges[i][1][1]*t; + points[numpoints * 3 + 2] = edges[i][0][2] + edges[i][1][2]*t; + numpoints++; + } + } + return numpoints; +} + +static int convex(float *p0, float *up, float *a, float *b) +{ + // Vec3 va = a-p0, vb = b-p0; + float va[3], vb[3], tmp[3]; + VECSUB(va, a, p0); + VECSUB(vb, b, p0); + Crossf(tmp, va, vb); + return INPR(up, tmp) >= 0; +} + +// copied from gpu_extension.c +static int is_pow2(int n) +{ + return ((n)&(n-1))==0; +} + +static int larger_pow2(int n) +{ + if (is_pow2(n)) + return n; + + while(!is_pow2(n)) + n= n&(n-1); + + return n*2; +} + +void draw_volume(Scene *scene, ARegion *ar, View3D *v3d, Base *base, GPUTexture *tex, int res[3]) +{ + Object *ob = base->object; + RegionView3D *rv3d= ar->regiondata; + + float viewnormal[3]; + // int res[3]; + int i, j, n; + float d, d0, dd; + float *points = NULL; + int numpoints = 0; + float cor[3] = {1.,1.,1.}; + + /* + res[0] = smd->domain->res[0]; + res[1] = smd->domain->res[1]; + res[2] = smd->domain->res[2]; + */ + + wmLoadMatrix(rv3d->viewmat); + + glDepthMask(GL_FALSE); + glEnable(GL_TEXTURE_3D); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // get view vector + VECCOPY(viewnormal, rv3d->viewinv[2]); + Normalize(viewnormal); + + // find cube vertex that is closest to the viewer + for (i=0; i<8; i++) { + float x,y,z; + + x = cv[i][0] + viewnormal[0]; + y = cv[i][1] + viewnormal[1]; + z = cv[i][2] + viewnormal[2]; + + if ((x>=-1.0f)&&(x<=1.0f) + &&(y>=-1.0f)&&(y<=1.0f) + &&(z>=-1.0f)&&(z<=1.0f)) { + break; + } + } + + GPU_texture_bind(tex, 0); + + cor[0] = (float)res[0]/(float)larger_pow2(res[0]); + cor[1] = (float)res[1]/(float)larger_pow2(res[1]); + cor[2] = (float)res[2]/(float)larger_pow2(res[2]); + + // our slices are defined by the plane equation a*x + b*y +c*z + d = 0 + // (a,b,c), the plane normal, are given by viewdir + // d is the parameter along the view direction. the first d is given by + // inserting previously found vertex into the plane equation + d0 = -(viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); + dd = 2.0*d0/64.0f; + n = 0; + + // printf("d0: %f, dd: %f\n", d0, dd); + + points = MEM_callocN(sizeof(float)*12*3, "smoke_points_preview"); + + for (d = d0; d > -d0; d -= dd) { + float p0[3]; + // intersect_edges returns the intersection points of all cube edges with + // the given plane that lie within the cube + numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], d); + + if (numpoints > 2) { + VECCOPY(p0, points); + + // sort points to get a convex polygon + for(i = 1; i < numpoints - 1; i++) + { + for(j = i + 1; j < numpoints; j++) + { + if(convex(p0, viewnormal, &points[j * 3], &points[i * 3])) + { + float tmp2[3]; + VECCOPY(tmp2, &points[i * 3]); + VECCOPY(&points[i * 3], &points[j * 3]); + VECCOPY(&points[j * 3], tmp2); + } + } + } + + glBegin(GL_POLYGON); + for (i = 0; i < numpoints; i++) { + glColor3f(1.0, 1.0, 1.0); + glTexCoord3d((points[i * 3 + 0] + 1.0)*cor[0]/2.0, (points[i * 3 + 1] + 1)*cor[1]/2.0, (points[i * 3 + 2] + 1.0)*cor[2]/2.0); + glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]); + } + glEnd(); + } + n++; + } + + GPU_texture_unbind(tex); + + MEM_freeN(points); + + wmMultMatrix(ob->obmat); + + glDisable(GL_TEXTURE_3D); + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); +} + diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index acd1c62bc17..e5e85cf9d16 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -156,6 +156,9 @@ void VIEW3D_OT_snap_menu(struct wmOperatorType *ot); ARegion *view3d_has_buttons_region(ScrArea *sa); ARegion *view3d_has_tools_region(ScrArea *sa); +/* draw_volume.c */ +void draw_volume(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct Base *base, struct GPUTexture *tex, int res[3]); + #endif /* ED_VIEW3D_INTERN_H */ diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 82ff51dc5ce..1c6b8399422 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -112,6 +112,10 @@ int GPU_verify_image(struct Image *ima, int tftile, int tfmode, int compare, int void GPU_free_image(struct Image *ima); void GPU_free_images(void); +/* smoke drawing functions */ +void GPU_free_smoke(struct SmokeModifierData *smd); +void GPU_create_smoke(struct SmokeModifierData *smd); + #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index eba585e8838..e00cab79ce0 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -73,6 +73,7 @@ int GPU_print_error(char *str); GPUTexture *GPU_texture_create_1D(int w, float *pixels); GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels); +GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels); GPUTexture *GPU_texture_create_depth(int w, int h); GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, double time, int mipmap); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index e7846a23905..a81c7e03455 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -38,9 +38,11 @@ #include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_smoke_types.h" #include "DNA_userdef_types.h" #include "DNA_view3d_types.h" @@ -744,6 +746,23 @@ int GPU_update_image_time(Image *ima, double time) return inc; } + +void GPU_free_smoke(SmokeModifierData *smd) +{ + if(smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) + { + if(smd->domain->tex) + GPU_texture_free(smd->domain->tex); + smd->domain->tex = NULL; + } +} + +void GPU_create_smoke(SmokeModifierData *smd) +{ + if(smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain && !smd->domain->tex) + smd->domain->tex = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smd->domain->view3d); +} + void GPU_free_image(Image *ima) { /* free regular image binding */ diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 467b2c4a7f4..0b6640b9e27 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -312,6 +312,78 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in return tex; } + +GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels) +{ + GPUTexture *tex; + GLenum type, format, internalformat; + void *pixels = NULL; + + tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->w = w; + tex->h = h; + tex->depth = depth; + tex->number = -1; + tex->refcount = 1; + tex->target = GL_TEXTURE_3D; + + glGenTextures(1, &tex->bindcode); + + if (!tex->bindcode) { + fprintf(stderr, "GPUTexture: texture create failed: %d\n", + (int)glGetError()); + GPU_texture_free(tex); + return NULL; + } + + // if (!GLEW_ARB_texture_non_power_of_two) + { + tex->w = larger_pow2(tex->w); + tex->h = larger_pow2(tex->h); + tex->depth = larger_pow2(tex->depth); + } + + tex->number = 0; + glBindTexture(tex->target, tex->bindcode); + + type = GL_UNSIGNED_BYTE; + format = GL_RGBA; + internalformat = GL_RGBA8; + + if (fpixels) + pixels = GPU_texture_convert_pixels(w*h*depth, fpixels); + + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, 0); + + if (fpixels) { + glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, pixels); + + /* + if (tex->w > w) + GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h); + if (tex->h > h) + GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h); + */ + } + + // glTexImage3D(tex->target, 0, GL_RGBA, w, h, depth, 0, GL_RGBA, GL_FLOAT, fpixels); + + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,GL_CLAMP_TO_BORDER); + + + if (pixels) + MEM_freeN(pixels); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time, int mipmap) { GPUTexture *tex; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 9d1707599b9..33499574012 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -42,6 +42,7 @@ typedef enum ModifierType { eModifierType_Multires, eModifierType_Surface, eModifierType_Smoke, + eModifierType_SmokeHR, NUM_MODIFIER_TYPES } ModifierType; @@ -252,9 +253,36 @@ typedef struct SmokeModifierData { struct SmokeCollSettings *coll; /* collision objects */ float time; int type; /* domain, inflow, outflow, ... */ - struct PointCache *point_cache; /* definition is in DNA_object_force.h */ } SmokeModifierData; + +/* noise */ +#define MOD_SMOKE_NOISEWAVE (1<<0) +#define MOD_SMOKE_NOISEFFT (1<<1) +#define MOD_SMOKE_NOISECURL (1<<2) + +/* flags */ +#define MOD_SMOKE_SHOWHIGHRES (1<<0) /* show high resolution */ + +typedef struct SmokeHRModifierData { + ModifierData modifier; + + struct WTURBULENCE *wt; // WTURBULENCE object, if active + struct PointCache *point_cache; /* definition is in DNA_object_force.h */ + struct ListBase ptcaches; + struct GPUTexture *tex; + float *view3d; /* voxel data for display */ + unsigned int v3dnum; /* number of frame in view3d buffer */ + float time; + float strength; + int res[3]; + int maxres; + short noise; /* noise type: wave, curl, anisotropic */ + short pad; + int amplify; + int flags; +} SmokeHRModifierData; + typedef struct DisplaceModifierData { ModifierData modifier; diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index c7f49d3ddd2..2d8b21b86de 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -30,24 +30,12 @@ #define DNA_SMOKE_TYPES_H /* flags */ -#define MOD_SMOKE_HIGHRES (1<<1) /* compute high resolution */ +#define MOD_SMOKE_HIGHRES (1<<1) /* enable high resolution */ #define MOD_SMOKE_DISSOLVE (1<<2) /* let smoke dissolve */ #define MOD_SMOKE_DISSOLVE_LOG (1<<3) /* using 1/x for dissolve */ -/* noise */ -#define MOD_SMOKE_NOISEWAVE (1<<0) -#define MOD_SMOKE_NOISEFFT (1<<1) -#define MOD_SMOKE_NOISECURL (1<<2) /* viewsettings */ -#define MOD_SMOKE_VIEW_X (1<<0) -#define MOD_SMOKE_VIEW_Y (1<<1) -#define MOD_SMOKE_VIEW_Z (1<<2) -#define MOD_SMOKE_VIEW_SMALL (1<<3) -#define MOD_SMOKE_VIEW_BIG (1<<4) -#define MOD_SMOKE_VIEW_CHANGETOBIG (1<<5) -#define MOD_SMOKE_VIEW_REDRAWNICE (1<<6) -#define MOD_SMOKE_VIEW_REDRAWALL (1<<7) -#define MOD_SMOKE_VIEW_USEBIG (1<<8) +/* nothing so far */ typedef struct SmokeDomainSettings { struct SmokeModifierData *smd; /* for fast RNA access */ @@ -55,33 +43,27 @@ typedef struct SmokeDomainSettings { struct Group *fluid_group; struct Group *eff_group; // effector group for e.g. wind force struct Group *coll_group; // collision objects group - unsigned int *bind; - float *tvox; - float *tray; - float *tvoxbig; - float *traybig; + struct GPUTexture *tex; + float *view3d; /* voxel data for display */ + unsigned int v3dnum; /* number of frame in view3d buffer */ float p0[3]; /* start point of BB */ float p1[3]; /* end point of BB */ float dx; /* edge length of one cell */ float firstframe; float lastframe; - float omega; /* smoke color - from 0 to 1 */ float temp; /* fluid temperature */ float tempAmb; /* ambient temperature */ float alpha; float beta; int res[3]; /* domain resolution */ - int amplify; /* wavelet amplification */ int maxres; /* longest axis on the BB gets this resolution assigned */ int flags; /* show up-res or low res, etc */ - int visibility; /* how many billboards to show (every 2nd, 3rd, 4th,..) */ int viewsettings; - int max_textures; - short noise; /* noise type: wave, curl, anisotropic */ short diss_percent; + short pad; int diss_speed;/* in frames */ - float strength; - struct WTURBULENCE *wt; // WTURBULENCE object, if active + struct PointCache *point_cache; /* definition is in DNA_object_force.h */ + struct ListBase ptcaches; } SmokeDomainSettings; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index e08bc734242..e4fe92317d4 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -387,6 +387,7 @@ extern StructRNA RNA_SmokeCollSettings; extern StructRNA RNA_SmokeDomainSettings; extern StructRNA RNA_SmokeFlowSettings; extern StructRNA RNA_SmokeModifier; +extern StructRNA RNA_SmokeHRModifier; extern StructRNA RNA_SmoothModifier; extern StructRNA RNA_SoftBodyModifier; extern StructRNA RNA_SoftBodySettings; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 837158b9ec8..f2c8e404a52 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -68,6 +68,7 @@ EnumPropertyItem modifier_type_items[] ={ {eModifierType_Shrinkwrap, "SHRINKWRAP", ICON_MOD_SHRINKWRAP, "Shrinkwrap", ""}, {eModifierType_SimpleDeform, "SIMPLE_DEFORM", ICON_MOD_SIMPLEDEFORM, "Simple Deform", ""}, {eModifierType_Smoke, "SMOKE", 0, "Smoke", ""}, + {eModifierType_SmokeHR, "SMOKE_HR", 0, "SmokeHR", ""}, {eModifierType_Smooth, "SMOOTH", ICON_MOD_SMOOTH, "Smooth", ""}, {eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""}, {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""}, @@ -156,6 +157,8 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_SurfaceModifier; case eModifierType_Smoke: return &RNA_SmokeModifier; + case eModifierType_SmokeHR: + return &RNA_SmokeHRModifier; default: return &RNA_Modifier; } @@ -181,19 +184,30 @@ static void rna_Smoke_set_type(bContext *C, PointerRNA *ptr) { SmokeModifierData *smd= (SmokeModifierData *)ptr->data; Object *ob= (Object*)ptr->id.data; + + // nothing changed + if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) + return; smokeModifier_free(smd); // XXX TODO: completely free all 3 pointers smokeModifier_createType(smd); // create regarding of selected type - // particle_system_slot_add_exec(C, NULL); - // particle_system_slot_remove_exec(C, NULL); - if(smd->type == MOD_SMOKE_TYPE_DOMAIN) + if(smd->type & MOD_SMOKE_TYPE_DOMAIN) ob->dt = OB_WIRE; // update dependancy since a domain - other type switch could have happened rna_Modifier_dependency_update(C, ptr); } +static void rna_SmokeHR_reset(bContext *C, PointerRNA *ptr) +{ + // SmokeDomainSettings *settings = (SmokeDomainSettings*)ptr->data; + + // smokeModifier_reset(settings->smd); + + // rna_Smoke_update(C, ptr); +} + static void rna_ExplodeModifier_vgroup_get(PointerRNA *ptr, char *value) { ExplodeModifierData *emd= (ExplodeModifierData*)ptr->data; @@ -1499,6 +1513,55 @@ static void rna_def_modifier_cloth(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Point Cache", ""); } +static void rna_def_modifier_smoke_highresolution(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem prop_noise_type_items[] = { + {MOD_SMOKE_NOISEWAVE, "NOISEWAVE", 0, "Wavelet", ""}, +#if FFTW3 == 1 + {MOD_SMOKE_NOISEFFT, "NOISEFFT", 0, "FFT", ""}, +#endif + /* {MOD_SMOKE_NOISECURL, "NOISECURL", 0, "Curl", ""}, */ + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "SmokeHRModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Smoke High Resolution Modifier", "Smoke high resolution simulation modifier."); + RNA_def_struct_sdna(srna, "SmokeHRModifierData"); + + prop= RNA_def_property(srna, "show_highres", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_SHOWHIGHRES); + RNA_def_property_ui_text(prop, "High res", "Show high resolution (using amplification)."); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); + + prop= RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "noise"); + RNA_def_property_enum_items(prop, prop_noise_type_items); + RNA_def_property_ui_text(prop, "Noise Method", "Noise method which is used for creating the high resolution"); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_SmokeHR_reset"); + + prop= RNA_def_property(srna, "amplify", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "amplify"); + RNA_def_property_range(prop, 1, 10); + RNA_def_property_ui_range(prop, 1, 10, 1, 0); + RNA_def_property_ui_text(prop, "Amplification", "Enhance the resolution of smoke by this factor using noise."); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_SmokeHR_reset"); + + prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "strength"); + RNA_def_property_range(prop, 1.0, 10.0); + RNA_def_property_ui_range(prop, 1.0, 10.0, 1, 2); + RNA_def_property_ui_text(prop, "Strength", "Strength of wavelet noise"); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_SmokeHR_reset"); + + prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "point_cache"); + RNA_def_property_struct_type(prop, "PointCache"); + RNA_def_property_ui_text(prop, "Point Cache", ""); + +} + static void rna_def_modifier_smoke(BlenderRNA *brna) { StructRNA *srna; @@ -1915,6 +1978,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_multires(brna); rna_def_modifier_surface(brna); rna_def_modifier_smoke(brna); + rna_def_modifier_smoke_highresolution(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 6f1babb495a..a119eefa62c 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -78,11 +78,28 @@ static void rna_Smoke_reset_dependancy(bContext *C, PointerRNA *ptr) rna_Smoke_dependency_update(C, ptr); } +static void rna_Smoke_enable_HR(bContext *C, PointerRNA *ptr) +{ + SmokeDomainSettings *settings = (SmokeDomainSettings*)ptr->data; + Object *ob = (Object*)ptr->id.data; + + if(settings->flags & MOD_SMOKE_HIGHRES) + BLI_addtail(&ob->modifiers, modifier_new(eModifierType_SmokeHR)); + else + { + ModifierData *tmd = modifiers_findByType(ob, eModifierType_SmokeHR); + if(tmd) { + BLI_remlink(&ob->modifiers, tmd); + modifier_free(tmd); + } + } +} + static void rna_Smoke_redraw(bContext *C, PointerRNA *ptr) { SmokeDomainSettings *settings = (SmokeDomainSettings*)ptr->data; - settings->flags |= MOD_SMOKE_VIEW_REDRAWNICE; + // settings->flags |= MOD_SMOKE_VIEW_REDRAWNICE; } static char *rna_SmokeDomainSettings_path(PointerRNA *ptr) @@ -116,14 +133,6 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static EnumPropertyItem prop_noise_type_items[] = { - {MOD_SMOKE_NOISEWAVE, "NOISEWAVE", 0, "Wavelet", ""}, -#if FFTW3 == 1 - {MOD_SMOKE_NOISEFFT, "NOISEFFT", 0, "FFT", ""}, -#endif - /* {MOD_SMOKE_NOISECURL, "NOISECURL", 0, "Curl", ""}, */ - {0, NULL, 0, NULL, NULL}}; - srna = RNA_def_struct(brna, "SmokeDomainSettings", NULL); RNA_def_struct_ui_text(srna, "Domain Settings", "Smoke domain settings."); RNA_def_struct_sdna(srna, "SmokeDomainSettings"); @@ -136,56 +145,19 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Max Res", "Maximal resolution used in the fluid domain."); RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset"); - prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "omega"); - RNA_def_property_range(prop, 0.02, 1.0); - RNA_def_property_ui_range(prop, 0.02, 1.0, 0.02, 2); - RNA_def_property_ui_text(prop, "Color", "Smoke color (0 = black, 1 = white)."); - RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Smoke_redraw"); - - prop= RNA_def_property(srna, "amplify", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "amplify"); - RNA_def_property_range(prop, 1, 10); - RNA_def_property_ui_range(prop, 1, 10, 1, 0); - RNA_def_property_ui_text(prop, "Amplification", "Enhance the resolution of smoke by this factor using noise."); - RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset"); - - prop= RNA_def_property(srna, "highres", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGHRES); - RNA_def_property_ui_text(prop, "High res", "Enable high resolution (using amplification)."); - RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset"); - - prop= RNA_def_property(srna, "viewhighres", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "viewsettings", MOD_SMOKE_VIEW_USEBIG); - RNA_def_property_ui_text(prop, "Show High Resolution", "Show high resolution (using amplification)."); - RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_redraw"); - - prop= RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "noise"); - RNA_def_property_enum_items(prop, prop_noise_type_items); - RNA_def_property_ui_text(prop, "Noise Method", "Noise method which is used for creating the high resolution"); - RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset"); - - prop= RNA_def_property(srna, "visibility", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "visibility"); - RNA_def_property_range(prop, 1, 15); - RNA_def_property_ui_range(prop, 1, 15, 1, 0); - RNA_def_property_ui_text(prop, "Display", "How much of the resolution should be shown during preview (every 2nd, 3rd, etc)."); - RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Smoke_redraw"); - prop= RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "alpha"); RNA_def_property_range(prop, -5.0, 5.0); RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5); RNA_def_property_ui_text(prop, "Gravity", "Higher value results in sinking smoke"); - RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL); prop= RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "beta"); RNA_def_property_range(prop, -5.0, 5.0); RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5); RNA_def_property_ui_text(prop, "Heat", "Higher value results in faster rising smoke."); - RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL); prop= RNA_def_property(srna, "coll_group", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "coll_group"); @@ -208,13 +180,6 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this group."); RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset_dependancy"); - prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "strength"); - RNA_def_property_range(prop, 1.0, 10.0); - RNA_def_property_ui_range(prop, 1.0, 10.0, 1, 2); - RNA_def_property_ui_text(prop, "Strength", "Strength of wavelet noise"); - RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset"); - prop= RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "diss_speed"); RNA_def_property_range(prop, 1.0, 100.0); @@ -222,6 +187,11 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed"); RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL); + prop= RNA_def_property(srna, "highres", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGHRES); + RNA_def_property_ui_text(prop, "High Resolution Smoke", "Enable high resolution smoke"); + RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_enable_HR"); + prop= RNA_def_property(srna, "dissolve_smoke", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE); RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time."); @@ -231,6 +201,11 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE_LOG); RNA_def_property_ui_text(prop, "Logarithmic dissolve", "Using 1/x "); RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, NULL); + + prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "point_cache"); + RNA_def_property_struct_type(prop, "PointCache"); + RNA_def_property_ui_text(prop, "Point Cache", ""); } static void rna_def_smoke_flow_settings(BlenderRNA *brna) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 3a2cef2d038..3b95c409b30 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -319,6 +319,8 @@ IF(UNIX) bf_dummy bf_bullet bf_smoke + bf_minilzo + bf_lzma bf_common bf_ketsji bf_logic |