Merging r46043 through r46061 from trunk into soc-2011-tomato

This commit is contained in:
Sergey Sharybin
2012-04-29 10:15:04 +00:00
20 changed files with 1323 additions and 667 deletions

View File

@@ -41,11 +41,11 @@ struct FLUID_3D;
void smoke_export(struct FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles);
// low res
struct FLUID_3D *smoke_init(int *res, float *p0);
struct FLUID_3D *smoke_init(int *res, float *p0, float dtdef);
void smoke_free(struct FLUID_3D *fluid);
void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli);
void smoke_step(struct FLUID_3D *fluid, size_t framenr, float fps);
void smoke_step(struct FLUID_3D *fluid, float dtSubdiv);
float *smoke_get_density(struct FLUID_3D *fluid);
float *smoke_get_heat(struct FLUID_3D *fluid);
@@ -53,6 +53,9 @@ float *smoke_get_velocity_x(struct FLUID_3D *fluid);
float *smoke_get_velocity_y(struct FLUID_3D *fluid);
float *smoke_get_velocity_z(struct FLUID_3D *fluid);
/* Moving obstacle velocity provided by blender */
void smoke_get_ob_velocity(struct FLUID_3D *fluid, float **x, float **y, float **z);
float *smoke_get_force_x(struct FLUID_3D *fluid);
float *smoke_get_force_y(struct FLUID_3D *fluid);
float *smoke_get_force_z(struct FLUID_3D *fluid);

View File

