2011-02-23 10:52:22 +00:00
/*
2009-07-30 15:00:26 +00:00
* * * * * * 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 ,
2010-02-12 13:34:04 +00:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2009-07-30 15:00:26 +00:00
*
* The Original Code is Copyright ( C ) Blender Foundation .
* All rights reserved .
*
* The Original Code is : all of this file .
*
* Contributor ( s ) : Daniel Genrich
2012-04-28 21:46:43 +00:00
* Blender Foundation
2009-07-30 15:00:26 +00:00
*
* * * * * * END GPL LICENSE BLOCK * * * * *
*/
2011-02-27 20:40:57 +00:00
/** \file blender/blenkernel/intern/smoke.c
* \ ingroup bke
*/
2009-07-30 20:12:40 +00:00
/* Part of the code copied from elbeem fluid library, copyright by Nils Thuerey */
2009-07-30 15:00:26 +00:00
# include <GL/glew.h>
# include "MEM_guardedalloc.h"
# include <float.h>
# include <math.h>
2010-08-13 15:26:37 +00:00
# include <stdio.h>
# include <string.h> /* memset */
2009-07-30 15:00:26 +00:00
# include "BLI_linklist.h"
# include "BLI_rand.h"
# include "BLI_jitter.h"
# include "BLI_blenlib.h"
2009-11-10 20:43:45 +00:00
# include "BLI_math.h"
2009-07-30 15:00:26 +00:00
# include "BLI_edgehash.h"
# include "BLI_kdtree.h"
# include "BLI_kdopbvh.h"
2012-02-17 21:22:18 +00:00
# include "BLI_utildefines.h"
2009-07-30 15:00:26 +00:00
2009-08-03 16:39:12 +00:00
# include "BKE_bvhutils.h"
2009-07-30 15:00:26 +00:00
# include "BKE_cdderivedmesh.h"
2012-04-28 21:46:43 +00:00
# include "BKE_collision.h"
2009-07-30 15:00:26 +00:00
# include "BKE_customdata.h"
# include "BKE_DerivedMesh.h"
2009-10-22 23:22:05 +00:00
# include "BKE_effect.h"
2009-07-30 15:00:26 +00:00
# include "BKE_modifier.h"
# include "BKE_particle.h"
2009-08-20 00:33:59 +00:00
# include "BKE_pointcache.h"
# include "BKE_smoke.h"
2011-01-07 19:18:31 +00:00
2009-07-30 15:00:26 +00:00
# include "DNA_customdata_types.h"
# include "DNA_group_types.h"
2009-08-20 00:33:59 +00:00
# include "DNA_lamp_types.h"
2009-07-30 15:00:26 +00:00
# include "DNA_mesh_types.h"
# include "DNA_meshdata_types.h"
# include "DNA_modifier_types.h"
# include "DNA_object_types.h"
# include "DNA_particle_types.h"
# include "DNA_scene_types.h"
# include "DNA_smoke_types.h"
# include "BKE_smoke.h"
2012-01-24 01:21:43 +00:00
/* UNUSED so far, may be enabled later */
/* #define USE_SMOKE_COLLISION_DM */
2011-11-01 22:51:10 +00:00
# ifdef WITH_SMOKE
2012-03-27 00:17:57 +00:00
# include "smoke_API.h"
2009-07-30 15:00:26 +00:00
# ifdef _WIN32
# include <time.h>
# include <stdio.h>
# include <conio.h>
# include <windows.h>
static LARGE_INTEGER liFrequency ;
static LARGE_INTEGER liStartTime ;
static LARGE_INTEGER liCurrentTime ;
static void tstart ( void )
{
QueryPerformanceFrequency ( & liFrequency ) ;
QueryPerformanceCounter ( & liStartTime ) ;
}
static void tend ( void )
{
QueryPerformanceCounter ( & liCurrentTime ) ;
}
2012-05-21 06:33:45 +00:00
static double UNUSED_FUNCTION ( tval ) ( void )
2009-09-16 17:43:09 +00:00
{
return ( ( double ) ( ( liCurrentTime . QuadPart - liStartTime . QuadPart ) * ( double ) 1000.0 / ( double ) liFrequency . QuadPart ) ) ;
}
2009-07-30 15:00:26 +00:00
# else
# include <sys/time.h>
static struct timeval _tstart , _tend ;
static struct timezone tz ;
static void tstart ( void )
{
gettimeofday ( & _tstart , & tz ) ;
}
static void tend ( void )
{
gettimeofday ( & _tend , & tz ) ;
}
2010-12-03 01:52:28 +00:00
2012-05-21 06:33:45 +00:00
static double UNUSED_FUNCTION ( tval ) ( void )
2009-07-30 15:00:26 +00:00
{
double t1 , t2 ;
t1 = ( double ) _tstart . tv_sec * 1000 + ( double ) _tstart . tv_usec / ( 1000 ) ;
t2 = ( double ) _tend . tv_sec * 1000 + ( double ) _tend . tv_usec / ( 1000 ) ;
return t2 - t1 ;
}
# endif
struct Object ;
struct Scene ;
struct DerivedMesh ;
struct SmokeModifierData ;
2012-04-28 21:46:43 +00:00
# define TRI_UVOFFSET (1. / 4.)
// timestep default value for nice appearance 0.1f
# define DT_DEFAULT 0.1f
2009-07-30 15:00:26 +00:00
2011-10-21 00:48:02 +00:00
/* forward declerations */
static void calcTriangleDivs ( Object * ob , MVert * verts , int numverts , MFace * tris , int numfaces , int numtris , int * * tridivs , float cell_len ) ;
static void get_cell ( float * p0 , int res [ 3 ] , float dx , float * pos , int * cell , int correct ) ;
static void fill_scs_points ( Object * ob , DerivedMesh * dm , SmokeCollSettings * scs ) ;
2011-11-01 22:51:10 +00:00
2011-10-21 00:48:02 +00:00
# else /* WITH_SMOKE */
2011-11-01 22:51:10 +00:00
2011-07-13 18:40:21 +00:00
/* Stubs to use when smoke is disabled */
struct WTURBULENCE * smoke_turbulence_init ( int * UNUSED ( res ) , int UNUSED ( amplify ) , int UNUSED ( noisetype ) ) { return NULL ; }
struct FLUID_3D * smoke_init ( int * UNUSED ( res ) , float * UNUSED ( p0 ) ) { return NULL ; }
void smoke_free ( struct FLUID_3D * UNUSED ( fluid ) ) { }
void smoke_turbulence_free ( struct WTURBULENCE * UNUSED ( wt ) ) { }
void smoke_initWaveletBlenderRNA ( struct WTURBULENCE * UNUSED ( wt ) , float * UNUSED ( strength ) ) { }
void smoke_initBlenderRNA ( struct FLUID_3D * UNUSED ( fluid ) , float * UNUSED ( alpha ) , float * UNUSED ( beta ) , float * UNUSED ( dt_factor ) , float * UNUSED ( vorticity ) , int * UNUSED ( border_colli ) ) { }
long long smoke_get_mem_req ( int UNUSED ( xres ) , int UNUSED ( yres ) , int UNUSED ( zres ) , int UNUSED ( amplify ) ) { return 0 ; }
void smokeModifier_do ( SmokeModifierData * UNUSED ( smd ) , Scene * UNUSED ( scene ) , Object * UNUSED ( ob ) , DerivedMesh * UNUSED ( dm ) ) { }
2011-11-01 22:51:10 +00:00
2011-10-21 00:48:02 +00:00
# endif /* WITH_SMOKE */
2011-07-13 18:40:21 +00:00
2011-10-21 00:48:02 +00:00
# ifdef WITH_SMOKE
2011-11-01 22:51:10 +00:00
2011-02-14 17:55:27 +00:00
static int smokeModifier_init ( SmokeModifierData * smd , Object * ob , Scene * scene , DerivedMesh * dm )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( ( smd - > type & MOD_SMOKE_TYPE_DOMAIN ) & & smd - > domain & & ! smd - > domain - > fluid )
2009-07-30 15:00:26 +00:00
{
size_t i ;
float min [ 3 ] = { FLT_MAX , FLT_MAX , FLT_MAX } , max [ 3 ] = { - FLT_MAX , - FLT_MAX , - FLT_MAX } ;
float size [ 3 ] ;
MVert * verts = dm - > getVertArray ( dm ) ;
float scale = 0.0 ;
2009-08-03 16:39:12 +00:00
int res ;
res = smd - > domain - > maxres ;
2009-07-30 15:00:26 +00:00
// get BB of domain
2012-04-28 21:46:43 +00:00
for ( i = 0 ; i < dm - > getNumVerts ( dm ) ; i + + )
2009-07-30 15:00:26 +00:00
{
float tmp [ 3 ] ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( tmp , verts [ i ] . co ) ;
2009-11-10 20:43:45 +00:00
mul_m4_v3 ( ob - > obmat , tmp ) ;
2009-07-30 15:00:26 +00:00
// min BB
min [ 0 ] = MIN2 ( min [ 0 ] , tmp [ 0 ] ) ;
min [ 1 ] = MIN2 ( min [ 1 ] , tmp [ 1 ] ) ;
min [ 2 ] = MIN2 ( min [ 2 ] , tmp [ 2 ] ) ;
// max BB
max [ 0 ] = MAX2 ( max [ 0 ] , tmp [ 0 ] ) ;
max [ 1 ] = MAX2 ( max [ 1 ] , tmp [ 1 ] ) ;
max [ 2 ] = MAX2 ( max [ 2 ] , tmp [ 2 ] ) ;
}
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( smd - > domain - > p0 , min ) ;
copy_v3_v3 ( smd - > domain - > p1 , max ) ;
2009-07-30 15:00:26 +00:00
// calc other res with max_res provided
2011-11-06 15:39:20 +00:00
sub_v3_v3v3 ( size , max , min ) ;
2009-08-25 23:39:49 +00:00
2009-09-16 17:43:09 +00:00
// prevent crash when initializing a plane as domain
2012-04-28 21:46:43 +00:00
if ( ( size [ 0 ] < FLT_EPSILON ) | | ( size [ 1 ] < FLT_EPSILON ) | | ( size [ 2 ] < FLT_EPSILON ) )
2009-08-25 23:39:49 +00:00
return 0 ;
2012-04-28 21:46:43 +00:00
if ( size [ 0 ] > size [ 1 ] )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( size [ 0 ] > size [ 2 ] )
2009-07-30 15:00:26 +00:00
{
scale = res / size [ 0 ] ;
2012-05-24 23:50:20 +00:00
smd - > domain - > scale = size [ 0 ] ;
smd - > domain - > dx = 1.0f / res ;
2009-07-30 15:00:26 +00:00
smd - > domain - > res [ 0 ] = res ;
smd - > domain - > res [ 1 ] = ( int ) ( size [ 1 ] * scale + 0.5 ) ;
smd - > domain - > res [ 2 ] = ( int ) ( size [ 2 ] * scale + 0.5 ) ;
}
2012-03-06 18:40:15 +00:00
else {
2010-11-25 22:13:40 +00:00
scale = res / size [ 2 ] ;
2012-05-24 23:50:20 +00:00
smd - > domain - > scale = size [ 2 ] ;
smd - > domain - > dx = 1.0f / res ;
2010-11-25 22:13:40 +00:00
smd - > domain - > res [ 2 ] = res ;
2009-07-30 15:00:26 +00:00
smd - > domain - > res [ 0 ] = ( int ) ( size [ 0 ] * scale + 0.5 ) ;
2010-11-25 22:13:40 +00:00
smd - > domain - > res [ 1 ] = ( int ) ( size [ 1 ] * scale + 0.5 ) ;
2009-07-30 15:00:26 +00:00
}
}
2012-03-06 18:40:15 +00:00
else {
2012-04-28 21:46:43 +00:00
if ( size [ 1 ] > size [ 2 ] )
2009-07-30 15:00:26 +00:00
{
scale = res / size [ 1 ] ;
2012-05-24 23:50:20 +00:00
smd - > domain - > scale = size [ 1 ] ;
smd - > domain - > dx = 1.0f / res ;
2009-07-30 15:00:26 +00:00
smd - > domain - > res [ 1 ] = res ;
smd - > domain - > res [ 0 ] = ( int ) ( size [ 0 ] * scale + 0.5 ) ;
smd - > domain - > res [ 2 ] = ( int ) ( size [ 2 ] * scale + 0.5 ) ;
}
2012-03-06 18:40:15 +00:00
else {
2009-07-30 15:00:26 +00:00
scale = res / size [ 2 ] ;
2012-05-24 23:50:20 +00:00
smd - > domain - > scale = size [ 2 ] ;
smd - > domain - > dx = 1.0f / res ;
2009-07-30 15:00:26 +00:00
smd - > domain - > res [ 2 ] = res ;
smd - > domain - > res [ 0 ] = ( int ) ( size [ 0 ] * scale + 0.5 ) ;
smd - > domain - > res [ 1 ] = ( int ) ( size [ 1 ] * scale + 0.5 ) ;
}
}
2009-08-02 23:30:44 +00:00
// TODO: put in failsafe if res<=0 - dg
2009-07-30 15:00:26 +00:00
// dt max is 0.1
2012-04-28 21:46:43 +00:00
smd - > domain - > fluid = smoke_init ( smd - > domain - > res , smd - > domain - > p0 , DT_DEFAULT ) ;
2009-07-30 15:00:26 +00:00
smd - > time = scene - > r . cfra ;
2009-08-25 21:53:52 +00:00
2012-04-28 21:46:43 +00:00
if ( smd - > domain - > flags & MOD_SMOKE_HIGHRES )
2009-08-20 00:33:59 +00:00
{
2009-09-16 17:43:09 +00:00
smd - > domain - > wt = smoke_turbulence_init ( smd - > domain - > res , smd - > domain - > amplify + 1 , smd - > domain - > noise ) ;
smd - > domain - > res_wt [ 0 ] = smd - > domain - > res [ 0 ] * ( smd - > domain - > amplify + 1 ) ;
smd - > domain - > res_wt [ 1 ] = smd - > domain - > res [ 1 ] * ( smd - > domain - > amplify + 1 ) ;
smd - > domain - > res_wt [ 2 ] = smd - > domain - > res [ 2 ] * ( smd - > domain - > amplify + 1 ) ;
smd - > domain - > dx_wt = smd - > domain - > dx / ( smd - > domain - > amplify + 1 ) ;
2009-08-20 00:33:59 +00:00
}
2012-04-28 21:46:43 +00:00
if ( ! smd - > domain - > shadow )
2009-09-16 17:43:09 +00:00
smd - > domain - > shadow = MEM_callocN ( sizeof ( float ) * smd - > domain - > res [ 0 ] * smd - > domain - > res [ 1 ] * smd - > domain - > res [ 2 ] , " SmokeDomainShadow " ) ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
smoke_initBlenderRNA ( smd - > domain - > fluid , & ( smd - > domain - > alpha ) , & ( smd - > domain - > beta ) , & ( smd - > domain - > time_scale ) , & ( smd - > domain - > vorticity ) , & ( smd - > domain - > border_collisions ) ) ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( smd - > domain - > wt )
2009-09-16 17:43:09 +00:00
{
smoke_initWaveletBlenderRNA ( smd - > domain - > wt , & ( smd - > domain - > strength ) ) ;
}
2009-07-30 15:00:26 +00:00
return 1 ;
}
2012-04-28 21:46:43 +00:00
else if ( ( smd - > type & MOD_SMOKE_TYPE_FLOW ) & & smd - > flow )
2009-07-30 15:00:26 +00:00
{
// handle flow object here
// XXX TODO
smd - > time = scene - > r . cfra ;
return 1 ;
}
2012-04-28 21:46:43 +00:00
else if ( ( smd - > type & MOD_SMOKE_TYPE_COLL ) )
2009-07-30 15:00:26 +00:00
{
2009-08-02 23:30:44 +00:00
// todo: delete this when loading colls work -dg
2012-04-28 21:46:43 +00:00
if ( ! smd - > coll )
{
2009-08-02 23:30:44 +00:00
smokeModifier_createType ( smd ) ;
2012-04-28 21:46:43 +00:00
}
2009-08-02 23:30:44 +00:00
2012-04-28 21:46:43 +00:00
if ( ! smd - > coll - > points )
2009-07-30 15:00:26 +00:00
{
// init collision points
SmokeCollSettings * scs = smd - > coll ;
2012-04-28 21:46:43 +00:00
smd - > time = scene - > r . cfra ;
2009-08-06 16:50:02 +00:00
// copy obmat
2009-11-10 20:43:45 +00:00
copy_m4_m4 ( scs - > mat , ob - > obmat ) ;
copy_m4_m4 ( scs - > mat_old , ob - > obmat ) ;
2009-08-06 16:50:02 +00:00
2012-03-20 20:32:17 +00:00
DM_ensure_tessface ( dm ) ;
2009-10-22 23:22:05 +00:00
fill_scs_points ( ob , dm , scs ) ;
}
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( ! smd - > coll - > bvhtree )
2009-10-22 23:22:05 +00:00
{
smd - > coll - > bvhtree = NULL ; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
}
return 1 ;
}
2009-07-30 15:00:26 +00:00
2010-08-01 15:00:53 +00:00
return 2 ;
2009-10-22 23:22:05 +00:00
}
static void fill_scs_points ( Object * ob , DerivedMesh * dm , SmokeCollSettings * scs )
{
MVert * mvert = dm - > getVertArray ( dm ) ;
MFace * mface = dm - > getTessFaceArray ( dm ) ;
int i = 0 , divs = 0 ;
2012-04-28 21:46:43 +00:00
// DG TODO: need to do this dynamically according to the domain object!
float cell_len = scs - > dx ;
2009-10-22 23:22:05 +00:00
int newdivs = 0 ;
int quads = 0 , facecounter = 0 ;
// count quads
2012-04-28 21:46:43 +00:00
for ( i = 0 ; i < dm - > getNumTessFaces ( dm ) ; i + + )
2009-10-22 23:22:05 +00:00
{
2012-04-28 21:46:43 +00:00
if ( mface [ i ] . v4 )
2009-10-22 23:22:05 +00:00
quads + + ;
}
2012-04-28 21:46:43 +00:00
scs - > numtris = dm - > getNumTessFaces ( dm ) + quads ;
scs - > tridivs = NULL ;
calcTriangleDivs ( ob , mvert , dm - > getNumVerts ( dm ) , mface , dm - > getNumTessFaces ( dm ) , scs - > numtris , & ( scs - > tridivs ) , cell_len ) ;
2009-10-22 23:22:05 +00:00
// count triangle divisions
2012-04-28 21:46:43 +00:00
for ( i = 0 ; i < dm - > getNumTessFaces ( dm ) + quads ; i + + )
2009-10-22 23:22:05 +00:00
{
2012-04-28 21:46:43 +00:00
divs + = ( scs - > tridivs [ 3 * i ] + 1 ) * ( scs - > tridivs [ 3 * i + 1 ] + 1 ) * ( scs - > tridivs [ 3 * i + 2 ] + 1 ) ;
2009-10-22 23:22:05 +00:00
}
2009-07-30 15:00:26 +00:00
2009-10-22 23:22:05 +00:00
scs - > points = MEM_callocN ( sizeof ( float ) * ( dm - > getNumVerts ( dm ) + divs ) * 3 , " SmokeCollPoints " ) ;
2012-04-28 21:46:43 +00:00
scs - > points_old = MEM_callocN ( sizeof ( float ) * ( dm - > getNumVerts ( dm ) + divs ) * 3 , " SmokeCollPointsOld " ) ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
for ( i = 0 ; i < dm - > getNumVerts ( dm ) ; i + + )
2009-10-22 23:22:05 +00:00
{
float tmpvec [ 3 ] ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( tmpvec , mvert [ i ] . co ) ;
2012-04-28 21:46:43 +00:00
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( & scs - > points [ i * 3 ] , tmpvec ) ;
2009-10-22 23:22:05 +00:00
}
2012-04-28 21:46:43 +00:00
for ( i = 0 , facecounter = 0 ; i < dm - > getNumTessFaces ( dm ) ; i + + )
2009-10-22 23:22:05 +00:00
{
int again = 0 ;
do
{
int j , k ;
2012-04-28 21:46:43 +00:00
int divs1 = scs - > tridivs [ 3 * facecounter + 0 ] ;
int divs2 = scs - > tridivs [ 3 * facecounter + 1 ] ;
//int divs3 = scs->tridivs[3 * facecounter + 2];
2009-10-22 23:22:05 +00:00
float side1 [ 3 ] , side2 [ 3 ] , trinormorg [ 3 ] , trinorm [ 3 ] ;
2012-04-28 21:46:43 +00:00
if ( again = = 1 & & mface [ i ] . v4 )
2009-07-30 15:00:26 +00:00
{
2011-11-06 15:39:20 +00:00
sub_v3_v3v3 ( side1 , mvert [ mface [ i ] . v3 ] . co , mvert [ mface [ i ] . v1 ] . co ) ;
sub_v3_v3v3 ( side2 , mvert [ mface [ i ] . v4 ] . co , mvert [ mface [ i ] . v1 ] . co ) ;
2009-07-30 15:00:26 +00:00
}
2012-03-06 18:40:15 +00:00
else {
2011-11-06 15:39:20 +00:00
sub_v3_v3v3 ( side1 , mvert [ mface [ i ] . v2 ] . co , mvert [ mface [ i ] . v1 ] . co ) ;
sub_v3_v3v3 ( side2 , mvert [ mface [ i ] . v3 ] . co , mvert [ mface [ i ] . v1 ] . co ) ;
2009-10-22 23:22:05 +00:00
}
2009-11-10 20:43:45 +00:00
cross_v3_v3v3 ( trinormorg , side1 , side2 ) ;
normalize_v3 ( trinormorg ) ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( trinorm , trinormorg ) ;
2009-11-10 20:43:45 +00:00
mul_v3_fl ( trinorm , 0.25 * cell_len ) ;
2009-10-22 23:22:05 +00:00
2012-04-28 21:46:43 +00:00
for ( j = 0 ; j < = divs1 ; j + + )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
for ( k = 0 ; k < = divs2 ; k + + )
2009-07-30 15:00:26 +00:00
{
2009-10-22 23:22:05 +00:00
float p1 [ 3 ] , p2 [ 3 ] , p3 [ 3 ] , p [ 3 ] = { 0 , 0 , 0 } ;
const float uf = ( float ) ( j + TRI_UVOFFSET ) / ( float ) ( divs1 + 0.0 ) ;
const float vf = ( float ) ( k + TRI_UVOFFSET ) / ( float ) ( divs2 + 0.0 ) ;
float tmpvec [ 3 ] ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( uf + vf > 1.0 )
2009-07-30 15:00:26 +00:00
{
2009-10-22 23:22:05 +00:00
// printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
continue ;
2009-07-30 15:00:26 +00:00
}
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p1 , mvert [ mface [ i ] . v1 ] . co ) ;
2012-04-28 21:46:43 +00:00
if ( again = = 1 & & mface [ i ] . v4 )
2009-07-30 15:00:26 +00:00
{
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p2 , mvert [ mface [ i ] . v3 ] . co ) ;
copy_v3_v3 ( p3 , mvert [ mface [ i ] . v4 ] . co ) ;
2009-07-30 15:00:26 +00:00
}
2012-03-06 18:40:15 +00:00
else {
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p2 , mvert [ mface [ i ] . v2 ] . co ) ;
copy_v3_v3 ( p3 , mvert [ mface [ i ] . v3 ] . co ) ;
2009-10-22 23:22:05 +00:00
}
2009-07-30 15:00:26 +00:00
2009-11-10 20:43:45 +00:00
mul_v3_fl ( p1 , ( 1.0 - uf - vf ) ) ;
mul_v3_fl ( p2 , uf ) ;
mul_v3_fl ( p3 , vf ) ;
2009-10-22 23:22:05 +00:00
2011-11-06 15:39:20 +00:00
add_v3_v3v3 ( p , p1 , p2 ) ;
add_v3_v3 ( p , p3 ) ;
2009-10-22 23:22:05 +00:00
2012-04-28 21:46:43 +00:00
if ( newdivs > divs )
2009-10-22 23:22:05 +00:00
printf ( " mem problem \n " ) ;
// mMovPoints.push_back(p + trinorm);
2011-11-06 15:39:20 +00:00
add_v3_v3v3 ( tmpvec , p , trinorm ) ;
2012-04-28 21:46:43 +00:00
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( & scs - > points [ 3 * ( dm - > getNumVerts ( dm ) + newdivs ) ] , tmpvec ) ;
2009-10-22 23:22:05 +00:00
newdivs + + ;
2012-04-28 21:46:43 +00:00
if ( newdivs > divs )
2009-10-22 23:22:05 +00:00
printf ( " mem problem \n " ) ;
// mMovPoints.push_back(p - trinorm);
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( tmpvec , p ) ;
sub_v3_v3 ( tmpvec , trinorm ) ;
2012-04-28 21:46:43 +00:00
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( & scs - > points [ 3 * ( dm - > getNumVerts ( dm ) + newdivs ) ] , tmpvec ) ;
2009-10-22 23:22:05 +00:00
newdivs + + ;
}
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
if ( again = = 0 & & mface [ i ] . v4 )
2009-10-22 23:22:05 +00:00
again + + ;
else
again = 0 ;
2009-07-30 15:00:26 +00:00
2009-10-22 23:22:05 +00:00
facecounter + + ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
} while ( again ! = 0 ) ;
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
scs - > numverts = dm - > getNumVerts ( dm ) ;
// DG TODO: also save triangle count?
2009-10-22 23:22:05 +00:00
scs - > numpoints = dm - > getNumVerts ( dm ) + newdivs ;
2012-04-28 21:46:43 +00:00
for ( i = 0 ; i < scs - > numpoints * 3 ; i + + )
{
scs - > points_old [ i ] = scs - > points [ i ] ;
}
}
2012-04-29 09:34:51 +00:00
static void fill_scs_points_anim ( Object * UNUSED ( ob ) , DerivedMesh * dm , SmokeCollSettings * scs )
2012-04-28 21:46:43 +00:00
{
MVert * mvert = dm - > getVertArray ( dm ) ;
MFace * mface = dm - > getTessFaceArray ( dm ) ;
int quads = 0 , numtris = 0 , facecounter = 0 ;
unsigned int i = 0 ;
int divs = 0 , newdivs = 0 ;
// DG TODO: need to do this dynamically according to the domain object!
float cell_len = scs - > dx ;
// count quads
for ( i = 0 ; i < dm - > getNumTessFaces ( dm ) ; i + + )
{
if ( mface [ i ] . v4 )
quads + + ;
}
numtris = dm - > getNumTessFaces ( dm ) + quads ;
// check if mesh changed topology
if ( scs - > numtris ! = numtris )
return ;
if ( scs - > numverts ! = dm - > getNumVerts ( dm ) )
return ;
// update new positions
for ( i = 0 ; i < dm - > getNumVerts ( dm ) ; i + + )
{
float tmpvec [ 3 ] ;
copy_v3_v3 ( tmpvec , mvert [ i ] . co ) ;
copy_v3_v3 ( & scs - > points [ i * 3 ] , tmpvec ) ;
}
// for every triangle // update div points
for ( i = 0 , facecounter = 0 ; i < dm - > getNumTessFaces ( dm ) ; i + + )
{
int again = 0 ;
do
{
int j , k ;
int divs1 = scs - > tridivs [ 3 * facecounter + 0 ] ;
int divs2 = scs - > tridivs [ 3 * facecounter + 1 ] ;
float srcside1 [ 3 ] , srcside2 [ 3 ] , destside1 [ 3 ] , destside2 [ 3 ] , src_trinormorg [ 3 ] , dest_trinormorg [ 3 ] , src_trinorm [ 3 ] , dest_trinorm [ 3 ] ;
if ( again = = 1 & & mface [ i ] . v4 )
{
sub_v3_v3v3 ( srcside1 , & scs - > points_old [ mface [ i ] . v3 * 3 ] , & scs - > points_old [ mface [ i ] . v1 * 3 ] ) ;
sub_v3_v3v3 ( destside1 , & scs - > points [ mface [ i ] . v3 * 3 ] , & scs - > points [ mface [ i ] . v1 * 3 ] ) ;
sub_v3_v3v3 ( srcside2 , & scs - > points_old [ mface [ i ] . v4 * 3 ] , & scs - > points_old [ mface [ i ] . v1 * 3 ] ) ;
sub_v3_v3v3 ( destside2 , & scs - > points [ mface [ i ] . v4 * 3 ] , & scs - > points [ mface [ i ] . v1 * 3 ] ) ;
}
else {
sub_v3_v3v3 ( srcside1 , & scs - > points_old [ mface [ i ] . v2 * 3 ] , & scs - > points_old [ mface [ i ] . v1 * 3 ] ) ;
sub_v3_v3v3 ( destside1 , & scs - > points [ mface [ i ] . v2 * 3 ] , & scs - > points [ mface [ i ] . v1 * 3 ] ) ;
sub_v3_v3v3 ( srcside2 , & scs - > points_old [ mface [ i ] . v3 * 3 ] , & scs - > points_old [ mface [ i ] . v1 * 3 ] ) ;
sub_v3_v3v3 ( destside2 , & scs - > points [ mface [ i ] . v3 * 3 ] , & scs - > points [ mface [ i ] . v1 * 3 ] ) ;
}
cross_v3_v3v3 ( src_trinormorg , srcside1 , srcside2 ) ;
cross_v3_v3v3 ( dest_trinormorg , destside1 , destside2 ) ;
normalize_v3 ( src_trinormorg ) ;
normalize_v3 ( dest_trinormorg ) ;
copy_v3_v3 ( src_trinorm , src_trinormorg ) ;
copy_v3_v3 ( dest_trinorm , dest_trinormorg ) ;
mul_v3_fl ( src_trinorm , 0.25 * cell_len ) ;
mul_v3_fl ( dest_trinorm , 0.25 * cell_len ) ;
for ( j = 0 ; j < = divs1 ; j + + )
{
for ( k = 0 ; k < = divs2 ; k + + )
{
float src_p1 [ 3 ] , src_p2 [ 3 ] , src_p3 [ 3 ] , src_p [ 3 ] = { 0 , 0 , 0 } ;
float dest_p1 [ 3 ] , dest_p2 [ 3 ] , dest_p3 [ 3 ] , dest_p [ 3 ] = { 0 , 0 , 0 } ;
const float uf = ( float ) ( j + TRI_UVOFFSET ) / ( float ) ( divs1 + 0.0 ) ;
const float vf = ( float ) ( k + TRI_UVOFFSET ) / ( float ) ( divs2 + 0.0 ) ;
float src_tmpvec [ 3 ] , dest_tmpvec [ 3 ] ;
if ( uf + vf > 1.0 )
{
// printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
continue ;
}
copy_v3_v3 ( src_p1 , & scs - > points_old [ mface [ i ] . v1 * 3 ] ) ;
copy_v3_v3 ( dest_p1 , & scs - > points [ mface [ i ] . v1 * 3 ] ) ;
if ( again = = 1 & & mface [ i ] . v4 )
{
copy_v3_v3 ( src_p2 , & scs - > points_old [ mface [ i ] . v3 * 3 ] ) ;
copy_v3_v3 ( dest_p2 , & scs - > points [ mface [ i ] . v3 * 3 ] ) ;
copy_v3_v3 ( src_p3 , & scs - > points_old [ mface [ i ] . v4 * 3 ] ) ;
copy_v3_v3 ( dest_p3 , & scs - > points [ mface [ i ] . v4 * 3 ] ) ;
}
else {
copy_v3_v3 ( src_p2 , & scs - > points_old [ mface [ i ] . v2 * 3 ] ) ;
copy_v3_v3 ( dest_p2 , & scs - > points [ mface [ i ] . v2 * 3 ] ) ;
copy_v3_v3 ( src_p3 , & scs - > points_old [ mface [ i ] . v3 * 3 ] ) ;
copy_v3_v3 ( dest_p3 , & scs - > points [ mface [ i ] . v3 * 3 ] ) ;
}
mul_v3_fl ( src_p1 , ( 1.0 - uf - vf ) ) ;
mul_v3_fl ( dest_p1 , ( 1.0 - uf - vf ) ) ;
mul_v3_fl ( src_p2 , uf ) ;
mul_v3_fl ( dest_p2 , uf ) ;
mul_v3_fl ( src_p3 , vf ) ;
mul_v3_fl ( dest_p3 , vf ) ;
add_v3_v3v3 ( src_p , src_p1 , src_p2 ) ;
add_v3_v3v3 ( dest_p , dest_p1 , dest_p2 ) ;
add_v3_v3 ( src_p , src_p3 ) ;
add_v3_v3 ( dest_p , dest_p3 ) ;
if ( newdivs > divs )
printf ( " mem problem \n " ) ;
// mMovPoints.push_back(p + trinorm);
add_v3_v3v3 ( src_tmpvec , src_p , src_trinorm ) ;
add_v3_v3v3 ( dest_tmpvec , dest_p , dest_trinorm ) ;
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
copy_v3_v3 ( & scs - > points_old [ 3 * ( dm - > getNumVerts ( dm ) + newdivs ) ] , src_tmpvec ) ;
copy_v3_v3 ( & scs - > points [ 3 * ( dm - > getNumVerts ( dm ) + newdivs ) ] , dest_tmpvec ) ;
newdivs + + ;
if ( newdivs > divs )
printf ( " mem problem \n " ) ;
// mMovPoints.push_back(p - trinorm);
copy_v3_v3 ( src_tmpvec , src_p ) ;
copy_v3_v3 ( dest_tmpvec , dest_p ) ;
sub_v3_v3 ( src_tmpvec , src_trinorm ) ;
sub_v3_v3 ( dest_tmpvec , dest_trinorm ) ;
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
copy_v3_v3 ( & scs - > points_old [ 3 * ( dm - > getNumVerts ( dm ) + newdivs ) ] , src_tmpvec ) ;
copy_v3_v3 ( & scs - > points [ 3 * ( dm - > getNumVerts ( dm ) + newdivs ) ] , dest_tmpvec ) ;
newdivs + + ;
}
}
if ( again = = 0 & & mface [ i ] . v4 )
again + + ;
else
again = 0 ;
facecounter + + ;
} while ( again ! = 0 ) ;
}
// scs->numpoints = dm->getNumVerts(dm) + newdivs;
2009-07-30 15:00:26 +00:00
}
/*! init triangle divisions */
2011-10-21 00:48:02 +00:00
static void calcTriangleDivs ( Object * ob , MVert * verts , int UNUSED ( numverts ) , MFace * faces , int numfaces , int numtris , int * * tridivs , float cell_len )
2009-07-30 15:00:26 +00:00
{
// mTriangleDivs1.resize( faces.size() );
// mTriangleDivs2.resize( faces.size() );
// mTriangleDivs3.resize( faces.size() );
size_t i = 0 , facecounter = 0 ;
2012-04-28 21:46:43 +00:00
float maxscale [ 3 ] = { 1 , 1 , 1 } ; // = channelFindMaxVf(mcScale); get max scale value
2009-07-30 15:00:26 +00:00
float maxpart = ABS ( maxscale [ 0 ] ) ;
float scaleFac = 0 ;
float fsTri = 0 ;
2012-04-28 21:46:43 +00:00
if ( ABS ( maxscale [ 1 ] ) > maxpart ) maxpart = ABS ( maxscale [ 1 ] ) ;
if ( ABS ( maxscale [ 2 ] ) > maxpart ) maxpart = ABS ( maxscale [ 2 ] ) ;
2009-07-30 15:00:26 +00:00
scaleFac = 1.0 / maxpart ;
// featureSize = mLevel[mMaxRefine].nodeSize
2012-04-28 21:46:43 +00:00
fsTri = cell_len * 0.75 * scaleFac ; // fsTri = cell_len * 0.9;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( * tridivs )
2009-07-30 15:00:26 +00:00
MEM_freeN ( * tridivs ) ;
* tridivs = MEM_callocN ( sizeof ( int ) * numtris * 3 , " Smoke_Tridivs " ) ;
2012-04-28 21:46:43 +00:00
for ( i = 0 , facecounter = 0 ; i < numfaces ; i + + )
2009-07-30 15:00:26 +00:00
{
float p0 [ 3 ] , p1 [ 3 ] , p2 [ 3 ] ;
float side1 [ 3 ] ;
float side2 [ 3 ] ;
float side3 [ 3 ] ;
int divs1 = 0 , divs2 = 0 , divs3 = 0 ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p0 , verts [ faces [ i ] . v1 ] . co ) ;
2009-11-10 20:43:45 +00:00
mul_m4_v3 ( ob - > obmat , p0 ) ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p1 , verts [ faces [ i ] . v2 ] . co ) ;
2009-11-10 20:43:45 +00:00
mul_m4_v3 ( ob - > obmat , p1 ) ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p2 , verts [ faces [ i ] . v3 ] . co ) ;
2009-11-10 20:43:45 +00:00
mul_m4_v3 ( ob - > obmat , p2 ) ;
2009-07-30 15:00:26 +00:00
2011-11-06 15:39:20 +00:00
sub_v3_v3v3 ( side1 , p1 , p0 ) ;
sub_v3_v3v3 ( side2 , p2 , p0 ) ;
sub_v3_v3v3 ( side3 , p1 , p2 ) ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( dot_v3v3 ( side1 , side1 ) > fsTri * fsTri )
2009-07-30 15:00:26 +00:00
{
2009-11-10 20:43:45 +00:00
float tmp = normalize_v3 ( side1 ) ;
2009-08-06 16:50:02 +00:00
divs1 = ( int ) ceil ( tmp / fsTri ) ;
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
if ( dot_v3v3 ( side2 , side2 ) > fsTri * fsTri )
2009-07-30 15:00:26 +00:00
{
2009-11-10 20:43:45 +00:00
float tmp = normalize_v3 ( side2 ) ;
2009-08-06 16:50:02 +00:00
divs2 = ( int ) ceil ( tmp / fsTri ) ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
/*
2009-07-30 15:00:26 +00:00
// debug
2012-04-28 21:46:43 +00:00
if ( i = = 0 )
2009-07-30 15:00:26 +00:00
printf ( " b tmp: %f, fsTri: %f, divs2: %d \n " , tmp , fsTri , divs2 ) ;
*/
2012-04-28 21:46:43 +00:00
2009-07-30 15:00:26 +00:00
}
( * tridivs ) [ 3 * facecounter + 0 ] = divs1 ;
( * tridivs ) [ 3 * facecounter + 1 ] = divs2 ;
( * tridivs ) [ 3 * facecounter + 2 ] = divs3 ;
// TODO quad case
2012-04-28 21:46:43 +00:00
if ( faces [ i ] . v4 )
2009-07-30 15:00:26 +00:00
{
divs1 = 0 , divs2 = 0 , divs3 = 0 ;
facecounter + + ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p0 , verts [ faces [ i ] . v3 ] . co ) ;
2009-11-10 20:43:45 +00:00
mul_m4_v3 ( ob - > obmat , p0 ) ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p1 , verts [ faces [ i ] . v4 ] . co ) ;
2009-11-10 20:43:45 +00:00
mul_m4_v3 ( ob - > obmat , p1 ) ;
2011-11-06 15:39:20 +00:00
copy_v3_v3 ( p2 , verts [ faces [ i ] . v1 ] . co ) ;
2009-11-10 20:43:45 +00:00
mul_m4_v3 ( ob - > obmat , p2 ) ;
2009-07-30 15:00:26 +00:00
2011-11-06 15:39:20 +00:00
sub_v3_v3v3 ( side1 , p1 , p0 ) ;
sub_v3_v3v3 ( side2 , p2 , p0 ) ;
sub_v3_v3v3 ( side3 , p1 , p2 ) ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( dot_v3v3 ( side1 , side1 ) > fsTri * fsTri )
2009-07-30 15:00:26 +00:00
{
2009-11-10 20:43:45 +00:00
float tmp = normalize_v3 ( side1 ) ;
2009-08-06 16:50:02 +00:00
divs1 = ( int ) ceil ( tmp / fsTri ) ;
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
if ( dot_v3v3 ( side2 , side2 ) > fsTri * fsTri )
2009-07-30 15:00:26 +00:00
{
2009-11-10 20:43:45 +00:00
float tmp = normalize_v3 ( side2 ) ;
2009-08-06 16:50:02 +00:00
divs2 = ( int ) ceil ( tmp / fsTri ) ;
2009-07-30 15:00:26 +00:00
}
( * tridivs ) [ 3 * facecounter + 0 ] = divs1 ;
( * tridivs ) [ 3 * facecounter + 1 ] = divs2 ;
( * tridivs ) [ 3 * facecounter + 2 ] = divs3 ;
}
facecounter + + ;
}
}
2011-10-21 00:48:02 +00:00
# endif /* WITH_SMOKE */
2009-09-16 17:43:09 +00:00
static void smokeModifier_freeDomain ( SmokeModifierData * smd )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > domain )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > domain - > shadow )
2009-09-16 17:43:09 +00:00
MEM_freeN ( smd - > domain - > shadow ) ;
smd - > domain - > shadow = NULL ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( smd - > domain - > fluid )
2009-07-30 15:00:26 +00:00
smoke_free ( smd - > domain - > fluid ) ;
2009-08-09 01:30:32 +00:00
2012-04-28 21:46:43 +00:00
if ( smd - > domain - > wt )
2009-08-25 21:53:52 +00:00
smoke_turbulence_free ( smd - > domain - > wt ) ;
2012-04-28 21:46:43 +00:00
if ( smd - > domain - > effector_weights )
2009-10-22 23:22:05 +00:00
MEM_freeN ( smd - > domain - > effector_weights ) ;
smd - > domain - > effector_weights = NULL ;
2009-08-25 23:39:49 +00:00
BKE_ptcache_free_list ( & ( smd - > domain - > ptcaches [ 0 ] ) ) ;
smd - > domain - > point_cache [ 0 ] = NULL ;
2009-08-09 01:30:32 +00:00
2009-07-30 15:00:26 +00:00
MEM_freeN ( smd - > domain ) ;
smd - > domain = NULL ;
}
}
2009-09-16 17:43:09 +00:00
static void smokeModifier_freeFlow ( SmokeModifierData * smd )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > flow )
2009-07-30 15:00:26 +00:00
{
2009-08-12 17:32:02 +00:00
/*
2012-04-28 21:46:43 +00:00
if ( smd - > flow - > bvh )
2009-08-12 17:32:02 +00:00
{
free_bvhtree_from_mesh ( smd - > flow - > bvh ) ;
MEM_freeN ( smd - > flow - > bvh ) ;
}
smd - > flow - > bvh = NULL ;
*/
2009-07-30 15:00:26 +00:00
MEM_freeN ( smd - > flow ) ;
smd - > flow = NULL ;
}
}
2009-09-16 17:43:09 +00:00
static void smokeModifier_freeCollision ( SmokeModifierData * smd )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > coll )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
SmokeCollSettings * scs = smd - > coll ;
if ( scs - > numpoints )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( scs - > points )
{
MEM_freeN ( scs - > points ) ;
scs - > points = NULL ;
}
if ( scs - > points_old )
{
MEM_freeN ( scs - > points_old ) ;
scs - > points_old = NULL ;
}
if ( scs - > tridivs )
{
MEM_freeN ( scs - > tridivs ) ;
scs - > tridivs = NULL ;
}
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
if ( scs - > bvhtree )
2009-08-03 16:39:12 +00:00
{
2012-04-28 21:46:43 +00:00
BLI_bvhtree_free ( scs - > bvhtree ) ;
scs - > bvhtree = NULL ;
2009-08-03 16:39:12 +00:00
}
2012-01-24 01:21:43 +00:00
# ifdef USE_SMOKE_COLLISION_DM
2012-04-28 21:46:43 +00:00
if ( smd - > coll - > dm )
2009-08-06 16:50:02 +00:00
smd - > coll - > dm - > release ( smd - > coll - > dm ) ;
smd - > coll - > dm = NULL ;
2012-01-24 01:21:43 +00:00
# endif
2009-08-06 16:50:02 +00:00
2009-07-30 15:00:26 +00:00
MEM_freeN ( smd - > coll ) ;
smd - > coll = NULL ;
}
}
2009-09-16 17:43:09 +00:00
void smokeModifier_reset_turbulence ( struct SmokeModifierData * smd )
{
2012-04-28 21:46:43 +00:00
if ( smd & & smd - > domain & & smd - > domain - > wt )
2009-09-16 17:43:09 +00:00
{
smoke_turbulence_free ( smd - > domain - > wt ) ;
smd - > domain - > wt = NULL ;
}
}
2009-07-30 15:00:26 +00:00
void smokeModifier_reset ( struct SmokeModifierData * smd )
{
2012-04-28 21:46:43 +00:00
if ( smd )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > domain )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > domain - > shadow )
2009-09-16 17:43:09 +00:00
MEM_freeN ( smd - > domain - > shadow ) ;
smd - > domain - > shadow = NULL ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( smd - > domain - > fluid )
2009-07-30 15:00:26 +00:00
{
smoke_free ( smd - > domain - > fluid ) ;
smd - > domain - > fluid = NULL ;
}
2009-08-25 21:53:52 +00:00
2009-09-16 17:43:09 +00:00
smokeModifier_reset_turbulence ( smd ) ;
smd - > time = - 1 ;
// printf("reset domain end\n");
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
else if ( smd - > flow )
2009-07-30 15:00:26 +00:00
{
2009-08-12 17:32:02 +00:00
/*
2012-04-28 21:46:43 +00:00
if ( smd - > flow - > bvh )
2009-08-12 17:32:02 +00:00
{
free_bvhtree_from_mesh ( smd - > flow - > bvh ) ;
MEM_freeN ( smd - > flow - > bvh ) ;
2009-09-16 17:43:09 +00:00
}
2009-08-12 17:32:02 +00:00
smd - > flow - > bvh = NULL ;
*/
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
else if ( smd - > coll )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
SmokeCollSettings * scs = smd - > coll ;
2009-08-03 16:39:12 +00:00
2012-04-28 21:46:43 +00:00
if ( scs - > numpoints & & scs - > points )
2009-08-03 16:39:12 +00:00
{
2012-04-28 21:46:43 +00:00
MEM_freeN ( scs - > points ) ;
scs - > points = NULL ;
if ( scs - > points_old )
{
MEM_freeN ( scs - > points_old ) ;
scs - > points_old = NULL ;
}
if ( scs - > tridivs )
{
MEM_freeN ( scs - > tridivs ) ;
scs - > tridivs = NULL ;
}
2009-08-03 16:39:12 +00:00
}
2009-07-30 15:00:26 +00:00
}
}
}
2012-04-29 17:11:40 +00:00
void smokeModifier_free ( SmokeModifierData * smd )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd )
2009-07-30 15:00:26 +00:00
{
smokeModifier_freeDomain ( smd ) ;
smokeModifier_freeFlow ( smd ) ;
smokeModifier_freeCollision ( smd ) ;
}
}
void smokeModifier_createType ( struct SmokeModifierData * smd )
{
2012-04-28 21:46:43 +00:00
if ( smd )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > type & MOD_SMOKE_TYPE_DOMAIN )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > domain )
2009-07-30 15:00:26 +00:00
smokeModifier_freeDomain ( smd ) ;
smd - > domain = MEM_callocN ( sizeof ( SmokeDomainSettings ) , " SmokeDomain " ) ;
smd - > domain - > smd = smd ;
2009-08-25 23:39:49 +00:00
smd - > domain - > point_cache [ 0 ] = BKE_ptcache_add ( & ( smd - > domain - > ptcaches [ 0 ] ) ) ;
smd - > domain - > point_cache [ 0 ] - > flag | = PTCACHE_DISK_CACHE ;
smd - > domain - > point_cache [ 0 ] - > step = 1 ;
2010-11-30 21:31:18 +00:00
/* Deprecated */
smd - > domain - > point_cache [ 1 ] = NULL ;
smd - > domain - > ptcaches [ 1 ] . first = smd - > domain - > ptcaches [ 1 ] . last = NULL ;
2009-07-30 15:00:26 +00:00
/* set some standard values */
smd - > domain - > fluid = NULL ;
2009-09-16 17:43:09 +00:00
smd - > domain - > wt = NULL ;
2009-07-30 15:00:26 +00:00
smd - > domain - > eff_group = NULL ;
smd - > domain - > fluid_group = NULL ;
smd - > domain - > coll_group = NULL ;
2009-08-02 23:30:44 +00:00
smd - > domain - > maxres = 32 ;
2009-09-16 17:43:09 +00:00
smd - > domain - > amplify = 1 ;
smd - > domain - > omega = 1.0 ;
2009-07-30 15:00:26 +00:00
smd - > domain - > alpha = - 0.001 ;
smd - > domain - > beta = 0.1 ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
smd - > domain - > time_scale = 1.0 ;
smd - > domain - > vorticity = 2.0 ;
2012-04-28 21:46:43 +00:00
smd - > domain - > border_collisions = SM_BORDER_OPEN ; // open domain
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
smd - > domain - > flags = MOD_SMOKE_DISSOLVE_LOG | MOD_SMOKE_HIGH_SMOOTH ;
2009-09-16 17:43:09 +00:00
smd - > domain - > strength = 2.0 ;
2009-07-30 15:00:26 +00:00
smd - > domain - > noise = MOD_SMOKE_NOISEWAVE ;
2009-09-16 17:43:09 +00:00
smd - > domain - > diss_speed = 5 ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
// init 3dview buffer
smd - > domain - > viewsettings = MOD_SMOKE_VIEW_SHOWBIG ;
2009-10-22 23:22:05 +00:00
smd - > domain - > effector_weights = BKE_add_effector_weights ( NULL ) ;
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
else if ( smd - > type & MOD_SMOKE_TYPE_FLOW )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > flow )
2009-07-30 15:00:26 +00:00
smokeModifier_freeFlow ( smd ) ;
smd - > flow = MEM_callocN ( sizeof ( SmokeFlowSettings ) , " SmokeFlow " ) ;
smd - > flow - > smd = smd ;
/* set some standard values */
smd - > flow - > density = 1.0 ;
smd - > flow - > temp = 1.0 ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
smd - > flow - > flags = MOD_SMOKE_FLOW_ABSOLUTE ;
smd - > flow - > vel_multi = 1.0 ;
2009-07-30 15:00:26 +00:00
smd - > flow - > psys = NULL ;
}
2012-04-28 21:46:43 +00:00
else if ( smd - > type & MOD_SMOKE_TYPE_COLL )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( smd - > coll )
2009-07-30 15:00:26 +00:00
smokeModifier_freeCollision ( smd ) ;
smd - > coll = MEM_callocN ( sizeof ( SmokeCollSettings ) , " SmokeColl " ) ;
smd - > coll - > smd = smd ;
smd - > coll - > points = NULL ;
2012-04-28 21:46:43 +00:00
smd - > coll - > points_old = NULL ;
smd - > coll - > tridivs = NULL ;
smd - > coll - > vel = NULL ;
2009-07-30 15:00:26 +00:00
smd - > coll - > numpoints = 0 ;
2012-04-28 21:46:43 +00:00
smd - > coll - > numtris = 0 ;
2009-08-03 16:39:12 +00:00
smd - > coll - > bvhtree = NULL ;
2012-04-28 21:46:43 +00:00
smd - > coll - > type = 0 ; // static obstacle
smd - > coll - > dx = 1.0f / 50.0f ;
2012-01-24 01:21:43 +00:00
# ifdef USE_SMOKE_COLLISION_DM
2009-08-06 16:50:02 +00:00
smd - > coll - > dm = NULL ;
2012-01-24 01:21:43 +00:00
# endif
2009-07-30 15:00:26 +00:00
}
}
}
2010-05-14 07:09:15 +00:00
void smokeModifier_copy ( struct SmokeModifierData * smd , struct SmokeModifierData * tsmd )
{
tsmd - > type = smd - > type ;
tsmd - > time = smd - > time ;
smokeModifier_createType ( tsmd ) ;
if ( tsmd - > domain ) {
tsmd - > domain - > maxres = smd - > domain - > maxres ;
tsmd - > domain - > amplify = smd - > domain - > amplify ;
tsmd - > domain - > omega = smd - > domain - > omega ;
tsmd - > domain - > alpha = smd - > domain - > alpha ;
tsmd - > domain - > beta = smd - > domain - > beta ;
tsmd - > domain - > flags = smd - > domain - > flags ;
tsmd - > domain - > strength = smd - > domain - > strength ;
tsmd - > domain - > noise = smd - > domain - > noise ;
tsmd - > domain - > diss_speed = smd - > domain - > diss_speed ;
tsmd - > domain - > viewsettings = smd - > domain - > viewsettings ;
tsmd - > domain - > fluid_group = smd - > domain - > fluid_group ;
tsmd - > domain - > coll_group = smd - > domain - > coll_group ;
2010-12-01 02:28:08 +00:00
tsmd - > domain - > vorticity = smd - > domain - > vorticity ;
tsmd - > domain - > time_scale = smd - > domain - > time_scale ;
tsmd - > domain - > border_collisions = smd - > domain - > border_collisions ;
2010-05-14 07:09:15 +00:00
MEM_freeN ( tsmd - > domain - > effector_weights ) ;
tsmd - > domain - > effector_weights = MEM_dupallocN ( smd - > domain - > effector_weights ) ;
2012-04-28 21:46:43 +00:00
}
2012-03-24 06:18:31 +00:00
else if ( tsmd - > flow ) {
2010-05-14 07:09:15 +00:00
tsmd - > flow - > density = smd - > flow - > density ;
tsmd - > flow - > temp = smd - > flow - > temp ;
tsmd - > flow - > psys = smd - > flow - > psys ;
tsmd - > flow - > type = smd - > flow - > type ;
2010-12-01 02:28:08 +00:00
tsmd - > flow - > flags = smd - > flow - > flags ;
tsmd - > flow - > vel_multi = smd - > flow - > vel_multi ;
2012-03-24 06:18:31 +00:00
}
else if ( tsmd - > coll ) {
2010-05-14 07:09:15 +00:00
;
2012-03-18 07:38:51 +00:00
/* leave it as initialized, collision settings is mostly caches */
2010-05-14 07:09:15 +00:00
}
}
2011-10-20 09:47:05 +00:00
# ifdef WITH_SMOKE
2010-05-14 07:09:15 +00:00
2009-09-16 17:43:09 +00:00
// forward decleration
static void smoke_calc_transparency ( float * result , float * input , float * p0 , float * p1 , int res [ 3 ] , float dx , float * light , bresenham_callback cb , float correct ) ;
static float calc_voxel_transp ( float * result , float * input , int res [ 3 ] , int * pixel , float * tRay , float correct ) ;
2011-07-13 18:40:21 +00:00
2009-09-16 17:43:09 +00:00
static int get_lamp ( Scene * scene , float * light )
{
Base * base_tmp = NULL ;
2010-09-30 20:19:54 +00:00
int found_lamp = 0 ;
// try to find a lamp, preferably local
2012-04-28 21:46:43 +00:00
for ( base_tmp = scene - > base . first ; base_tmp ; base_tmp = base_tmp - > next ) {
if ( base_tmp - > object - > type = = OB_LAMP ) {
2010-09-30 20:19:54 +00:00
Lamp * la = base_tmp - > object - > data ;
2012-04-28 21:46:43 +00:00
if ( la - > type = = LA_LOCAL ) {
2010-09-30 20:19:54 +00:00
copy_v3_v3 ( light , base_tmp - > object - > obmat [ 3 ] ) ;
return 1 ;
}
2012-04-28 21:46:43 +00:00
else if ( ! found_lamp ) {
2010-09-30 20:19:54 +00:00
copy_v3_v3 ( light , base_tmp - > object - > obmat [ 3 ] ) ;
found_lamp = 1 ;
}
}
}
return found_lamp ;
2009-09-16 17:43:09 +00:00
}
2009-07-30 15:00:26 +00:00
2012-04-29 09:34:51 +00:00
static void smoke_calc_domain ( Scene * UNUSED ( scene ) , Object * UNUSED ( ob ) , SmokeModifierData * UNUSED ( smd ) )
2009-09-16 17:43:09 +00:00
{
2012-04-28 21:46:43 +00:00
#if 0
2009-09-16 17:43:09 +00:00
SmokeDomainSettings * sds = smd - > domain ;
GroupObject * go = NULL ;
2012-04-28 21:46:43 +00:00
Base * base = NULL ;
2009-09-16 17:43:09 +00:00
2012-04-28 21:46:43 +00:00
/* do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells */
if ( 1 )
2010-11-23 14:40:27 +00:00
{
2012-04-28 21:46:43 +00:00
unsigned int i ;
Object * * collobjs = NULL ;
unsigned int numcollobj = 0 ;
collobjs = get_collisionobjects ( scene , ob , sds - > coll_group , & numcollobj ) ;
2010-11-23 14:40:27 +00:00
2012-04-28 21:46:43 +00:00
for ( i = 0 ; i < numcollobj ; i + + )
2010-11-23 14:40:27 +00:00
{
2012-04-28 21:46:43 +00:00
Object * collob = collobjs [ i ] ;
SmokeModifierData * smd2 = ( SmokeModifierData * ) modifiers_findByType ( collob , eModifierType_Smoke ) ;
2010-11-23 14:40:27 +00:00
// check for active smoke modifier
2012-04-28 21:46:43 +00:00
// if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
// SmokeModifierData *smd2 = (SmokeModifierData *)md;
if ( ( smd2 - > type & MOD_SMOKE_TYPE_COLL ) & & smd2 - > coll & & smd2 - > coll - > points & & smd2 - > coll - > points_old )
2010-11-23 14:40:27 +00:00
{
2012-04-28 21:46:43 +00:00
// ??? anything to do here?
// TODO: only something to do for ANIMATED obstacles: need to update positions
}
}
if ( collobjs )
MEM_freeN ( collobjs ) ;
}
# endif
}
2010-11-23 14:40:27 +00:00
2012-04-28 21:46:43 +00:00
/* Animated obstacles: dx_step = ((x_new - x_old) / totalsteps) * substep */
static void update_obstacles ( Scene * scene , Object * ob , SmokeDomainSettings * sds , float dt , int substep , int totalsteps )
{
Object * * collobjs = NULL ;
unsigned int numcollobj = 0 ;
unsigned int collIndex ;
unsigned char * obstacles = smoke_get_obstacle ( sds - > fluid ) ;
float * velx = NULL ;
float * vely = NULL ;
float * velz = NULL ;
float * velxOrig = smoke_get_velocity_x ( sds - > fluid ) ;
float * velyOrig = smoke_get_velocity_y ( sds - > fluid ) ;
float * velzOrig = smoke_get_velocity_z ( sds - > fluid ) ;
// float *density = smoke_get_density(sds->fluid);
unsigned int z ;
smoke_get_ob_velocity ( sds - > fluid , & velx , & vely , & velz ) ;
// TODO: delete old obstacle flags
for ( z = 0 ; z < sds - > res [ 0 ] * sds - > res [ 1 ] * sds - > res [ 2 ] ; z + + )
{
if ( obstacles [ z ] )
{
// density[z] = 0;
velxOrig [ z ] = 0 ;
velyOrig [ z ] = 0 ;
velzOrig [ z ] = 0 ;
}
if ( obstacles [ z ] & 8 ) // Do not delete static obstacles
{
obstacles [ z ] = 0 ;
}
velx [ z ] = 0 ;
vely [ z ] = 0 ;
velz [ z ] = 0 ;
}
collobjs = get_collisionobjects ( scene , ob , sds - > coll_group , & numcollobj , eModifierType_Smoke ) ;
// update obstacle tags in cells
for ( collIndex = 0 ; collIndex < numcollobj ; collIndex + + )
{
Object * collob = collobjs [ collIndex ] ;
SmokeModifierData * smd2 = ( SmokeModifierData * ) modifiers_findByType ( collob , eModifierType_Smoke ) ;
// DG TODO: check if modifier is active?
if ( ( smd2 - > type & MOD_SMOKE_TYPE_COLL ) & & smd2 - > coll & & smd2 - > coll - > points & & smd2 - > coll - > points_old )
{
SmokeCollSettings * scs = smd2 - > coll ;
unsigned int i ;
/*
// DG TODO: support static cobstacles, but basicly we could even support static + rigid with one set of code
if ( scs - > type > SM_COLL_STATIC )
*/
/* Handle collisions */
for ( i = 0 ; i < scs - > numpoints ; i + + )
{
// 1. get corresponding cell
int cell [ 3 ] ;
float pos [ 3 ] , oldpos [ 3 ] , vel [ 3 ] ;
float cPos [ 3 ] , cOldpos [ 3 ] ; /* current position in substeps */
int badcell = 0 ;
size_t index ;
int j ;
// translate local points into global positions
copy_v3_v3 ( cPos , & scs - > points [ 3 * i ] ) ;
mul_m4_v3 ( scs - > mat , cPos ) ;
copy_v3_v3 ( pos , cPos ) ;
copy_v3_v3 ( cOldpos , & scs - > points_old [ 3 * i ] ) ;
mul_m4_v3 ( scs - > mat_old , cOldpos ) ;
copy_v3_v3 ( oldpos , cOldpos ) ;
/* support for rigid bodies, armatures etc */
2010-11-23 14:40:27 +00:00
{
2012-04-28 21:46:43 +00:00
float tmp [ 3 ] ;
2010-11-23 14:40:27 +00:00
2012-04-28 21:46:43 +00:00
/* x_current = x_old + (x_new - x_old) * step_current / steps_total */
float mulStep = ( float ) ( ( ( float ) substep ) / ( ( float ) totalsteps ) ) ;
2010-11-23 14:40:27 +00:00
2012-04-28 21:46:43 +00:00
sub_v3_v3v3 ( tmp , cPos , cOldpos ) ;
mul_v3_fl ( tmp , mulStep ) ;
add_v3_v3 ( cOldpos , tmp ) ;
}
sub_v3_v3v3 ( vel , pos , oldpos ) ;
/* Scale velocity to incorperate the object movement during this step */
mul_v3_fl ( vel , 1.0 / ( totalsteps * dt ) ) ;
// mul_v3_fl(vel, 1.0 / dt);
// DG TODO: cap velocity to maxVelMag (or maxvel)
// oldpos + velocity * dt = newpos
2012-05-24 23:50:20 +00:00
get_cell ( sds - > p0 , sds - > res , sds - > dx * sds - > scale , cOldpos /* use current position here instead of "pos" */ , cell , 0 ) ;
2012-04-28 21:46:43 +00:00
// 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 ;
2010-11-23 14:40:27 +00:00
}
2012-04-28 21:46:43 +00:00
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 ] ) ;
// Don't overwrite existing obstacles
if ( obstacles [ index ] )
continue ;
// 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 | 8 /* ANIMATED */ ;
if ( len_v3 ( vel ) > FLT_EPSILON )
{
// Collision object is moving
velx [ index ] = vel [ 0 ] ; // use "+="?
vely [ index ] = vel [ 1 ] ;
velz [ index ] = vel [ 2 ] ;
2010-11-23 14:40:27 +00:00
}
}
}
}
2012-04-28 21:46:43 +00:00
if ( collobjs )
MEM_freeN ( collobjs ) ;
}
static void update_flowsfluids ( Scene * scene , Object * ob , SmokeDomainSettings * sds , float time )
{
Object * * flowobjs = NULL ;
unsigned int numflowobj = 0 ;
unsigned int flowIndex ;
flowobjs = get_collisionobjects ( scene , ob , sds - > fluid_group , & numflowobj , eModifierType_Smoke ) ;
// update obstacle tags in cells
for ( flowIndex = 0 ; flowIndex < numflowobj ; flowIndex + + )
2010-11-23 14:40:27 +00:00
{
2012-04-28 21:46:43 +00:00
Object * collob = flowobjs [ flowIndex ] ;
SmokeModifierData * smd2 = ( SmokeModifierData * ) modifiers_findByType ( collob , eModifierType_Smoke ) ;
2009-09-16 17:43:09 +00:00
2012-04-28 21:46:43 +00:00
// check for initialized smoke object
if ( ( smd2 - > type & MOD_SMOKE_TYPE_FLOW ) & & smd2 - > flow )
{
// we got nice flow object
SmokeFlowSettings * sfs = smd2 - > flow ;
2009-09-16 17:43:09 +00:00
2012-04-28 21:46:43 +00:00
if ( sfs & & sfs - > psys & & sfs - > psys - > part & & sfs - > psys - > part - > type = = PART_EMITTER ) // is particle system selected
2009-09-16 17:43:09 +00:00
{
2012-04-28 21:46:43 +00:00
ParticleSimulationData sim ;
ParticleSystem * psys = sfs - > psys ;
int totpart = psys - > totpart , totchild ;
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 ) ;
// DG TODO UNUSED unsigned char *obstacleAnim = smoke_get_obstacle_anim(sds->fluid);
int bigres [ 3 ] ;
short absolute_flow = ( sfs - > flags & MOD_SMOKE_FLOW_ABSOLUTE ) ;
short high_emission_smoothing = bigdensity ? ( sds - > flags & MOD_SMOKE_HIGH_SMOOTH ) : 0 ;
/*
* A temporary volume map used to store whole emissive
* area to be added to smoke density and interpolated
* for high resolution smoke .
*/
float * temp_emission_map = NULL ;
sim . scene = scene ;
sim . ob = collob ;
sim . psys = psys ;
// initialize temp emission map
if ( ! ( sfs - > type & MOD_SMOKE_FLOW_TYPE_OUTFLOW ) )
2009-09-16 17:43:09 +00:00
{
2012-04-28 21:46:43 +00:00
int i ;
temp_emission_map = MEM_callocN ( sizeof ( float ) * sds - > res [ 0 ] * sds - > res [ 1 ] * sds - > res [ 2 ] , " SmokeTempEmission " ) ;
// set whole volume to 0.0f
for ( i = 0 ; i < sds - > res [ 0 ] * sds - > res [ 1 ] * sds - > res [ 2 ] ; i + + ) {
temp_emission_map [ i ] = 0.0f ;
}
}
// mostly copied from particle code
if ( psys - > part - > type = = PART_HAIR )
{
/*
if ( psys - > childcache )
2009-09-16 17:43:09 +00:00
{
2012-04-28 21:46:43 +00:00
totchild = psys - > totchildcache ;
}
else
*/
// TODO: PART_HAIR not supported whatsoever
totchild = 0 ;
}
else
totchild = psys - > totchild * psys - > part - > disp / 100 ;
for ( p = 0 ; p < totpart + totchild ; p + + )
{
int cell [ 3 ] ;
size_t i = 0 ;
size_t index = 0 ;
int badcell = 0 ;
ParticleKey state ;
if ( p < totpart )
{
if ( psys - > particles [ p ] . flag & ( PARS_NO_DISP | PARS_UNEXIST ) )
continue ;
}
else {
/* handle child particle */
ChildParticle * cpa = & psys - > child [ p - totpart ] ;
if ( psys - > particles [ cpa - > parent ] . flag & ( PARS_NO_DISP | PARS_UNEXIST ) )
continue ;
}
state . time = time ;
if ( psys_get_particle_state ( & sim , p , & state , 0 ) = = 0 )
continue ;
// copy_v3_v3(pos, pa->state.co);
// mul_m4_v3(ob->imat, pos);
// 1. get corresponding cell
2012-05-24 23:50:20 +00:00
get_cell ( sds - > p0 , sds - > res , sds - > dx * sds - > scale , state . co , cell , 0 ) ;
2012-04-28 21:46:43 +00:00
// 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 ] ) ) // this is inflow
{
// heat[index] += sfs->temp * 0.1;
// density[index] += sfs->density * 0.1;
heat [ index ] = sfs - > temp ;
// Add emitter density to temp emission map
temp_emission_map [ index ] = sfs - > density ;
// Uses particle velocity as initial velocity for smoke
if ( sfs - > flags & MOD_SMOKE_FLOW_INITVELOCITY & & ( psys - > part - > phystype ! = PART_PHYS_NO ) )
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
{
2012-04-28 21:46:43 +00:00
velocity_x [ index ] = state . vel [ 0 ] * sfs - > vel_multi ;
velocity_y [ index ] = state . vel [ 1 ] * sfs - > vel_multi ;
velocity_z [ index ] = state . vel [ 2 ] * sfs - > vel_multi ;
}
}
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 )
2012-02-19 20:05:01 +00:00
{
2012-04-28 21:46:43 +00:00
// init all surrounding cells according to amplification, too
int i , j , k ;
smoke_turbulence_get_res ( sds - > wt , bigres ) ;
for ( i = 0 ; i < sds - > amplify + 1 ; i + + )
for ( j = 0 ; j < sds - > amplify + 1 ; j + + )
for ( k = 0 ; k < sds - > amplify + 1 ; k + + )
{
index = smoke_get_index ( ( sds - > amplify + 1 ) * cell [ 0 ] + i , bigres [ 0 ] , ( sds - > amplify + 1 ) * cell [ 1 ] + j , bigres [ 1 ] , ( sds - > amplify + 1 ) * cell [ 2 ] + k ) ;
bigdensity [ index ] = 0.f ;
}
2012-02-19 20:05:01 +00:00
}
2012-04-28 21:46:43 +00:00
}
} // particles loop
// apply emission values
if ( ! ( sfs - > type & MOD_SMOKE_FLOW_TYPE_OUTFLOW ) )
{
// initialize variables
int ii , jj , kk , x , y , z , block_size ;
size_t index , index_big ;
smoke_turbulence_get_res ( sds - > wt , bigres ) ;
block_size = sds - > amplify + 1 ; // high res block size
2010-12-15 17:05:34 +00:00
2012-04-28 21:46:43 +00:00
// loop through every low res cell
for ( x = 0 ; x < sds - > res [ 0 ] ; x + + )
for ( y = 0 ; y < sds - > res [ 1 ] ; y + + )
for ( z = 0 ; z < sds - > res [ 2 ] ; z + + )
2012-02-19 20:05:01 +00:00
{
2012-04-28 21:46:43 +00:00
// neighbor cell emission densities (for high resolution smoke smooth interpolation)
float c000 , c001 , c010 , c011 , c100 , c101 , c110 , c111 ;
2010-12-15 17:05:34 +00:00
2012-04-28 21:46:43 +00:00
c000 = ( x > 0 & & y > 0 & & z > 0 ) ? temp_emission_map [ smoke_get_index ( x - 1 , sds - > res [ 0 ] , y - 1 , sds - > res [ 1 ] , z - 1 ) ] : 0 ;
c001 = ( x > 0 & & y > 0 ) ? temp_emission_map [ smoke_get_index ( x - 1 , sds - > res [ 0 ] , y - 1 , sds - > res [ 1 ] , z ) ] : 0 ;
c010 = ( x > 0 & & z > 0 ) ? temp_emission_map [ smoke_get_index ( x - 1 , sds - > res [ 0 ] , y , sds - > res [ 1 ] , z - 1 ) ] : 0 ;
c011 = ( x > 0 ) ? temp_emission_map [ smoke_get_index ( x - 1 , sds - > res [ 0 ] , y , sds - > res [ 1 ] , z ) ] : 0 ;
c100 = ( y > 0 & & z > 0 ) ? temp_emission_map [ smoke_get_index ( x , sds - > res [ 0 ] , y - 1 , sds - > res [ 1 ] , z - 1 ) ] : 0 ;
c101 = ( y > 0 ) ? temp_emission_map [ smoke_get_index ( x , sds - > res [ 0 ] , y - 1 , sds - > res [ 1 ] , z ) ] : 0 ;
c110 = ( z > 0 ) ? temp_emission_map [ smoke_get_index ( x , sds - > res [ 0 ] , y , sds - > res [ 1 ] , z - 1 ) ] : 0 ;
c111 = temp_emission_map [ smoke_get_index ( x , sds - > res [ 0 ] , y , sds - > res [ 1 ] , z ) ] ; // this cell
// get cell index
index = smoke_get_index ( x , sds - > res [ 0 ] , y , sds - > res [ 1 ] , z ) ;
// add emission to low resolution density
if ( absolute_flow )
2009-09-16 17:43:09 +00:00
{
2012-04-28 21:46:43 +00:00
if ( temp_emission_map [ index ] > 0 )
density [ index ] = temp_emission_map [ index ] ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
}
2012-04-28 21:46:43 +00:00
else
{
density [ index ] + = temp_emission_map [ index ] ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
if ( density [ index ] > 1 )
density [ index ] = 1.0f ;
}
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
smoke_turbulence_get_res ( sds - > wt , bigres ) ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
/* loop through high res blocks if high res enabled */
if ( bigdensity )
for ( ii = 0 ; ii < block_size ; ii + + )
for ( jj = 0 ; jj < block_size ; jj + + )
for ( kk = 0 ; kk < block_size ; kk + + )
{
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
float fx , fy , fz , interpolated_value ;
int shift_x , shift_y , shift_z ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
/*
* Do volume interpolation if emitter smoothing
* is enabled
*/
if ( high_emission_smoothing )
{
// convert block position to relative
// for interpolation smoothing
fx = ( float ) ii / block_size + 0.5f / block_size ;
fy = ( float ) jj / block_size + 0.5f / block_size ;
fz = ( float ) kk / block_size + 0.5f / block_size ;
// calculate trilinear interpolation
interpolated_value = c000 * ( 1 - fx ) * ( 1 - fy ) * ( 1 - fz ) +
c100 * fx * ( 1 - fy ) * ( 1 - fz ) +
c010 * ( 1 - fx ) * fy * ( 1 - fz ) +
c001 * ( 1 - fx ) * ( 1 - fy ) * fz +
c101 * fx * ( 1 - fy ) * fz +
c011 * ( 1 - fx ) * fy * fz +
c110 * fx * fy * ( 1 - fz ) +
c111 * fx * fy * fz ;
// add some contrast / sharpness
// depending on hi-res block size
interpolated_value = ( interpolated_value - 0.4f * sfs - > density ) * ( block_size / 2 ) + 0.4f * sfs - > density ;
if ( interpolated_value < 0.0f ) interpolated_value = 0.0f ;
if ( interpolated_value > 1.0f ) interpolated_value = 1.0f ;
// shift smoke block index
// (because pixel center is actually
// in halfway of the low res block)
shift_x = ( x < 1 ) ? 0 : block_size / 2 ;
shift_y = ( y < 1 ) ? 0 : block_size / 2 ;
shift_z = ( z < 1 ) ? 0 : block_size / 2 ;
}
else
{
// without interpolation use same low resolution
// block value for all hi-res blocks
interpolated_value = c111 ;
shift_x = 0 ;
shift_y = 0 ;
shift_z = 0 ;
}
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
// get shifted index for current high resolution block
index_big = smoke_get_index ( block_size * x + ii - shift_x , bigres [ 0 ] , block_size * y + jj - shift_y , bigres [ 1 ] , block_size * z + kk - shift_z ) ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
// add emission data to high resolution density
if ( absolute_flow )
{
if ( interpolated_value > 0 )
bigdensity [ index_big ] = interpolated_value ;
}
else
{
bigdensity [ index_big ] + = interpolated_value ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
if ( bigdensity [ index_big ] > 1 )
bigdensity [ index_big ] = 1.0f ;
}
} // end of hires loop
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
} // end of low res loop
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
// free temporary emission map
if ( temp_emission_map )
MEM_freeN ( temp_emission_map ) ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
} // end emission
}
}
}
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
if ( flowobjs )
MEM_freeN ( flowobjs ) ;
}
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-29 09:34:51 +00:00
static void update_effectors ( Scene * scene , Object * ob , SmokeDomainSettings * sds , float UNUSED ( dt ) )
2012-04-28 21:46:43 +00:00
{
ListBase * effectors = pdInitEffectors ( scene , ob , NULL , sds - > effector_weights ) ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
if ( effectors )
{
float * density = smoke_get_density ( sds - > fluid ) ;
float * force_x = smoke_get_force_x ( sds - > fluid ) ;
float * force_y = smoke_get_force_y ( sds - > fluid ) ;
float * force_z = smoke_get_force_z ( 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 x , y , z ;
// precalculate wind forces
for ( x = 0 ; x < sds - > res [ 0 ] ; x + + )
for ( y = 0 ; y < sds - > res [ 1 ] ; y + + )
for ( z = 0 ; z < sds - > res [ 2 ] ; z + + )
{
EffectedPoint epoint ;
2012-04-29 15:47:02 +00:00
float voxelCenter [ 3 ] = { 0 , 0 , 0 } , vel [ 3 ] = { 0 , 0 , 0 } , retvel [ 3 ] = { 0 , 0 , 0 } ;
2012-04-28 21:46:43 +00:00
unsigned int index = smoke_get_index ( x , sds - > res [ 0 ] , y , sds - > res [ 1 ] , z ) ;
if ( ( density [ index ] < FLT_EPSILON ) | | obstacle [ index ] )
continue ;
vel [ 0 ] = velocity_x [ index ] ;
vel [ 1 ] = velocity_y [ index ] ;
vel [ 2 ] = velocity_z [ index ] ;
2012-05-24 23:50:20 +00:00
voxelCenter [ 0 ] = sds - > p0 [ 0 ] + sds - > dx * sds - > scale * x + sds - > dx * sds - > scale * 0.5 ;
voxelCenter [ 1 ] = sds - > p0 [ 1 ] + sds - > dx * sds - > scale * y + sds - > dx * sds - > scale * 0.5 ;
voxelCenter [ 2 ] = sds - > p0 [ 2 ] + sds - > dx * sds - > scale * z + sds - > dx * sds - > scale * 0.5 ;
2012-04-28 21:46:43 +00:00
pd_point_from_loc ( scene , voxelCenter , vel , index , & epoint ) ;
pdDoEffectors ( effectors , NULL , sds - > effector_weights , & epoint , retvel , NULL ) ;
// TODO dg - do in force!
force_x [ index ] = MIN2 ( MAX2 ( - 1.0 , retvel [ 0 ] * 0.2 ) , 1.0 ) ;
force_y [ index ] = MIN2 ( MAX2 ( - 1.0 , retvel [ 1 ] * 0.2 ) , 1.0 ) ;
force_z [ index ] = MIN2 ( MAX2 ( - 1.0 , retvel [ 2 ] * 0.2 ) , 1.0 ) ;
}
}
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
pdEndEffectors ( & effectors ) ;
}
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
static void step ( Scene * scene , Object * ob , SmokeModifierData * smd , float fps )
{
/* stability values copied from wturbulence.cpp */
const int maxSubSteps = 25 ;
float maxVel ;
// maxVel should be 1.5 (1.5 cell max movement) * dx (cell size)
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
float dt = DT_DEFAULT ;
float maxVelMag = 0.0f ;
int totalSubsteps ;
int substep = 0 ;
float dtSubdiv ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
SmokeDomainSettings * sds = smd - > domain ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
/* get max velocity and lower the dt value if it is too high */
size_t size = sds - > res [ 0 ] * sds - > res [ 1 ] * sds - > res [ 2 ] ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
float * velX = smoke_get_velocity_x ( sds - > fluid ) ;
float * velY = smoke_get_velocity_y ( sds - > fluid ) ;
float * velZ = smoke_get_velocity_z ( sds - > fluid ) ;
size_t i ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-04-28 21:46:43 +00:00
/* adapt timestep for different framerates, dt = 0.1 is at 25fps */
dt * = ( 25.0f / fps ) ;
Smoke Patch + additions: a) Applying patch #22765 by Miika Hämäläinen (domain border collision settings, vorticity settings, time scale, non absolute density, smooth high res emitter, initial velocity multiplier, high res strength available to be set to 0), b) Additions by me: --Initial velocity is now per flow object, not per domain; --Using boundingbox as standard display mode for domains (was wire before); --When adding a flow object, an initial nice SmokeParticle system is added too with nice initial settings (life=1, no_render, unborn, etc) fitting smoke simulation; --Adaptive timesteps introduced to the smoke sim (depending on the magnitude of the velocity) because it was quite unstable when used for fire simulations, still needs to be tested and will also slow down some simulations.
2010-07-27 14:53:20 +00:00
2012-05-27 18:45:16 +00:00
// maximum timestep/"CFL" constraint: dt < 5.0 *dx / maxVel
maxVel = ( sds - > dx * 5.0 ) ;
2009-09-16 17:43:09 +00:00
2012-04-28 21:46:43 +00:00
for ( i = 0 ; i < size ; i + + )
{
float vtemp = ( velX [ i ] * velX [ i ] + velY [ i ] * velY [ i ] + velZ [ i ] * velZ [ i ] ) ;
if ( vtemp > maxVelMag )
maxVelMag = vtemp ;
2009-09-16 17:43:09 +00:00
}
2012-04-28 21:46:43 +00:00
maxVelMag = sqrt ( maxVelMag ) * dt * sds - > time_scale ;
totalSubsteps = ( int ) ( ( maxVelMag / maxVel ) + 1.0f ) ; /* always round up */
totalSubsteps = ( totalSubsteps < 1 ) ? 1 : totalSubsteps ;
totalSubsteps = ( totalSubsteps > maxSubSteps ) ? maxSubSteps : totalSubsteps ;
2012-05-27 18:45:16 +00:00
/* Disable substeps for now, since it results in numerical instability */
totalSubsteps = 1.0f ;
2012-04-28 21:46:43 +00:00
dtSubdiv = ( float ) dt / ( float ) totalSubsteps ;
// printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
for ( substep = 0 ; substep < totalSubsteps ; substep + + )
2009-09-16 17:43:09 +00:00
{
2012-04-28 21:46:43 +00:00
// calc animated obstacle velocities
update_obstacles ( scene , ob , sds , dtSubdiv , substep , totalSubsteps ) ;
update_flowsfluids ( scene , ob , sds , smd - > time ) ;
update_effectors ( scene , ob , sds , dtSubdiv ) ; // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt
2009-10-22 23:22:05 +00:00
2012-04-28 21:46:43 +00:00
smoke_step ( sds - > fluid , dtSubdiv ) ;
2009-10-22 23:22:05 +00:00
2012-04-28 21:46:43 +00:00
// move animated obstacle: Done in update_obstacles() */
2009-09-16 17:43:09 +00:00
2012-04-28 21:46:43 +00:00
// where to delete old obstacles from array? Done in update_obstacles() */
}
2009-09-16 17:43:09 +00:00
}
2012-04-28 21:46:43 +00:00
2010-10-21 01:10:22 +00:00
void smokeModifier_do ( SmokeModifierData * smd , Scene * scene , Object * ob , DerivedMesh * dm )
2009-08-02 23:30:44 +00:00
{
2012-04-28 21:46:43 +00:00
if ( ( smd - > type & MOD_SMOKE_TYPE_FLOW ) )
2009-07-30 15:00:26 +00:00
{
2012-04-28 21:46:43 +00:00
if ( scene - > r . cfra > = smd - > time )
2009-09-16 17:43:09 +00:00
smokeModifier_init ( smd , ob , scene , dm ) ;
2009-07-30 15:00:26 +00:00
2012-04-28 21:46:43 +00:00
if ( scene - > r . cfra > smd - > time )
2009-07-30 15:00:26 +00:00
{
// XXX TODO
2009-08-03 16:39:12 +00:00
smd - > time = scene - > r . cfra ;
2009-08-12 17:32:02 +00:00
// rigid movement support
/*
2009-11-10 20:43:45 +00:00
copy_m4_m4 ( smd - > flow - > mat_old , smd - > flow - > mat ) ;
copy_m4_m4 ( smd - > flow - > mat , ob - > obmat ) ;
2009-08-12 17:32:02 +00:00
*/
2009-08-03 16:39:12 +00:00
}
2012-04-28 21:46:43 +00:00
else if ( scene - > r . cfra < smd - > time )
2009-08-03 16:39:12 +00:00
{
smd - > time = scene - > r . cfra ;
smokeModifier_reset ( smd ) ;
}
}
2012-04-28 21:46:43 +00:00
else if ( smd - > type & MOD_SMOKE_TYPE_COLL )
2009-08-03 16:39:12 +00:00
{
2012-04-28 21:46:43 +00:00
/* Check if domain resolution changed */
/* DG TODO: can this be solved more elegant using dependancy graph? */
{
SmokeCollSettings * scs = smd - > coll ;
Base * base = scene - > base . first ;
int changed = 0 ;
float dx = FLT_MAX ;
2012-05-24 23:50:20 +00:00
float scale = 1.0f ;
2012-04-28 21:46:43 +00:00
int haveDomain = 0 ;
for ( ; base ; base = base - > next )
{
SmokeModifierData * smd2 = ( SmokeModifierData * ) modifiers_findByType ( base - > object , eModifierType_Smoke ) ;
if ( smd2 & & ( smd2 - > type & MOD_SMOKE_TYPE_DOMAIN ) & & smd2 - > domain )
{
SmokeDomainSettings * sds = smd2 - > domain ;
2012-05-24 23:50:20 +00:00
if ( sds - > dx * sds - > scale < dx )
2012-04-28 21:46:43 +00:00
{
dx = sds - > dx ;
2012-05-24 23:50:20 +00:00
scale = sds - > scale ;
2012-04-28 21:46:43 +00:00
changed = 1 ;
}
haveDomain = 1 ;
}
}
if ( ! haveDomain )
return ;
if ( changed )
{
2012-05-24 23:50:20 +00:00
if ( dx * scale ! = scs - > dx )
2012-04-28 21:46:43 +00:00
{
2012-05-24 23:50:20 +00:00
scs - > dx = dx * scale ;
2012-04-28 21:46:43 +00:00
smokeModifier_reset ( smd ) ;
}
}
}
if ( scene - > r . cfra > = smd - > time )
2009-08-20 00:33:59 +00:00
smokeModifier_init ( smd , ob , scene , dm ) ;
2012-04-28 21:46:43 +00:00
if ( scene - > r . cfra > smd - > time )
2009-08-03 16:39:12 +00:00
{
2012-04-28 21:46:43 +00:00
unsigned int i ;
SmokeCollSettings * scs = smd - > coll ;
float * points_old = scs - > points_old ;
float * points = scs - > points ;
unsigned int numpoints = scs - > numpoints ;
// XXX TODO <-- DG: what is TODO here?
2009-08-03 16:39:12 +00:00
smd - > time = scene - > r . cfra ;
2012-01-24 01:21:43 +00:00
2012-04-28 21:46:43 +00:00
// rigid movement support
copy_m4_m4 ( scs - > mat_old , scs - > mat ) ;
copy_m4_m4 ( scs - > mat , ob - > obmat ) ;
2009-08-06 16:50:02 +00:00
2012-04-28 21:46:43 +00:00
if ( scs - > type ! = SM_COLL_ANIMATED ) // if(not_animated)
{
// nothing to do, "mat" is already up to date
}
else
{
// XXX TODO: need to update positions + divs
2009-08-06 16:50:02 +00:00
2012-04-28 21:46:43 +00:00
if ( scs - > numverts ! = dm - > getNumVerts ( dm ) )
{
// DG TODO: reset modifier?
return ;
}
for ( i = 0 ; i < numpoints * 3 ; i + + )
{
points_old [ i ] = points [ i ] ;
}
DM_ensure_tessface ( dm ) ;
fill_scs_points_anim ( ob , dm , scs ) ;
}
2009-07-30 15:00:26 +00:00
}
2012-04-28 21:46:43 +00:00
else if ( scene - > r . cfra < smd - > time )
2009-07-30 15:00:26 +00:00
{
smd - > time = scene - > r . cfra ;
smokeModifier_reset ( smd ) ;
}
}
2012-04-28 21:46:43 +00:00
else if ( smd - > type & MOD_SMOKE_TYPE_DOMAIN )
2009-07-30 15:00:26 +00:00
{
2009-09-16 17:43:09 +00:00
SmokeDomainSettings * sds = smd - > domain ;
float light [ 3 ] ;
PointCache * cache = NULL ;
2009-08-20 00:33:59 +00:00
PTCacheID pid ;
int startframe , endframe , framenr ;
2009-09-16 17:43:09 +00:00
float timescale ;
2009-08-20 00:33:59 +00:00
framenr = scene - > r . cfra ;
2010-11-30 21:31:18 +00:00
//printf("time: %d\n", scene->r.cfra);
2009-09-16 17:43:09 +00:00
cache = sds - > point_cache [ 0 ] ;
2009-08-20 00:33:59 +00:00
BKE_ptcache_id_from_smoke ( & pid , ob , smd ) ;
BKE_ptcache_id_time ( & pid , scene , framenr , & startframe , & endframe , & timescale ) ;
2012-04-28 21:46:43 +00:00
if ( ! smd - > domain - > fluid | | framenr = = startframe )
2009-09-16 17:43:09 +00:00
{
BKE_ptcache_id_reset ( scene , & pid , PTCACHE_RESET_OUTDATED ) ;
2010-09-27 12:24:12 +00:00
BKE_ptcache_validate ( cache , framenr ) ;
cache - > flag & = ~ PTCACHE_REDO_NEEDED ;
2009-08-20 00:33:59 +00:00
}
2009-09-16 17:43:09 +00:00
2012-04-28 21:46:43 +00:00
if ( ! smd - > domain - > fluid & & ( framenr ! = startframe ) & & ( smd - > domain - > flags & MOD_SMOKE_FILE_LOAD ) = = 0 & & ( cache - > flag & PTCACHE_BAKED ) = = 0 )
2009-09-16 17:43:09 +00:00
return ;
2009-07-30 15:00:26 +00:00
2010-11-23 14:04:05 +00:00
smd - > domain - > flags & = ~ MOD_SMOKE_FILE_LOAD ;
2009-07-30 15:00:26 +00:00
2010-11-30 21:31:18 +00:00
CLAMP ( framenr , startframe , endframe ) ;
2009-07-30 15:00:26 +00:00
2010-11-11 17:59:52 +00:00
/* If already viewing a pre/after frame, no need to reload */
if ( ( smd - > time = = framenr ) & & ( framenr ! = scene - > r . cfra ) )
2009-08-20 00:33:59 +00:00
return ;
2009-07-30 15:00:26 +00:00
2009-09-16 17:43:09 +00:00
// printf("startframe: %d, framenr: %d\n", startframe, framenr);
2012-04-28 21:46:43 +00:00
if ( smokeModifier_init ( smd , ob , scene , dm ) = = 0 )
2009-09-16 17:43:09 +00:00
{
printf ( " bad smokeModifier_init \n " ) ;
2009-08-25 23:39:49 +00:00
return ;
2009-09-16 17:43:09 +00:00
}
2009-07-30 15:00:26 +00:00
2009-08-20 00:33:59 +00:00
/* try to read from cache */
2012-04-28 21:46:43 +00:00
if ( BKE_ptcache_read ( & pid , ( float ) framenr ) = = PTCACHE_READ_EXACT ) {
2010-03-21 20:36:06 +00:00
BKE_ptcache_validate ( cache , framenr ) ;
2010-09-27 12:24:12 +00:00
smd - > time = framenr ;
2010-11-30 21:31:18 +00:00
return ;
2009-08-20 00:33:59 +00:00
}
2010-11-30 21:31:18 +00:00
2010-09-27 12:24:12 +00:00
/* only calculate something when we advanced a single frame */
2012-04-28 21:46:43 +00:00
if ( framenr ! = ( int ) smd - > time + 1 )
2010-04-01 14:44:31 +00:00
return ;
2009-08-20 00:33:59 +00:00
2010-11-11 17:59:52 +00:00
/* don't simulate if viewing start frame, but scene frame is not real start frame */
if ( framenr ! = scene - > r . cfra )
2010-04-01 14:44:31 +00:00
return ;
2009-09-16 17:43:09 +00:00
tstart ( ) ;
smoke_calc_domain ( scene , ob , smd ) ;
2010-09-27 12:24:12 +00:00
/* if on second frame, write cache for first frame */
2012-04-28 21:46:43 +00:00
if ( ( int ) smd - > time = = startframe & & ( cache - > flag & PTCACHE_OUTDATED | | cache - > last_exact = = 0 ) ) {
2010-10-30 08:51:50 +00:00
// create shadows straight after domain initialization so we get nice shadows for startframe, too
2012-04-28 21:46:43 +00:00
if ( get_lamp ( scene , light ) )
2012-05-25 09:40:56 +00:00
smoke_calc_transparency ( sds - > shadow , smoke_get_density ( sds - > fluid ) , sds - > p0 , sds - > p1 , sds - > res , sds - > dx , light , calc_voxel_transp , - 7.0 * sds - > dx ) ;
2010-10-30 08:51:50 +00:00
2012-04-28 21:46:43 +00:00
if ( sds - > wt )
2010-11-30 21:31:18 +00:00
{
2012-04-28 21:46:43 +00:00
if ( sds - > flags & MOD_SMOKE_DISSOLVE )
2010-11-30 21:31:18 +00:00
smoke_dissolve_wavelet ( sds - > wt , sds - > diss_speed , sds - > flags & MOD_SMOKE_DISSOLVE_LOG ) ;
smoke_turbulence_step ( sds - > wt , sds - > fluid ) ;
}
2010-12-18 15:03:31 +00:00
BKE_ptcache_write ( & pid , startframe ) ;
2010-09-27 12:24:12 +00:00
}
2009-08-20 00:33:59 +00:00
2009-09-16 17:43:09 +00:00
// set new time
smd - > time = scene - > r . cfra ;
2009-08-20 00:33:59 +00:00
/* do simulation */
// low res
2009-09-16 17:43:09 +00:00
// simulate the actual smoke (c++ code in intern/smoke)
// DG: interesting commenting this line + deactivating loading of noise files
2012-04-28 21:46:43 +00:00
if ( framenr ! = startframe )
2009-10-22 23:22:05 +00:00
{
2012-04-28 21:46:43 +00:00
if ( sds - > flags & MOD_SMOKE_DISSOLVE )
2009-10-22 23:22:05 +00:00
smoke_dissolve ( sds - > fluid , sds - > diss_speed , sds - > flags & MOD_SMOKE_DISSOLVE_LOG ) ;
2012-04-28 21:46:43 +00:00
step ( scene , ob , smd , scene - > r . frs_sec / scene - > r . frs_sec_base ) ;
2009-10-02 11:09:05 +00:00
}
2009-08-20 00:33:59 +00:00
2010-10-30 08:51:50 +00:00
// create shadows before writing cache so they get stored
2012-04-28 21:46:43 +00:00
if ( get_lamp ( scene , light ) )
2012-05-25 09:40:56 +00:00
smoke_calc_transparency ( sds - > shadow , smoke_get_density ( sds - > fluid ) , sds - > p0 , sds - > p1 , sds - > res , sds - > dx , light , calc_voxel_transp , - 7.0 * sds - > dx ) ;
2009-08-25 23:39:49 +00:00
2012-04-28 21:46:43 +00:00
if ( sds - > wt )
2009-08-20 00:33:59 +00:00
{
2012-04-28 21:46:43 +00:00
if ( sds - > flags & MOD_SMOKE_DISSOLVE )
2010-11-30 21:31:18 +00:00
smoke_dissolve_wavelet ( sds - > wt , sds - > diss_speed , sds - > flags & MOD_SMOKE_DISSOLVE_LOG ) ;
smoke_turbulence_step ( sds - > wt , sds - > fluid ) ;
2009-08-20 00:33:59 +00:00
}
2010-11-30 21:31:18 +00:00
BKE_ptcache_validate ( cache , framenr ) ;
2012-04-28 21:46:43 +00:00
if ( framenr ! = startframe )
2010-12-18 15:03:31 +00:00
BKE_ptcache_write ( & pid , framenr ) ;
2009-07-30 15:00:26 +00:00
2009-08-20 00:33:59 +00:00
tend ( ) ;
2012-04-28 21:46:43 +00:00
// printf ( "Frame: %d, Time: %f\n\n", (int)smd->time, ( float ) tval() );
2009-08-20 00:33:59 +00:00
}
}
2009-09-16 17:43:09 +00:00
static float calc_voxel_transp ( float * result , float * input , int res [ 3 ] , int * pixel , float * tRay , float correct )
2009-08-20 00:33:59 +00:00
{
const size_t index = smoke_get_index ( pixel [ 0 ] , res [ 0 ] , pixel [ 1 ] , res [ 1 ] , pixel [ 2 ] ) ;
// T_ray *= T_vox
2009-09-16 17:43:09 +00:00
* tRay * = exp ( input [ index ] * correct ) ;
2012-04-28 21:46:43 +00:00
if ( result [ index ] < 0.0f )
2009-07-30 15:00:26 +00:00
{
2009-09-16 17:43:09 +00:00
# pragma omp critical
result [ index ] = * tRay ;
}
2009-07-30 15:00:26 +00:00
2009-09-16 17:43:09 +00:00
return * tRay ;
2009-07-30 15:00:26 +00:00
}
long long smoke_get_mem_req ( int xres , int yres , int zres , int amplify )
{
2011-04-21 15:53:30 +00:00
int totalCells = xres * yres * zres ;
int amplifiedCells = totalCells * amplify * amplify * amplify ;
2009-07-30 15:00:26 +00:00
2011-04-21 15:53:30 +00:00
// print out memory requirements
long long int coarseSize = sizeof ( float ) * totalCells * 22 +
sizeof ( unsigned char ) * totalCells ;
2009-07-30 15:00:26 +00:00
2011-04-21 15:53:30 +00:00
long long int fineSize = sizeof ( float ) * amplifiedCells * 7 + // big grids
sizeof ( float ) * totalCells * 8 + // small grids
sizeof ( float ) * 128 * 128 * 128 ; // noise tile
2009-07-30 15:00:26 +00:00
2011-04-21 15:53:30 +00:00
long long int totalMB = ( coarseSize + fineSize ) / ( 1024 * 1024 ) ;
2009-07-30 15:00:26 +00:00
2011-04-21 15:53:30 +00:00
return totalMB ;
2009-07-30 15:00:26 +00:00
}
2009-09-16 17:43:09 +00:00
static void bresenham_linie_3D ( int x1 , int y1 , int z1 , int x2 , int y2 , int z2 , float * tRay , bresenham_callback cb , float * result , float * input , int res [ 3 ] , float correct )
2009-07-30 15:00:26 +00:00
{
2010-03-22 09:30:00 +00:00
int dx , dy , dz , i , l , m , n , x_inc , y_inc , z_inc , err_1 , err_2 , dx2 , dy2 , dz2 ;
int pixel [ 3 ] ;
pixel [ 0 ] = x1 ;
pixel [ 1 ] = y1 ;
pixel [ 2 ] = z1 ;
dx = x2 - x1 ;
dy = y2 - y1 ;
dz = z2 - z1 ;
x_inc = ( dx < 0 ) ? - 1 : 1 ;
l = abs ( dx ) ;
y_inc = ( dy < 0 ) ? - 1 : 1 ;
m = abs ( dy ) ;
z_inc = ( dz < 0 ) ? - 1 : 1 ;
n = abs ( dz ) ;
dx2 = l < < 1 ;
dy2 = m < < 1 ;
dz2 = n < < 1 ;
if ( ( l > = m ) & & ( l > = n ) ) {
err_1 = dy2 - l ;
err_2 = dz2 - l ;
for ( i = 0 ; i < l ; i + + ) {
2012-04-28 21:46:43 +00:00
if ( cb ( result , input , res , pixel , tRay , correct ) < = FLT_EPSILON )
2010-03-22 09:30:00 +00:00
break ;
if ( err_1 > 0 ) {
pixel [ 1 ] + = y_inc ;
err_1 - = dx2 ;
}
if ( err_2 > 0 ) {
pixel [ 2 ] + = z_inc ;
err_2 - = dx2 ;
}
err_1 + = dy2 ;
err_2 + = dz2 ;
pixel [ 0 ] + = x_inc ;
}
2012-04-28 21:46:43 +00:00
}
2012-03-24 06:18:31 +00:00
else if ( ( m > = l ) & & ( m > = n ) ) {
2010-03-22 09:30:00 +00:00
err_1 = dx2 - m ;
err_2 = dz2 - m ;
for ( i = 0 ; i < m ; i + + ) {
2012-04-28 21:46:43 +00:00
if ( cb ( result , input , res , pixel , tRay , correct ) < = FLT_EPSILON )
2010-03-22 09:30:00 +00:00
break ;
if ( err_1 > 0 ) {
pixel [ 0 ] + = x_inc ;
err_1 - = dy2 ;
}
if ( err_2 > 0 ) {
pixel [ 2 ] + = z_inc ;
err_2 - = dy2 ;
}
err_1 + = dx2 ;
err_2 + = dz2 ;
pixel [ 1 ] + = y_inc ;
}
2012-04-28 21:46:43 +00:00
}
2012-03-24 06:18:31 +00:00
else {
2010-03-22 09:30:00 +00:00
err_1 = dy2 - n ;
err_2 = dx2 - n ;
for ( i = 0 ; i < n ; i + + ) {
2012-04-28 21:46:43 +00:00
if ( cb ( result , input , res , pixel , tRay , correct ) < = FLT_EPSILON )
2010-03-22 09:30:00 +00:00
break ;
if ( err_1 > 0 ) {
pixel [ 1 ] + = y_inc ;
err_1 - = dz2 ;
}
if ( err_2 > 0 ) {
pixel [ 0 ] + = x_inc ;
err_2 - = dz2 ;
}
err_1 + = dy2 ;
err_2 + = dx2 ;
pixel [ 2 ] + = z_inc ;
}
}
cb ( result , input , res , pixel , tRay , correct ) ;
2009-07-30 15:00:26 +00:00
}
2009-08-20 00:33:59 +00:00
static void get_cell ( float * p0 , int res [ 3 ] , float dx , float * pos , int * cell , int correct )
2009-07-30 15:00:26 +00:00
{
float tmp [ 3 ] ;
2011-11-06 15:39:20 +00:00
sub_v3_v3v3 ( tmp , pos , p0 ) ;
2009-11-10 20:43:45 +00:00
mul_v3_fl ( tmp , 1.0 / dx ) ;
2009-07-30 15:00:26 +00:00
2012-03-06 18:40:15 +00:00
if ( correct ) {
2009-08-02 18:32:56 +00:00
cell [ 0 ] = MIN2 ( res [ 0 ] - 1 , MAX2 ( 0 , ( int ) floor ( tmp [ 0 ] ) ) ) ;
cell [ 1 ] = MIN2 ( res [ 1 ] - 1 , MAX2 ( 0 , ( int ) floor ( tmp [ 1 ] ) ) ) ;
cell [ 2 ] = MIN2 ( res [ 2 ] - 1 , MAX2 ( 0 , ( int ) floor ( tmp [ 2 ] ) ) ) ;
2009-07-30 15:00:26 +00:00
}
2012-03-06 18:40:15 +00:00
else {
2009-08-02 18:32:56 +00:00
cell [ 0 ] = ( int ) floor ( tmp [ 0 ] ) ;
cell [ 1 ] = ( int ) floor ( tmp [ 1 ] ) ;
cell [ 2 ] = ( int ) floor ( tmp [ 2 ] ) ;
2009-07-30 15:00:26 +00:00
}
}
2009-09-16 17:43:09 +00:00
static void smoke_calc_transparency ( float * result , float * input , float * p0 , float * p1 , int res [ 3 ] , float dx , float * light , bresenham_callback cb , float correct )
2009-07-30 15:00:26 +00:00
{
float bv [ 6 ] ;
2010-03-12 14:42:03 +00:00
int a , z , slabsize = res [ 0 ] * res [ 1 ] , size = res [ 0 ] * res [ 1 ] * res [ 2 ] ;
2012-04-28 21:46:43 +00:00
for ( a = 0 ; a < size ; a + + )
2010-03-12 14:42:03 +00:00
result [ a ] = - 1.0f ;
2009-07-30 15:00:26 +00:00
2009-08-20 00:33:59 +00:00
bv [ 0 ] = p0 [ 0 ] ;
bv [ 1 ] = p1 [ 0 ] ;
2009-07-30 15:00:26 +00:00
// y
2009-08-20 00:33:59 +00:00
bv [ 2 ] = p0 [ 1 ] ;
bv [ 3 ] = p1 [ 1 ] ;
2009-07-30 15:00:26 +00:00
// z
2009-08-20 00:33:59 +00:00
bv [ 4 ] = p0 [ 2 ] ;
bv [ 5 ] = p1 [ 2 ] ;
2009-07-30 15:00:26 +00:00
2010-01-25 15:10:14 +00:00
# pragma omp parallel for schedule(static,1)
2012-04-28 21:46:43 +00:00
for ( z = 0 ; z < res [ 2 ] ; z + + )
2010-01-25 15:10:14 +00:00
{
size_t index = z * slabsize ;
int x , y ;
2012-04-28 21:46:43 +00:00
for ( y = 0 ; y < res [ 1 ] ; y + + )
for ( x = 0 ; x < res [ 0 ] ; x + + , index + + )
2009-07-30 15:00:26 +00:00
{
float voxelCenter [ 3 ] ;
float pos [ 3 ] ;
int cell [ 3 ] ;
float tRay = 1.0 ;
2012-04-28 21:46:43 +00:00
if ( result [ index ] > = 0.0f )
2009-09-16 17:43:09 +00:00
continue ;
2009-08-20 00:33:59 +00:00
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 ;
2009-07-30 15:00:26 +00:00
// get starting position (in voxel coords)
2012-04-28 21:46:43 +00:00
if ( BLI_bvhtree_bb_raycast ( bv , light , voxelCenter , pos ) > FLT_EPSILON )
2009-07-30 15:00:26 +00:00
{
// we're ouside
2009-08-20 00:33:59 +00:00
get_cell ( p0 , res , dx , pos , cell , 1 ) ;
2009-07-30 15:00:26 +00:00
}
2012-03-06 18:40:15 +00:00
else {
2009-07-30 15:00:26 +00:00
// we're inside
2009-08-20 00:33:59 +00:00
get_cell ( p0 , res , dx , light , cell , 1 ) ;
2009-07-30 15:00:26 +00:00
}
2009-09-16 17:43:09 +00:00
bresenham_linie_3D ( cell [ 0 ] , cell [ 1 ] , cell [ 2 ] , x , y , z , & tRay , cb , result , input , res , correct ) ;
2009-07-30 15:00:26 +00:00
2009-08-20 00:33:59 +00:00
// convention -> from a RGBA float array, use G value for tRay
2009-09-16 17:43:09 +00:00
// #pragma omp critical
result [ index ] = tRay ;
2009-07-30 15:00:26 +00:00
}
2010-01-25 15:10:14 +00:00
}
2009-07-30 15:00:26 +00:00
}
2011-10-21 00:48:02 +00:00
# endif /* WITH_SMOKE */