@@ -34,6 +34,8 @@
#include "SPHERE.h"
#include <zlib.h>
#include "float.h"
#if PARALLEL==1
#include <omp.h>
#endif // PARALLEL
@@ -42,11 +44,11 @@
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FLUID_3D::FLUID_3D(int *res, float *p0) :
FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
_xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f)
{
// set simulation consts
_dt = DT_DEFAULT; // just in case. set in step from a RNA factor
_dt = dtdef; // just in case. set in step from a RNA factor
// start point of array
_p0[0] = p0[0];
@@ -81,6 +83,9 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
_xVelocity = new float[_totalCells];
_yVelocity = new float[_totalCells];
_zVelocity = new float[_totalCells];
_xVelocityOb = new float[_totalCells];
_yVelocityOb = new float[_totalCells];
_zVelocityOb = new float[_totalCells];
_xVelocityOld = new float[_totalCells];
_yVelocityOld = new float[_totalCells];
_zVelocityOld = new float[_totalCells];
@@ -111,6 +116,9 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
_xVelocity[x] = 0.0f;
_yVelocity[x] = 0.0f;
_zVelocity[x] = 0.0f;
_xVelocityOb[x] = 0.0f;
_yVelocityOb[x] = 0.0f;
_zVelocityOb[x] = 0.0f;
_xVelocityOld[x] = 0.0f;
_yVelocityOld[x] = 0.0f;
_zVelocityOld[x] = 0.0f;
@@ -131,9 +139,15 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
_colloPrev = 1; // default value
setBorderObstacles(); // walls
}
void FLUID_3D::setBorderObstacles()
{
// set side obstacles
int index;
unsigned int index;
for (int y = 0; y < _yRes; y++)
for (int x = 0; x < _xRes; x++)
{
@@ -169,7 +183,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
index += _xRes - 1;
if(_domainBcRight==1) _obstacles[index] = 1;
}
}
FLUID_3D::~FLUID_3D()
@@ -177,6 +190,9 @@ FLUID_3D::~FLUID_3D()
if (_xVelocity) delete[] _xVelocity;
if (_yVelocity) delete[] _yVelocity;
if (_zVelocity) delete[] _zVelocity;
if (_xVelocityOb) delete[] _xVelocityOb;
if (_yVelocityOb) delete[] _yVelocityOb;
if (_zVelocityOb) delete[] _zVelocityOb;
if (_xVelocityOld) delete[] _xVelocityOld;
if (_yVelocityOld) delete[] _yVelocityOld;
if (_zVelocityOld) delete[] _zVelocityOld;
@@ -214,10 +230,18 @@ void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float
//////////////////////////////////////////////////////////////////////
void FLUID_3D::step(float dt)
{
#if 0
// If border rules have been changed
if (_colloPrev != *_borderColli) {
printf("Border collisions changed\n");
// DG TODO: Need to check that no animated obstacle flags are overwritten
setBorderCollisions();
}
#endif
// DG: TODO for the moment redo border for every timestep since it's been deleted every time by moving obstacles
setBorderCollisions();
// set delta time by dt_factor
@@ -786,6 +810,7 @@ void FLUID_3D::project()
memset(_pressure, 0, sizeof(float)*_totalCells);
memset(_divergence, 0, sizeof(float)*_totalCells);
// set velocity and pressure inside of obstacles to zero
setObstacleBoundaries(_pressure, 0, _zRes);
// copy out the boundaries
@@ -798,12 +823,49 @@ void FLUID_3D::project()
if(_domainBcTop == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
else setZeroZ(_zVelocity, _res, 0, _zRes);
/*
{
float maxx = 0, maxy = 0, maxz = 0;
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
{
if(_xVelocity[i] > maxx)
maxx = _xVelocity[i];
if(_yVelocity[i] > maxy)
maxy = _yVelocity[i];
if(_zVelocity[i] > maxz)
maxz = _zVelocity[i];
}
printf("Max velx: %f, vely: %f, velz: %f\n", maxx, maxy, maxz);
}
*/
/*
{
float maxvalue = 0;
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
{
if(_heat[i] > maxvalue)
maxvalue = _heat[i];
}
printf("Max heat: %f\n", maxvalue);
}
*/
// calculate divergence
index = _slabSize + _xRes + 1;
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
for (y = 1; y < _yRes - 1; y++, index += 2)
for (x = 1; x < _xRes - 1; x++, index++)
{
if(_obstacles[index])
{
_divergence[index] = 0.0f;
continue;
}
float xright = _xVelocity[index + 1];
float xleft = _xVelocity[index - 1];
float yup = _yVelocity[index + _xRes];
@@ -811,26 +873,82 @@ void FLUID_3D::project()
float ztop = _zVelocity[index + _slabSize];
float zbottom = _zVelocity[index - _slabSize];
if(_obstacles[index+1]) xright = - _xVelocity[index];
if(_obstacles[index+1]) xright = - _xVelocity[index]; // DG: +=
if(_obstacles[index-1]) xleft = - _xVelocity[index];
if(_obstacles[index+_xRes]) yup = - _yVelocity[index];
if(_obstacles[index-_xRes]) ydown = - _yVelocity[index];
if(_obstacles[index+_slabSize]) ztop = - _zVelocity[index];
if(_obstacles[index-_slabSize]) zbottom = - _zVelocity[index];
if(_obstacles[index+1] & 8) xright += _xVelocityOb[index + 1];
if(_obstacles[index-1] & 8) xleft += _xVelocityOb[index - 1];
if(_obstacles[index+_xRes] & 8) yup += _yVelocityOb[index + _xRes];
if(_obstacles[index-_xRes] & 8) ydown += _yVelocityOb[index - _xRes];
if(_obstacles[index+_slabSize] & 8) ztop += _zVelocityOb[index + _slabSize];
if(_obstacles[index-_slabSize] & 8) zbottom += _zVelocityOb[index - _slabSize];
_divergence[index] = -_dx * 0.5f * (
xright - xleft +
yup - ydown +
ztop - zbottom );
// DG: commenting this helps CG to get a better start, 10-20% speed improvement
// _pressure[index] = 0.0f;
// Pressure is zero anyway since now a local array is used
_pressure[index] = 0.0f;
}
/*
{
float maxvalue = 0;
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
{
if(_divergence[i] > maxvalue)
maxvalue = _divergence[i];
}
printf("Max divergence: %f\n", maxvalue);
}
*/
copyBorderAll(_pressure, 0, _zRes);
/*
{
float maxvalue = 0;
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
{
if(_pressure[i] > maxvalue)
maxvalue = _pressure[i];
}
printf("Max pressure BEFORE: %f\n", maxvalue);
}
*/
// solve Poisson equation
solvePressurePre(_pressure, _divergence, _obstacles);
{
float maxvalue = 0;
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
{
if(_pressure[i] > maxvalue)
maxvalue = _pressure[i];
/* HACK: Animated collision object sometimes result in a non converging solvePressurePre() */
if(_pressure[i] > _dx * _dt)
_pressure[i] = _dx * _dt;
else if(_pressure[i] < -_dx * _dt)
_pressure[i] = -_dx * _dt;
// if(_obstacle[i] && _pressure[i] != 0.0)
// printf("BAD PRESSURE i\n");
// if(_pressure[i]>1)
// printf("index: %d\n", i);
}
// printf("Max pressure: %f, dx: %f\n", maxvalue, _dx);
}
setObstaclePressure(_pressure, 0, _zRes);
// project out solution
@@ -848,12 +966,74 @@ void FLUID_3D::project()
}
}
setObstacleVelocity(0, _zRes);
if (_pressure) delete[] _pressure;
if (_divergence) delete[] _divergence;
}
//////////////////////////////////////////////////////////////////////
// calculate the obstacle velocity at boundary
//////////////////////////////////////////////////////////////////////
void FLUID_3D::setObstacleVelocity(int zBegin, int zEnd)
{
// completely TODO <-- who wrote this and what is here TODO? DG
const size_t index_ = _slabSize + _xRes + 1;
//int vIndex=_slabSize + _xRes + 1;
int bb=0;
int bt=0;
if (zBegin == 0) {bb = 1;}
if (zEnd == _zRes) {bt = 1;}
// tag remaining obstacle blocks
for (int z = zBegin + bb; z < zEnd - bt; z++)
{
size_t index = index_ +(z-1)*_slabSize;
for (int y = 1; y < _yRes - 1; y++, index += 2)
{
for (int x = 1; x < _xRes - 1; x++, index++)
{
if (!_obstacles[index])
{
// if(_obstacles[index+1]) xright = - _xVelocityOb[index];
if((_obstacles[index - 1] & 8) && abs(_xVelocityOb[index - 1]) > FLT_EPSILON )
{
// printf("velocity x!\n");
_xVelocity[index] = _xVelocityOb[index - 1];
_xVelocity[index - 1] = _xVelocityOb[index - 1];
}
// if(_obstacles[index+_xRes]) yup = - _yVelocityOb[index];
if((_obstacles[index - _xRes] & 8) && abs(_yVelocityOb[index - _xRes]) > FLT_EPSILON)
{
// printf("velocity y!\n");
_yVelocity[index] = _yVelocityOb[index - _xRes];
_yVelocity[index - _xRes] = _yVelocityOb[index - _xRes];
}
// if(_obstacles[index+_slabSize]) ztop = - _zVelocityOb[index];
if((_obstacles[index - _slabSize] & 8) && abs(_zVelocityOb[index - _slabSize]) > FLT_EPSILON)
{
// printf("velocity z!\n");
_zVelocity[index] = _zVelocityOb[index - _slabSize];
_zVelocity[index - _slabSize] = _zVelocityOb[index - _slabSize];
}
}
else
{
_density[index] = 0;
}
//vIndex++;
} // x loop
//vIndex += 2;
} // y loop
//vIndex += 2 * _xRes;
} // z loop
}
//////////////////////////////////////////////////////////////////////
// diffuse heat
@@ -892,7 +1072,7 @@ void FLUID_3D::addObstacle(OBSTACLE* obstacle)
void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
{
// compleately TODO
// completely TODO <-- who wrote this and what is here TODO? DG
const size_t index_ = _slabSize + _xRes + 1;
@@ -914,7 +1094,7 @@ void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
for (int x = 1; x < _xRes - 1; x++, index++)
{
// could do cascade of ifs, but they are a pain
if (_obstacles[index])
if (_obstacles[index] /* && !(_obstacles[index] & 8) DG TODO TEST THIS CONDITION */)
{
const int top = _obstacles[index + _slabSize];
const int bottom= _obstacles[index - _slabSize];
@@ -928,9 +1108,11 @@ void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
// const bool fully = (up && down);
//const bool fullx = (left && right);
/*
_xVelocity[index] =
_yVelocity[index] =
_zVelocity[index] = 0.0f;
*/
_pressure[index] = 0.0f;
// average pressure neighbors
@@ -1253,7 +1435,35 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
setZeroBorder(_density, res, zBegin, zEnd);
setZeroBorder(_heat, res, zBegin, zEnd);
#if 0
{
const size_t index_ = _slabSize + _xRes + 1;
int bb=0;
int bt=0;
if (zBegin == 0) {bb = 1;}
if (zEnd == _zRes) {bt = 1;}
for (int z = zBegin + bb; z < zEnd - bt; z++)
{
size_t index = index_ +(z-1)*_slabSize;
for (int y = 1; y < _yRes - 1; y++, index += 2)
{
for (int x = 1; x < _xRes - 1; x++, index++)
{
// clean custom velocities from moving obstacles again
if (_obstacles[index])
{
_xVelocity[index] =
_yVelocity[index] =
_zVelocity[index] = 0.0f;
}
}
}
}
}
#endif
/*int begin=zBegin * _slabSize;
int end=begin + (zEnd - zBegin) * _slabSize;

View File

@@ -39,9 +39,6 @@
// #include "WTURBULENCE.h"
#include "VEC3.h"
// timestep default value for nice appearance
#define DT_DEFAULT 0.1f;
using namespace std;
using namespace BasicVector;
class WTURBULENCE;
@@ -49,7 +46,7 @@ class WTURBULENCE;
class FLUID_3D
{
public:
FLUID_3D(int *res, /* int amplify, */ float *p0);
FLUID_3D(int *res, /* int amplify, */ float *p0, float dtdef);
FLUID_3D() {};
virtual ~FLUID_3D();
@@ -72,7 +69,7 @@ class FLUID_3D
int yRes() const { return _yRes; };
int zRes() const { return _zRes; };
public:
public:
// dimensions
int _xRes, _yRes, _zRes, _maxRes;
Vec3Int _res;
@@ -89,6 +86,8 @@ class FLUID_3D
void artificialDampingSL(int zBegin, int zEnd);
void artificialDampingExactSL(int pos);
void setBorderObstacles();
// fields
float* _density;
float* _densityOld;
@@ -97,13 +96,17 @@ class FLUID_3D
float* _xVelocity;
float* _yVelocity;
float* _zVelocity;
float* _xVelocityOb;
float* _yVelocityOb;
float* _zVelocityOb;
float* _xVelocityOld;
float* _yVelocityOld;
float* _zVelocityOld;
float* _xForce;
float* _yForce;
float* _zForce;
unsigned char* _obstacles;
unsigned char* _obstacles; /* only used (usefull) for static obstacles like domain boundaries */
unsigned char* _obstaclesAnim;
// Required for proper threading:
float* _xVelocityTemp;
@@ -137,6 +140,8 @@ class FLUID_3D
// have to recalibrate borders if nothing has changed
void setBorderCollisions();
void setObstacleVelocity(int zBegin, int zEnd);
// WTURBULENCE object, if active
// WTURBULENCE* _wTurbulence;

View File

@@ -27,9 +27,11 @@
#define OBSTACLE_H
enum OBSTACLE_FLAGS {
EMPTY = 0,
EMPTY = 0,
/* 1 is used to flag an object cell */
MARCHED = 2,
RETIRED = 4
RETIRED = 4,
ANIMATED = 8,
};
class OBSTACLE

View File

@@ -431,8 +431,11 @@ void WTURBULENCE::decomposeEnergy(float *_energy, float *_highFreqEnergy)
// compute velocity from energies and march into obstacles
// for wavelet decomposition
//////////////////////////////////////////////////////////////////////
void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float* zvel, unsigned char *obstacles)
void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float* zvel, unsigned char *origObstacles)
{
unsigned char *obstacles = new unsigned char[_totalCellsSm];
memcpy(obstacles, origObstacles, sizeof(unsigned char) * _totalCellsSm);
// compute everywhere
for (int x = 0; x < _totalCellsSm; x++)
_energy[x] = 0.5f * (xvel[x] * xvel[x] + yvel[x] * yvel[x] + zvel[x] * zvel[x]);
@@ -506,7 +509,9 @@ void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float*
for (int y = 1; y < _yResSm - 1; y++, index += 2)
for (int x = 1; x < _xResSm - 1; x++, index++)
if (obstacles[index])
obstacles[index] = 1;
obstacles[index] = 1; // DG TODO ? animated obstacle flag?
free(obstacles);
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -19,6 +19,7 @@
* All rights reserved.
*
* Contributor(s): Daniel Genrich
* Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -36,10 +37,10 @@
#include <math.h>
// y in smoke is z in blender
extern "C" FLUID_3D *smoke_init(int *res, float *p0)
extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef)
{
// smoke lib uses y as top-bottom/vertical axis where blender uses z
FLUID_3D *fluid = new FLUID_3D(res, p0);
FLUID_3D *fluid = new FLUID_3D(res, p0, dtdef);
// printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
@@ -78,41 +79,9 @@ extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z
return x + y * max_x;
}
extern "C" void smoke_step(FLUID_3D *fluid, size_t framenr, float fps)
extern "C" void smoke_step(FLUID_3D *fluid, float dtSubdiv)
{
/* stability values copied from wturbulence.cpp */
const int maxSubSteps = 25;
const float maxVel = 0.5f; /* TODO: maybe 0.5 is still too high, please confirm! -dg */
float dt = DT_DEFAULT;
float maxVelMag = 0.0f;
int totalSubsteps;
int substep = 0;
float dtSubdiv;
/* get max velocity and lower the dt value if it is too high */
size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
for(size_t i = 0; i < size; i++)
{
float vtemp = (fluid->_xVelocity[i]*fluid->_xVelocity[i]+fluid->_yVelocity[i]*fluid->_yVelocity[i]+fluid->_zVelocity[i]*fluid->_zVelocity[i]);
if(vtemp > maxVelMag)
maxVelMag = vtemp;
}
/* adapt timestep for different framerates, dt = 0.1 is at 25fps */
dt *= (25.0f / fps);
maxVelMag = sqrt(maxVelMag) * dt * (*(fluid->_dtFactor));
totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */
totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
dtSubdiv = (float)dt / (float)totalSubsteps;
// printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
for(substep = 0; substep < totalSubsteps; substep++)
fluid->step(dtSubdiv);
fluid->step(dtSubdiv);
}
extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
@@ -307,6 +276,18 @@ extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
return fluid->_obstacles;
}
extern "C" void smoke_get_ob_velocity(struct FLUID_3D *fluid, float **x, float **y, float **z)
{
*x = fluid->_xVelocityOb;
*y = fluid->_yVelocityOb;
*z = fluid->_zVelocityOb;
}
extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid)
{
return fluid->_obstaclesAnim;
}
extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
{
wt->setNoise(type);

View File

@@ -100,6 +100,15 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
sub.prop(flow, "use_absolute")
sub.prop(flow, "density")
sub.prop(flow, "temperature")
elif md.smoke_type == 'COLLISION':
coll = md.coll_settings
split = layout.split()
col = split.column()
col.prop(coll, "collision_type")
class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):

View File

@@ -637,10 +637,6 @@ class USERPREF_PT_theme(Panel):
col.label(text="Tooltip:")
ui_items_general(col, ui)
ui = theme.user_interface.wcol_tooltip
col.label(text="Tooltip:")
ui_items_general(col, ui)
ui = theme.user_interface.wcol_menu_item
col.label(text="Menu Item:")
ui_items_general(col, ui)

View File

@@ -21,6 +21,7 @@
* The Original Code is: all of this file.
*
* Contributor(s): Daniel Genrich
* Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -53,6 +54,7 @@
#include "BKE_bvhutils.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_collision.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_effect.h"
@@ -118,8 +120,7 @@ static void tend ( void )
gettimeofday ( &_tend,&tz );
}
#if 0 // unused
static double tval()
static double tval( void )
{
double t1, t2;
t1 = ( double ) _tstart.tv_sec*1000 + ( double ) _tstart.tv_usec/ ( 1000 );
@@ -127,14 +128,16 @@ static double tval()
return t2-t1;
}
#endif
#endif
struct Object;
struct Scene;
struct DerivedMesh;
struct SmokeModifierData;
#define TRI_UVOFFSET (1.0 / 4.0)
#define TRI_UVOFFSET (1./4.)
// timestep default value for nice appearance 0.1f
#define DT_DEFAULT 0.1f
/* forward declerations */
static void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *tris, int numfaces, int numtris, int **tridivs, float cell_len);
@@ -159,7 +162,7 @@ void smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Obje
static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm)
{
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
{
size_t i;
float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
@@ -171,7 +174,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
res = smd->domain->maxres;
// get BB of domain
for (i = 0; i < dm->getNumVerts(dm); i++)
for(i = 0; i < dm->getNumVerts(dm); i++)
{
float tmp[3];
@@ -198,32 +201,32 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
// printf("size: %f, %f, %f\n", size[0], size[1], size[2]);
// prevent crash when initializing a plane as domain
if ((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
if((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
return 0;
if (size[0] > size[1])
if(size[0] > size[1])
{
if (size[0] > size[2])
if(size[0] > size[2])
{
scale = res / size[0];
smd->domain->dx = size[0] / res;
smd->domain->dx = size[0] / res; // dx is in global coords
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);
}
else {
scale = res / size[2];
smd->domain->dx = size[2] / res;
smd->domain->dx = size[2] / res; // dx is in global coords
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);
}
}
else {
if (size[1] > size[2])
if(size[1] > size[2])
{
scale = res / size[1];
smd->domain->dx = size[1] / res;
smd->domain->dx = size[1] / res; // dx is in global coords
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);
@@ -243,10 +246,10 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
// printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
// dt max is 0.1
smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0);
smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, DT_DEFAULT);
smd->time = scene->r.cfra;
if (smd->domain->flags & MOD_SMOKE_HIGHRES)
if(smd->domain->flags & MOD_SMOKE_HIGHRES)
{
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);
@@ -257,19 +260,19 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
// printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n");
}
if (!smd->domain->shadow)
if(!smd->domain->shadow)
smd->domain->shadow = MEM_callocN(sizeof(float) * smd->domain->res[0] * smd->domain->res[1] * smd->domain->res[2], "SmokeDomainShadow");
smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta), &(smd->domain->time_scale), &(smd->domain->vorticity), &(smd->domain->border_collisions));
if (smd->domain->wt)
if(smd->domain->wt)
{
smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength));
// printf("smoke_initWaveletBlenderRNA\n");
}
return 1;
}
else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
else if((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
{
// handle flow object here
// XXX TODO
@@ -288,7 +291,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
}
/*
if (!smd->flow->bvh)
if(!smd->flow->bvh)
{
// smd->flow->bvh = MEM_callocN(sizeof(BVHTreeFromMesh), "smoke_bvhfromfaces");
// bvhtree_from_mesh_faces(smd->flow->bvh, dm, 0.0, 2, 6);
@@ -301,28 +304,33 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
return 1;
}
else if ((smd->type & MOD_SMOKE_TYPE_COLL))
else if((smd->type & MOD_SMOKE_TYPE_COLL))
{
smd->time = scene->r.cfra;
// todo: delete this when loading colls work -dg
if (!smd->coll)
smokeModifier_createType(smd);
if (!smd->coll->points)
if(!smd->coll)
{
smokeModifier_createType(smd);
}
if(!smd->coll->points)
{
// init collision points
SmokeCollSettings *scs = smd->coll;
smd->time = scene->r.cfra;
// copy obmat
copy_m4_m4(scs->mat, ob->obmat);
copy_m4_m4(scs->mat_old, ob->obmat);
DM_ensure_tessface(dm);
fill_scs_points(ob, dm, scs);
// DEBUG printf("scs->dx: %f\n", scs->dx);
}
if (!smd->coll->bvhtree)
if(!smd->coll->bvhtree)
{
smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
}
@@ -337,50 +345,52 @@ 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;
int *tridivs = NULL;
float cell_len = 1.0 / 50.0; // for res = 50
// DG TODO: need to do this dynamically according to the domain object!
float cell_len = scs->dx;
int newdivs = 0;
int quads = 0, facecounter = 0;
// count quads
for (i = 0; i < dm->getNumTessFaces(dm); i++)
for(i = 0; i < dm->getNumTessFaces(dm); i++)
{
if (mface[i].v4)
if(mface[i].v4)
quads++;
}
calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumTessFaces(dm), dm->getNumTessFaces(dm) + quads, &tridivs, cell_len);
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);
// count triangle divisions
for (i = 0; i < dm->getNumTessFaces(dm) + quads; i++)
for(i = 0; i < dm->getNumTessFaces(dm) + quads; i++)
{
divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1);
divs += (scs->tridivs[3 * i] + 1) * (scs->tridivs[3 * i + 1] + 1) * (scs->tridivs[3 * i + 2] + 1);
}
// printf("divs: %d\n", divs);
scs->points = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPoints");
scs->points_old = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPointsOld");
for (i = 0; i < dm->getNumVerts(dm); i++)
for(i = 0; i < dm->getNumVerts(dm); i++)
{
float tmpvec[3];
copy_v3_v3(tmpvec, mvert[i].co);
mul_m4_v3(ob->obmat, tmpvec);
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
copy_v3_v3(&scs->points[i * 3], tmpvec);
}
for (i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
{
int again = 0;
do
{
int j, k;
int divs1 = tridivs[3 * facecounter + 0];
int divs2 = tridivs[3 * facecounter + 1];
//int divs3 = tridivs[3 * facecounter + 2];
int divs1 = scs->tridivs[3 * facecounter + 0];
int divs2 = scs->tridivs[3 * facecounter + 1];
//int divs3 = scs->tridivs[3 * facecounter + 2];
float side1[3], side2[3], trinormorg[3], trinorm[3];
if (again == 1 && mface[i].v4)
if(again == 1 && mface[i].v4)
{
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);
@@ -395,23 +405,23 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
copy_v3_v3(trinorm, trinormorg);
mul_v3_fl(trinorm, 0.25 * cell_len);
for (j = 0; j <= divs1; j++)
for(j = 0; j <= divs1; j++)
{
for (k = 0; k <= divs2; k++)
for(k = 0; k <= divs2; k++)
{
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];
if (uf+vf > 1.0)
if(uf+vf > 1.0)
{
// printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
continue;
}
copy_v3_v3(p1, mvert[ mface[i].v1 ].co);
if (again == 1 && mface[i].v4)
if(again == 1 && mface[i].v4)
{
copy_v3_v3(p2, mvert[ mface[i].v3 ].co);
copy_v3_v3(p3, mvert[ mface[i].v4 ].co);
@@ -428,40 +438,211 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
add_v3_v3v3(p, p1, p2);
add_v3_v3(p, p3);
if (newdivs > divs)
if(newdivs > divs)
printf("mem problem\n");
// mMovPoints.push_back(p + trinorm);
add_v3_v3v3(tmpvec, p, trinorm);
mul_m4_v3(ob->obmat, tmpvec);
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
newdivs++;
if (newdivs > divs)
if(newdivs > divs)
printf("mem problem\n");
// mMovPoints.push_back(p - trinorm);
copy_v3_v3(tmpvec, p);
sub_v3_v3(tmpvec, trinorm);
mul_m4_v3(ob->obmat, tmpvec);
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
newdivs++;
}
}
if (again == 0 && mface[i].v4)
if(again == 0 && mface[i].v4)
again++;
else
again = 0;
facecounter++;
} while (again!=0);
} while(again!=0);
}
scs->numverts = dm->getNumVerts(dm);
// DG TODO: also save triangle count?
scs->numpoints = dm->getNumVerts(dm) + newdivs;
MEM_freeN(tridivs);
for(i = 0; i < scs->numpoints * 3; i++)
{
scs->points_old[i] = scs->points[i];
}
}
static void fill_scs_points_anim(Object *UNUSED(ob), DerivedMesh *dm, SmokeCollSettings *scs)
{
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;
}
/*! init triangle divisions */
@@ -472,22 +653,22 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
// mTriangleDivs3.resize( faces.size() );
size_t i = 0, facecounter = 0;
float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale);
float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale); get max scale value
float maxpart = ABS(maxscale[0]);
float scaleFac = 0;
float fsTri = 0;
if (ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
if (ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
scaleFac = 1.0 / maxpart;
// featureSize = mLevel[mMaxRefine].nodeSize
fsTri = cell_len * 0.5 * scaleFac;
fsTri = cell_len * 0.75 * scaleFac; // fsTri = cell_len * 0.9;
if (*tridivs)
if(*tridivs)
MEM_freeN(*tridivs);
*tridivs = MEM_callocN(sizeof(int) * numtris * 3, "Smoke_Tridivs");
for (i = 0, facecounter = 0; i < numfaces; i++)
for(i = 0, facecounter = 0; i < numfaces; i++)
{
float p0[3], p1[3], p2[3];
float side1[3];
@@ -506,21 +687,22 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
sub_v3_v3v3(side2, p2, p0);
sub_v3_v3v3(side3, p1, p2);
if (dot_v3v3(side1, side1) > fsTri*fsTri)
if(dot_v3v3(side1, side1) > fsTri*fsTri)
{
float tmp = normalize_v3(side1);
divs1 = (int)ceil(tmp/fsTri);
}
if (dot_v3v3(side2, side2) > fsTri*fsTri)
if(dot_v3v3(side2, side2) > fsTri*fsTri)
{
float tmp = normalize_v3(side2);
divs2 = (int)ceil(tmp/fsTri);
/*
/*
// debug
if (i==0)
if(i==0)
printf("b tmp: %f, fsTri: %f, divs2: %d\n", tmp, fsTri, divs2);
*/
}
(*tridivs)[3 * facecounter + 0] = divs1;
@@ -528,7 +710,7 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
(*tridivs)[3 * facecounter + 2] = divs3;
// TODO quad case
if (faces[i].v4)
if(faces[i].v4)
{
divs1=0, divs2=0, divs3=0;
@@ -545,12 +727,12 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
sub_v3_v3v3(side2, p2, p0);
sub_v3_v3v3(side3, p1, p2);
if (dot_v3v3(side1, side1) > fsTri*fsTri)
if(dot_v3v3(side1, side1) > fsTri*fsTri)
{
float tmp = normalize_v3(side1);
divs1 = (int)ceil(tmp/fsTri);
}
if (dot_v3v3(side2, side2) > fsTri*fsTri)
if(dot_v3v3(side2, side2) > fsTri*fsTri)
{
float tmp = normalize_v3(side2);
divs2 = (int)ceil(tmp/fsTri);
@@ -568,19 +750,19 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
static void smokeModifier_freeDomain(SmokeModifierData *smd)
{
if (smd->domain)
if(smd->domain)
{
if (smd->domain->shadow)
if(smd->domain->shadow)
MEM_freeN(smd->domain->shadow);
smd->domain->shadow = NULL;
if (smd->domain->fluid)
if(smd->domain->fluid)
smoke_free(smd->domain->fluid);
if (smd->domain->wt)
if(smd->domain->wt)
smoke_turbulence_free(smd->domain->wt);
if (smd->domain->effector_weights)
if(smd->domain->effector_weights)
MEM_freeN(smd->domain->effector_weights);
smd->domain->effector_weights = NULL;
@@ -594,10 +776,10 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd)
static void smokeModifier_freeFlow(SmokeModifierData *smd)
{
if (smd->flow)
if(smd->flow)
{
/*
if (smd->flow->bvh)
if(smd->flow->bvh)
{
free_bvhtree_from_mesh(smd->flow->bvh);
MEM_freeN(smd->flow->bvh);
@@ -611,22 +793,37 @@ static void smokeModifier_freeFlow(SmokeModifierData *smd)
static void smokeModifier_freeCollision(SmokeModifierData *smd)
{
if (smd->coll)
if(smd->coll)
{
if (smd->coll->points)
SmokeCollSettings *scs = smd->coll;
if(scs->numpoints)
{
MEM_freeN(smd->coll->points);
smd->coll->points = NULL;
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;
}
}
if (smd->coll->bvhtree)
if(scs->bvhtree)
{
BLI_bvhtree_free(smd->coll->bvhtree);
smd->coll->bvhtree = NULL;
BLI_bvhtree_free(scs->bvhtree);
scs->bvhtree = NULL;
}
#ifdef USE_SMOKE_COLLISION_DM
if (smd->coll->dm)
if(smd->coll->dm)
smd->coll->dm->release(smd->coll->dm);
smd->coll->dm = NULL;
#endif
@@ -638,7 +835,7 @@ static void smokeModifier_freeCollision(SmokeModifierData *smd)
void smokeModifier_reset_turbulence(struct SmokeModifierData *smd)
{
if (smd && smd->domain && smd->domain->wt)
if(smd && smd->domain && smd->domain->wt)
{
smoke_turbulence_free(smd->domain->wt);
smd->domain->wt = NULL;
@@ -647,15 +844,15 @@ void smokeModifier_reset_turbulence(struct SmokeModifierData *smd)
void smokeModifier_reset(struct SmokeModifierData *smd)
{
if (smd)
if(smd)
{
if (smd->domain)
if(smd->domain)
{
if (smd->domain->shadow)
if(smd->domain->shadow)
MEM_freeN(smd->domain->shadow);
smd->domain->shadow = NULL;
if (smd->domain->fluid)
if(smd->domain->fluid)
{
smoke_free(smd->domain->fluid);
smd->domain->fluid = NULL;
@@ -667,10 +864,10 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
// printf("reset domain end\n");
}
else if (smd->flow)
else if(smd->flow)
{
/*
if (smd->flow->bvh)
if(smd->flow->bvh)
{
free_bvhtree_from_mesh(smd->flow->bvh);
MEM_freeN(smd->flow->bvh);
@@ -678,33 +875,33 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
smd->flow->bvh = NULL;
*/
}
else if (smd->coll)
else if(smd->coll)
{
if (smd->coll->points)
SmokeCollSettings *scs = smd->coll;
if(scs->numpoints && scs->points)
{
MEM_freeN(smd->coll->points);
smd->coll->points = NULL;
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;
}
}
if (smd->coll->bvhtree)
{
BLI_bvhtree_free(smd->coll->bvhtree);
smd->coll->bvhtree = NULL;
}
#ifdef USE_SMOKE_COLLISION_DM
if (smd->coll->dm)
smd->coll->dm->release(smd->coll->dm);
smd->coll->dm = NULL;
#endif
}
}
}
void smokeModifier_free (SmokeModifierData *smd)
{
if (smd)
if(smd)
{
smokeModifier_freeDomain(smd);
smokeModifier_freeFlow(smd);
@@ -714,11 +911,11 @@ void smokeModifier_free (SmokeModifierData *smd)
void smokeModifier_createType(struct SmokeModifierData *smd)
{
if (smd)
if(smd)
{
if (smd->type & MOD_SMOKE_TYPE_DOMAIN)
if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
{
if (smd->domain)
if(smd->domain)
smokeModifier_freeDomain(smd);
smd->domain = MEM_callocN(sizeof(SmokeDomainSettings), "SmokeDomain");
@@ -745,7 +942,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->beta = 0.1;
smd->domain->time_scale = 1.0;
smd->domain->vorticity = 2.0;
smd->domain->border_collisions = 1; // vertically non-colliding
smd->domain->border_collisions = SM_BORDER_OPEN; // open domain
smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG | MOD_SMOKE_HIGH_SMOOTH;
smd->domain->strength = 2.0;
smd->domain->noise = MOD_SMOKE_NOISEWAVE;
@@ -755,9 +952,9 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->viewsettings = MOD_SMOKE_VIEW_SHOWBIG;
smd->domain->effector_weights = BKE_add_effector_weights(NULL);
}
else if (smd->type & MOD_SMOKE_TYPE_FLOW)
else if(smd->type & MOD_SMOKE_TYPE_FLOW)
{
if (smd->flow)
if(smd->flow)
smokeModifier_freeFlow(smd);
smd->flow = MEM_callocN(sizeof(SmokeFlowSettings), "SmokeFlow");
@@ -773,17 +970,23 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->flow->psys = NULL;
}
else if (smd->type & MOD_SMOKE_TYPE_COLL)
else if(smd->type & MOD_SMOKE_TYPE_COLL)
{
if (smd->coll)
if(smd->coll)
smokeModifier_freeCollision(smd);
smd->coll = MEM_callocN(sizeof(SmokeCollSettings), "SmokeColl");
smd->coll->smd = smd;
smd->coll->points = NULL;
smd->coll->points_old = NULL;
smd->coll->tridivs = NULL;
smd->coll->vel = NULL;
smd->coll->numpoints = 0;
smd->coll->numtris = 0;
smd->coll->bvhtree = NULL;
smd->coll->type = 0; // static obstacle
smd->coll->dx = 1.0f / 50.0f;
#ifdef USE_SMOKE_COLLISION_DM
smd->coll->dm = NULL;
@@ -818,7 +1021,7 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
MEM_freeN(tsmd->domain->effector_weights);
tsmd->domain->effector_weights = MEM_dupallocN(smd->domain->effector_weights);
}
}
else if (tsmd->flow) {
tsmd->flow->density = smd->flow->density;
tsmd->flow->temp = smd->flow->temp;
@@ -845,15 +1048,15 @@ static int get_lamp(Scene *scene, float *light)
int found_lamp = 0;
// try to find a lamp, preferably local
for (base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) {
if (base_tmp->object->type == OB_LAMP) {
for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) {
if(base_tmp->object->type == OB_LAMP) {
Lamp *la = base_tmp->object->data;
if (la->type == LA_LOCAL) {
if(la->type == LA_LOCAL) {
copy_v3_v3(light, base_tmp->object->obmat[3]);
return 1;
}
else if (!found_lamp) {
else if(!found_lamp) {
copy_v3_v3(light, base_tmp->object->obmat[3]);
found_lamp = 1;
}
@@ -863,499 +1066,605 @@ static int get_lamp(Scene *scene, float *light)
return found_lamp;
}
static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
static void smoke_calc_domain(Scene *UNUSED(scene), Object *UNUSED(ob), SmokeModifierData *UNUSED(smd))
{
#if 0
SmokeDomainSettings *sds = smd->domain;
GroupObject *go = NULL;
Base *base = NULL;
Base *base = NULL;
// do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells
if (1)
/* do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells */
if(1)
{
Object *otherobj = NULL;
ModifierData *md = NULL;
unsigned int i;
Object **collobjs = NULL;
unsigned int numcollobj = 0;
collobjs = get_collisionobjects(scene, ob, sds->coll_group, &numcollobj);
if (sds->coll_group) // we use groups since we have 2 domains
go = sds->coll_group->gobject.first;
else
base = scene->base.first;
while (base || go)
for(i = 0; i < numcollobj; i++)
{
otherobj = NULL;
if (sds->coll_group)
{
if (go->ob)
otherobj = go->ob;
}
else
otherobj = base->object;
if (!otherobj)
{
if (sds->coll_group)
go = go->next;
else
base= base->next;
continue;
}
md = modifiers_findByType(otherobj, eModifierType_Smoke);
Object *collob= collobjs[i];
SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke);
// check for active smoke modifier
if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
// 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)
{
SmokeModifierData *smd2 = (SmokeModifierData *)md;
// ??? anything to do here?
if ((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points)
// TODO: only something to do for ANIMATED obstacles: need to update positions
}
}
if(collobjs)
MEM_freeN(collobjs);
}
#endif
}
/* 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 */
{
// we got nice collision object
SmokeCollSettings *scs = smd2->coll;
size_t i, j;
unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid);
float tmp[3];
for (i = 0; i < scs->numpoints; i++)
/* x_current = x_old + (x_new - x_old) * step_current / steps_total */
float mulStep = (float)(((float)substep) / ((float)totalsteps));
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
get_cell(sds->p0, sds->res, sds->dx, cOldpos /* use current position here instead of "pos" */, cell, 0);
// check if cell is valid (in the domain boundary)
for(j = 0; j < 3; j++)
if((cell[j] > sds->res[j] - 1) || (cell[j] < 0))
{
int badcell = 0;
size_t index = 0;
int cell[3];
// 1. get corresponding cell
get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, &scs->points[3 * i], cell, 0);
// check if cell is valid (in the domain boundary)
for (j = 0; j < 3; j++)
if ((cell[j] > sds->res[j] - 1) || (cell[j] < 0))
{
badcell = 1;
break;
}
if (badcell)
continue;
// 2. set cell values (heat, density and velocity)
index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
// printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]);
// printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index);
obstacles[index] = 1;
// for moving gobstacles
/*
const LbmFloat maxVelVal = 0.1666;
const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5;
LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec);
{
const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5;
USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz);
if (usqr>maxusqr) {
// cutoff at maxVelVal
for (int jj=0; jj<3; jj++) {
if (objvel[jj] > 0.0) objvel[jj] = maxVelVal;
if (objvel[jj] < 0.0) objvel[jj] = -maxVelVal;
}
}
}
const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) );
const LbmVec oldov=objvel; // debug
objvel = vec2L((*pNormals)[n]) *dp;
*/
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]);
// 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];
}
}
if (sds->coll_group)
go = go->next;
else
base= base->next;
}
}
// do flows and fluids
if (1)
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++)
{
Object *otherobj = NULL;
ModifierData *md = NULL;
if (sds->fluid_group) // we use groups since we have 2 domains
go = sds->fluid_group->gobject.first;
else
base = scene->base.first;
while (base || go)
{
otherobj = NULL;
if (sds->fluid_group)
{
if (go->ob)
otherobj = go->ob;
}
else
otherobj = base->object;
if (!otherobj)
{
if (sds->fluid_group)
go = go->next;
else
base= base->next;
Object *collob= flowobjs[flowIndex];
SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke);
continue;
}
// check for initialized smoke object
if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
{
// we got nice flow object
SmokeFlowSettings *sfs = smd2->flow;
md = modifiers_findByType(otherobj, eModifierType_Smoke);
// check for active smoke modifier
if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
if(sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected
{
SmokeModifierData *smd2 = (SmokeModifierData *)md;
// check for initialized smoke object
if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
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))
{
// we got nice flow object
SmokeFlowSettings *sfs = smd2->flow;
if (sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected
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)
{
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);
int bigres[3];
short absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE);
short high_emission_smoothing = bigdensity ? (smd->domain->flags & MOD_SMOKE_HIGH_SMOOTH) : 0;
totchild = psys->totchildcache;
}
else
*/
/*
* 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;
// TODO: PART_HAIR not supported whatsoever
totchild=0;
}
else
totchild=psys->totchild*psys->part->disp/100;
sim.scene = scene;
sim.ob = otherobj;
sim.psys = psys;
for(p=0; p<totpart+totchild; p++)
{
int cell[3];
size_t i = 0;
size_t index = 0;
int badcell = 0;
ParticleKey state;
// initialize temp emission map
if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
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
get_cell(sds->p0, sds->res, sds->dx, state.co, cell, 0);
// check if cell is valid (in the domain boundary)
for(i = 0; i < 3; i++)
{
if((cell[i] > sds->res[i] - 1) || (cell[i] < 0))
{
badcell = 1;
break;
}
}
if(badcell)
continue;
// 2. set cell values (heat, density and velocity)
index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // 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))
{
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;
}
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)
{
// 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;
}
}
// mostly copied from particle code
if (psys->part->type==PART_HAIR)
{
/*
if (psys->childcache)
}
} // 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
// 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++)
{
totchild = psys->totchildcache;
}
else
*/
// neighbor cell emission densities (for high resolution smoke smooth interpolation)
float c000, c001, c010, c011, c100, c101, c110, c111;
// 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;
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;
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;
}
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
state.time = smd->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
get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, state.co, cell, 0);
// check if cell is valid (in the domain boundary)
for (i = 0; i < 3; i++)
{
if ((cell[i] > sds->res[i] - 1) || (cell[i] < 0))
{
badcell = 1;
break;
}
}
if (badcell)
continue;
// 2. set cell values (heat, density and velocity)
index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // 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;
// get cell index
index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
// Uses particle velocity as initial velocity for smoke
if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO))
// add emission to low resolution density
if (absolute_flow)
{
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)
{
// init all surrounding cells according to amplification, too
int i, j, k;
smoke_turbulence_get_res(smd->domain->wt, bigres);
for (i = 0; i < smd->domain->amplify + 1; i++)
for (j = 0; j < smd->domain->amplify + 1; j++)
for (k = 0; k < smd->domain->amplify + 1; k++)
{
index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k);
bigdensity[index] = 0.f;
}
if (temp_emission_map[index]>0)
density[index] = temp_emission_map[index];
}
}
} // particles loop
else
{
density[index] += temp_emission_map[index];
if (density[index]>1)
density[index]=1.0f;
}
// apply emission values
if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) {
smoke_turbulence_get_res(sds->wt, bigres);
// initialize variables
int ii, jj, kk, x, y, z, block_size;
size_t index, index_big;
smoke_turbulence_get_res(smd->domain->wt, bigres);
block_size = smd->domain->amplify + 1; // high res block size
// 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++)
/* 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++)
{
// neighbor cell emission densities (for high resolution smoke smooth interpolation)
float c000, c001, c010, c011, c100, c101, c110, c111;
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) {if (temp_emission_map[index]>0) density[index] = temp_emission_map[index];}
else {
density[index] += temp_emission_map[index];
if (density[index]>1) density[index]=1.0f;
}
smoke_turbulence_get_res(smd->domain->wt, bigres);
float fx,fy,fz, interpolated_value;
int shift_x, shift_y, shift_z;
/*
loop through high res blocks if high res enabled
* Do volume interpolation if emitter smoothing
* is enabled
*/
if (bigdensity)
for (ii = 0; ii < block_size; ii++)
for (jj = 0; jj < block_size; jj++)
for (kk = 0; kk < block_size; kk++)
{
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;
float fx,fy,fz, interpolated_value;
int shift_x, shift_y, shift_z;
// 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;
/*
* 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;
// add some contrast / sharpness
// depending on hi-res 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;
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;
}
// add some contrast / sharpness
// depending on hi-res block size
// 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);
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;
// 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;
// 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;
}
if (bigdensity[index_big]>1)
bigdensity[index_big]=1.0f;
}
} // end of hires loop
// 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);
// 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;
if (bigdensity[index_big]>1) bigdensity[index_big]=1.0f;
}
} // end of low res loop
} // end of hires loop
// free temporary emission map
if (temp_emission_map)
MEM_freeN(temp_emission_map);
} // end of low res loop
// free temporary emission map
if (temp_emission_map) MEM_freeN(temp_emission_map);
} // end emission
}
else {
/*
for ()
{
// no psys
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist = FLT_MAX;
BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh);
}*/
}
}
}
if (sds->fluid_group)
go = go->next;
else
base= base->next;
}
}
// do effectors
{
ListBase *effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights);
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);
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;
float voxelCenter[3] = {0,0,0} , vel[3] = {0,0,0} , retvel[3] = {0,0,0};
unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
if (density[index] < FLT_EPSILON)
continue;
vel[0] = velocity_x[index];
vel[1] = velocity_y[index];
vel[2] = velocity_z[index];
voxelCenter[0] = sds->p0[0] + sds->dx * x + sds->dx * 0.5;
voxelCenter[1] = sds->p0[1] + sds->dx * y + sds->dx * 0.5;
voxelCenter[2] = sds->p0[2] + sds->dx * z + sds->dx * 0.5;
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);
} // end emission
}
}
pdEndEffectors(&effectors);
}
if(flowobjs)
MEM_freeN(flowobjs);
}
static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt))
{
ListBase *effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights);
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;
float voxelCenter[3] = {0,0,0} , vel[3] = {0,0,0} , retvel[3] = {0,0,0};
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];
voxelCenter[0] = sds->p0[0] + sds->dx * x + sds->dx * 0.5;
voxelCenter[1] = sds->p0[1] + sds->dx * y + sds->dx * 0.5;
voxelCenter[2] = sds->p0[2] + sds->dx * z + sds->dx * 0.5;
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);
}
}
pdEndEffectors(&effectors);
}
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)
float dt = DT_DEFAULT;
float maxVelMag = 0.0f;
int totalSubsteps;
int substep = 0;
float dtSubdiv;
SmokeDomainSettings *sds = smd->domain;
/* 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];
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;
/* adapt timestep for different framerates, dt = 0.1 is at 25fps */
dt *= (25.0f / fps);
// printf("test maxVel: %f\n", (sds->dx * 1.5) / dt); // gives 0.9
maxVel = (sds->dx * 1.5);
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;
}
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;
// totalSubsteps = 2.0f; // DEBUG
dtSubdiv = (float)dt / (float)totalSubsteps;
// printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
for(substep = 0; substep < totalSubsteps; substep++)
{
// 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
smoke_step(sds->fluid, dtSubdiv);
// move animated obstacle: Done in update_obstacles() */
// where to delete old obstacles from array? Done in update_obstacles() */
}
}
void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
{
if ((smd->type & MOD_SMOKE_TYPE_FLOW))
if((smd->type & MOD_SMOKE_TYPE_FLOW))
{
if (scene->r.cfra >= smd->time)
if(scene->r.cfra >= smd->time)
smokeModifier_init(smd, ob, scene, dm);
if (scene->r.cfra > smd->time)
if(scene->r.cfra > smd->time)
{
// XXX TODO
smd->time = scene->r.cfra;
@@ -1366,40 +1675,102 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
copy_m4_m4(smd->flow->mat, ob->obmat);
*/
}
else if (scene->r.cfra < smd->time)
else if(scene->r.cfra < smd->time)
{
smd->time = scene->r.cfra;
smokeModifier_reset(smd);
}
}
else if (smd->type & MOD_SMOKE_TYPE_COLL)
else if(smd->type & MOD_SMOKE_TYPE_COLL)
{
if (scene->r.cfra >= smd->time)
/* 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;
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;
if(sds->dx < dx)
{
dx = sds->dx;
changed = 1;
}
haveDomain = 1;
}
}
if(!haveDomain)
return;
if(changed)
{
if(dx != scs->dx)
{
scs->dx = dx;
smokeModifier_reset(smd);
}
}
}
if(scene->r.cfra >= smd->time)
smokeModifier_init(smd, ob, scene, dm);
if (scene->r.cfra > smd->time)
if(scene->r.cfra > smd->time)
{
// XXX TODO
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?
smd->time = scene->r.cfra;
#ifdef USE_SMOKE_COLLISION_DM
if (smd->coll->dm)
smd->coll->dm->release(smd->coll->dm);
smd->coll->dm = CDDM_copy_from_tessface(dm);
#endif
// rigid movement support
copy_m4_m4(smd->coll->mat_old, smd->coll->mat);
copy_m4_m4(smd->coll->mat, ob->obmat);
copy_m4_m4(scs->mat_old, scs->mat);
copy_m4_m4(scs->mat, ob->obmat);
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
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);
}
}
else if (scene->r.cfra < smd->time)
else if(scene->r.cfra < smd->time)
{
smd->time = scene->r.cfra;
smokeModifier_reset(smd);
}
}
else if (smd->type & MOD_SMOKE_TYPE_DOMAIN)
else if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
{
SmokeDomainSettings *sds = smd->domain;
float light[3];
@@ -1416,14 +1787,14 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
BKE_ptcache_id_from_smoke(&pid, ob, smd);
BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
if (!smd->domain->fluid || framenr == startframe)
if(!smd->domain->fluid || framenr == startframe)
{
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
BKE_ptcache_validate(cache, framenr);
cache->flag &= ~PTCACHE_REDO_NEEDED;
}
if (!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0)
if(!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0)
return;
smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD;
@@ -1436,21 +1807,21 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
// printf("startframe: %d, framenr: %d\n", startframe, framenr);
if (smokeModifier_init(smd, ob, scene, dm)==0)
if(smokeModifier_init(smd, ob, scene, dm)==0)
{
printf("bad smokeModifier_init\n");
return;
}
/* try to read from cache */
if (BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) {
if(BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) {
BKE_ptcache_validate(cache, framenr);
smd->time = framenr;
return;
}
/* only calculate something when we advanced a single frame */
if (framenr != (int)smd->time+1)
if(framenr != (int)smd->time+1)
return;
/* don't simulate if viewing start frame, but scene frame is not real start frame */
@@ -1462,14 +1833,14 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
smoke_calc_domain(scene, ob, smd);
/* if on second frame, write cache for first frame */
if ((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) {
if((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) {
// create shadows straight after domain initialization so we get nice shadows for startframe, too
if (get_lamp(scene, light))
if(get_lamp(scene, light))
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);
if (sds->wt)
if(sds->wt)
{
if (sds->flags & MOD_SMOKE_DISSOLVE)
if(sds->flags & MOD_SMOKE_DISSOLVE)
smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
smoke_turbulence_step(sds->wt, sds->fluid);
}
@@ -1486,30 +1857,31 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
// simulate the actual smoke (c++ code in intern/smoke)
// DG: interesting commenting this line + deactivating loading of noise files
if (framenr!=startframe)
if(framenr!=startframe)
{
if (sds->flags & MOD_SMOKE_DISSOLVE)
if(sds->flags & MOD_SMOKE_DISSOLVE)
smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
smoke_step(sds->fluid, smd->time, scene->r.frs_sec / scene->r.frs_sec_base);
step(scene, ob, smd, scene->r.frs_sec / scene->r.frs_sec_base);
}
// create shadows before writing cache so they get stored
if (get_lamp(scene, light))
if(get_lamp(scene, light))
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);
if (sds->wt)
if(sds->wt)
{
if (sds->flags & MOD_SMOKE_DISSOLVE)
if(sds->flags & MOD_SMOKE_DISSOLVE)
smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
smoke_turbulence_step(sds->wt, sds->fluid);
}
BKE_ptcache_validate(cache, framenr);
if (framenr != startframe)
if(framenr != startframe)
BKE_ptcache_write(&pid, framenr);
tend();
//printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() );
// printf ( "Frame: %d, Time: %f\n\n", (int)smd->time, ( float ) tval() );
}
}
@@ -1520,7 +1892,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix
// T_ray *= T_vox
*tRay *= exp(input[index]*correct);
if (result[index] < 0.0f)
if(result[index] < 0.0f)
{
#pragma omp critical
result[index] = *tRay;
@@ -1574,7 +1946,7 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
err_1 = dy2 - l;
err_2 = dz2 - l;
for (i = 0; i < l; i++) {
if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
break;
if (err_1 > 0) {
pixel[1] += y_inc;
@@ -1588,12 +1960,12 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
err_2 += dz2;
pixel[0] += x_inc;
}
}
}
else if ((m >= l) && (m >= n)) {
err_1 = dx2 - m;
err_2 = dz2 - m;
for (i = 0; i < m; i++) {
if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
break;
if (err_1 > 0) {
pixel[0] += x_inc;
@@ -1607,12 +1979,12 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
err_2 += dz2;
pixel[1] += y_inc;
}
}
}
else {
err_1 = dy2 - n;
err_2 = dx2 - n;
for (i = 0; i < n; i++) {
if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
break;
if (err_1 > 0) {
pixel[1] += y_inc;
@@ -1654,7 +2026,7 @@ static void smoke_calc_transparency(float *result, float *input, float *p0, floa
float bv[6];
int a, z, slabsize=res[0]*res[1], size= res[0]*res[1]*res[2];
for (a=0; a<size; a++)
for(a=0; a<size; a++)
result[a]= -1.0f;
bv[0] = p0[0];
@@ -1667,27 +2039,27 @@ static void smoke_calc_transparency(float *result, float *input, float *p0, floa
bv[5] = p1[2];
#pragma omp parallel for schedule(static,1)
for (z = 0; z < res[2]; z++)
for(z = 0; z < res[2]; z++)
{
size_t index = z*slabsize;
int x,y;
for (y = 0; y < res[1]; y++)
for (x = 0; x < res[0]; x++, index++)
for(y = 0; y < res[1]; y++)
for(x = 0; x < res[0]; x++, index++)
{
float voxelCenter[3];
float pos[3];
int cell[3];
float tRay = 1.0;
if (result[index] >= 0.0f)
if(result[index] >= 0.0f)
continue;
voxelCenter[0] = p0[0] + dx * x + dx * 0.5;
voxelCenter[1] = p0[1] + dx * y + dx * 0.5;
voxelCenter[2] = p0[2] + dx * z + dx * 0.5;
// get starting position (in voxel coords)
if (BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON)
if(BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON)
{
// we're ouside
get_cell(p0, res, dx, pos, cell, 1);

View File

@@ -104,6 +104,50 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons
return i;
}
/**
* \brief Elem Iter Flag Count
*
* Counts how many flagged / unflagged items are found in this element.
*/
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value)
{
BMIter iter;
BMElem *ele;
int count = 0;
BLI_assert(ELEM(value, TRUE, FALSE));
for (ele = BM_iter_new(&iter, NULL, itype, data); ele; ele = BM_iter_step(&iter)) {
if (BM_elem_flag_test_bool(ele, hflag) == value) {
count++;
}
}
return count;
}
/**
* \brief Mesh Iter Flag Count
*
* Counts how many flagged / unflagged items are found in this mesh.
*/
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value)
{
BMIter iter;
BMElem *ele;
int count = 0;
BLI_assert(ELEM(value, TRUE, FALSE));
for (ele = BM_iter_new(&iter, bm, itype, NULL); ele; ele = BM_iter_step(&iter)) {
if (BM_elem_flag_test_bool(ele, hflag) == value) {
count++;
}
}
return count;
}
/**
* \brief Init Iterator

View File

@@ -117,6 +117,8 @@ typedef struct BMIter {
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index);
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value);
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value);
/* private for bmesh_iterators_inline.c */
void bmiter__vert_of_mesh_begin(struct BMIter *iter);

View File

@@ -56,6 +56,11 @@
#define SM_BORDER_VERTICAL 1
#define SM_BORDER_CLOSED 2
/* collision types */
#define SM_COLL_STATIC 0
#define SM_COLL_RIGID 1
#define SM_COLL_ANIMATED 2
typedef struct SmokeDomainSettings {
struct SmokeModifierData *smd; /* for fast RNA access */
struct FLUID_3D *fluid;
@@ -137,15 +142,16 @@ typedef struct SmokeFlowSettings {
typedef struct SmokeCollSettings {
struct SmokeModifierData *smd; /* for fast RNA access */
struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
// struct DerivedMesh *dm; // UNUSED, ifdef'd in code for now.
float *points;
float *points_old;
float *vel;
float *vel; // UNUSED
int *tridivs;
float mat[4][4];
float mat_old[4][4];
int numpoints;
int numverts; // check if mesh changed
int numtris;
float dx; /* global domain cell length taken from (scale / resolution) */
short type; // static = 0, rigid = 1, dynamic = 2
short pad;
int pad2;

View File

@@ -16,6 +16,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Daniel Genrich
* Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -336,12 +337,25 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
static void rna_def_smoke_coll_settings(BlenderRNA *brna)
{
static EnumPropertyItem smoke_coll_type_items[] = {
{SM_COLL_STATIC, "COLLSTATIC", 0, "Static", "Non moving obstacle"},
{SM_COLL_RIGID, "COLLRIGID", 0, "Rigid", "Rigid obstacle"},
{SM_COLL_ANIMATED, "COLLANIMATED", 0, "Animated", "Animated obstacle"},
{0, NULL, 0, NULL, NULL}};
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SmokeCollSettings", NULL);
RNA_def_struct_ui_text(srna, "Collision Settings", "Smoke collision settings");
RNA_def_struct_sdna(srna, "SmokeCollSettings");
RNA_def_struct_path_func(srna, "rna_SmokeCollSettings_path");
prop = RNA_def_property(srna, "collision_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, smoke_coll_type_items);
RNA_def_property_ui_text(prop, "Collision type", "Collision type");
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
}
void RNA_def_smoke(BlenderRNA *brna)

View File

@@ -32,7 +32,7 @@ set(INC
)
set(INC_SYS
${PTHREADS_INCLUDE_DIRS}
)
set(SRC

View File

@@ -35,4 +35,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']:
incs += ' ' + env['BF_BULLET_INC']
incs += ' ' + env['BF_OPENGL_INC']
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
env.BlenderLib ( 'ge_blen_routines', sources, Split(incs), defs, libtype=['core','player'], priority=[300,35] , cxx_compileflags=env['BGE_CXXFLAGS'])

View File

@@ -59,6 +59,7 @@ set(INC
)
set(INC_SYS
${PTHREADS_INCLUDE_DIRS}
)

View File

@@ -39,4 +39,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']:
if env['WITH_BF_BULLET']:
defs.append('USE_BULLET')
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
env.BlenderLib ( 'ge_converter', sources, Split(incs), defs, libtype=['core','player'], priority=[305,40], cxx_compileflags=env['BGE_CXXFLAGS'])

View File

@@ -55,6 +55,7 @@ set(INC
)
set(INC_SYS
${PTHREADS_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH}
../../../extern/recastnavigation/Recast/Include
../../../extern/recastnavigation/Detour/Include

View File

@@ -52,12 +52,9 @@
#include "RAS_IRasterizer.h"
#include "RAS_IRenderTools.h"
#include "RAS_ICanvas.h"
#include "STR_String.h"
#include "MT_Vector3.h"
#include "MT_Transform.h"
#include "SCA_IInputDevice.h"
#include "KX_Scene.h"
#include "MT_CmMatrix4x4.h"
#include "KX_Camera.h"
#include "KX_FontObject.h"
#include "KX_Dome.h"
@@ -90,6 +87,12 @@
#define DEFAULT_LOGIC_TIC_RATE 60.0
#define DEFAULT_PHYSICS_TIC_RATE 60.0
#ifdef FREE_WINDOWS /* XXX mingw64 (gcc 4.7.0) defines a macro for DrawText that translates to DrawTextA. Not good */
#ifdef DrawText
#undef DrawText
#endif
#endif
const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
"Physics:", // tc_physics
"Logic:", // tc_logic
@@ -1063,37 +1066,30 @@ void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
m_overrideSceneName = forscene;
}
void KX_KetsjiEngine::SetCameraZoom(float camzoom)
{
m_cameraZoom = camzoom;
}
void KX_KetsjiEngine::SetCameraOverrideUseOrtho(bool useOrtho)
{
m_overrideCamUseOrtho = useOrtho;
}
void KX_KetsjiEngine::SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat)
{
m_overrideCamProjMat = mat;
}
void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
{
m_overrideCamViewMat = mat;
}
void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far)
void KX_KetsjiEngine::SetCameraOverrideClipping(float nearfrust, float farfrust)
{
m_overrideCamNear = near;
m_overrideCamFar = far;
m_overrideCamNear = nearfrust;
m_overrideCamFar = farfrust;
}
void KX_KetsjiEngine::SetCameraOverrideLens(float lens)

View File

@@ -47,4 +47,7 @@ if env['WITH_BF_BULLET']:
defs.append('USE_BULLET')
incs += ' #source/gameengine/Physics/Bullet'
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
env.BlenderLib ( 'ge_logic_ketsji', sources, Split(incs), defs, libtype=['core','player'], priority=[320,45], cxx_compileflags=env['BGE_CXXFLAGS'])