Google Summer of Code project: "Smoke Simulator Improvements & Fire".
Documentation & Test blend files: ------------------ http://wiki.blender.org/index.php/User:MiikaH/GSoC-2012-Smoke-Simulator-Improvements Credits: ------------------ Miika Hamalainen (MiikaH): Student / Main programmer Daniel Genrich (Genscher): Mentor / Programmer of merged patches from Smoke2 branch Google: For Google Summer of Code 2012
This commit is contained in:
@@ -40,6 +40,7 @@ set(SRC
|
||||
intern/FLUID_3D_SOLVERS.cpp
|
||||
intern/FLUID_3D_STATIC.cpp
|
||||
intern/LU_HELPER.cpp
|
||||
intern/spectrum.cpp
|
||||
intern/SPHERE.cpp
|
||||
intern/WTURBULENCE.cpp
|
||||
intern/smoke_API.cpp
|
||||
@@ -53,6 +54,7 @@ set(SRC
|
||||
intern/LU_HELPER.h
|
||||
intern/MERSENNETWISTER.h
|
||||
intern/OBSTACLE.h
|
||||
intern/spectrum.h
|
||||
intern/SPHERE.h
|
||||
intern/VEC3.h
|
||||
intern/WAVELET_NOISE.h
|
||||
|
||||
51
intern/smoke/extern/smoke_API.h
vendored
51
intern/smoke/extern/smoke_API.h
vendored
@@ -37,17 +37,23 @@ extern "C" {
|
||||
|
||||
struct FLUID_3D;
|
||||
|
||||
// export
|
||||
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, float dtdef);
|
||||
struct FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, int use_fire, int use_colors);
|
||||
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, float dtSubdiv);
|
||||
void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate,
|
||||
float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp);
|
||||
void smoke_step(struct FLUID_3D *fluid, float gravity[3], float dtSubdiv);
|
||||
|
||||
float *smoke_get_density(struct FLUID_3D *fluid);
|
||||
float *smoke_get_flame(struct FLUID_3D *fluid);
|
||||
float *smoke_get_fuel(struct FLUID_3D *fluid);
|
||||
float *smoke_get_react(struct FLUID_3D *fluid);
|
||||
float *smoke_get_color_r(struct FLUID_3D *fluid);
|
||||
float *smoke_get_color_g(struct FLUID_3D *fluid);
|
||||
float *smoke_get_color_b(struct FLUID_3D *fluid);
|
||||
void smoke_get_rgba(struct FLUID_3D *fluid, float *data, int sequential);
|
||||
void smoke_get_rgba_from_density(struct FLUID_3D *fluid, float color[3], float *data, int sequential);
|
||||
float *smoke_get_heat(struct FLUID_3D *fluid);
|
||||
float *smoke_get_velocity_x(struct FLUID_3D *fluid);
|
||||
float *smoke_get_velocity_y(struct FLUID_3D *fluid);
|
||||
@@ -68,19 +74,44 @@ size_t smoke_get_index2d(int x, int max_x, int y);
|
||||
void smoke_dissolve(struct FLUID_3D *fluid, int speed, int log);
|
||||
|
||||
// wavelet turbulence functions
|
||||
struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype);
|
||||
struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, int use_fire, int use_colors);
|
||||
void smoke_turbulence_free(struct WTURBULENCE *wt);
|
||||
void smoke_turbulence_step(struct WTURBULENCE *wt, struct FLUID_3D *fluid);
|
||||
|
||||
float *smoke_turbulence_get_density(struct WTURBULENCE *wt);
|
||||
float *smoke_turbulence_get_color_r(struct WTURBULENCE *wt);
|
||||
float *smoke_turbulence_get_color_g(struct WTURBULENCE *wt);
|
||||
float *smoke_turbulence_get_color_b(struct WTURBULENCE *wt);
|
||||
void smoke_turbulence_get_rgba(struct WTURBULENCE *wt, float *data, int sequential);
|
||||
void smoke_turbulence_get_rgba_from_density(struct WTURBULENCE *wt, float color[3], float *data, int sequential);
|
||||
float *smoke_turbulence_get_flame(struct WTURBULENCE *wt);
|
||||
float *smoke_turbulence_get_fuel(struct WTURBULENCE *wt);
|
||||
float *smoke_turbulence_get_react(struct WTURBULENCE *wt);
|
||||
void smoke_turbulence_get_res(struct WTURBULENCE *wt, int *res);
|
||||
int smoke_turbulence_get_cells(struct WTURBULENCE *wt);
|
||||
void smoke_turbulence_set_noise(struct WTURBULENCE *wt, int type);
|
||||
void smoke_initWaveletBlenderRNA(struct WTURBULENCE *wt, float *strength);
|
||||
|
||||
void smoke_dissolve_wavelet(struct WTURBULENCE *wt, int speed, int log);
|
||||
|
||||
// export
|
||||
void smoke_turbulence_export(struct WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw);
|
||||
/* export */
|
||||
void smoke_export(struct FLUID_3D *fluid, float *dt, float *dx, float **dens, float **react, float **flame, float **fuel, float **heat, float **heatold,
|
||||
float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles);
|
||||
void smoke_turbulence_export(struct WTURBULENCE *wt, float **dens, float **react, float **flame, float **fuel,
|
||||
float **r, float **g, float **b, float **tcu, float **tcv, float **tcw);
|
||||
|
||||
/* flame spectrum */
|
||||
void flame_get_spectrum(unsigned char *spec, int width, float t1, float t2);
|
||||
|
||||
/* data fields */
|
||||
int smoke_has_heat(struct FLUID_3D *fluid);
|
||||
int smoke_has_fuel(struct FLUID_3D *fluid);
|
||||
int smoke_has_colors(struct FLUID_3D *fluid);
|
||||
int smoke_turbulence_has_fuel(struct WTURBULENCE *wt);
|
||||
int smoke_turbulence_has_colors(struct WTURBULENCE *wt);
|
||||
|
||||
void smoke_ensure_heat(struct FLUID_3D *fluid);
|
||||
void smoke_ensure_fire(struct FLUID_3D *fluid, struct WTURBULENCE *wt);
|
||||
void smoke_ensure_colors(struct FLUID_3D *fluid, struct WTURBULENCE *wt, float init_r, float init_g, float init_b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -44,17 +44,12 @@
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
|
||||
FLUID_3D::FLUID_3D(int *res, float dx, float dtdef, int init_heat, int init_fire, int init_colors) :
|
||||
_xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f)
|
||||
{
|
||||
// set simulation consts
|
||||
_dt = dtdef; // just in case. set in step from a RNA factor
|
||||
|
||||
// start point of array
|
||||
_p0[0] = p0[0];
|
||||
_p0[1] = p0[1];
|
||||
_p0[2] = p0[2];
|
||||
|
||||
_iterations = 100;
|
||||
_tempAmb = 0;
|
||||
_heatDiffusion = 1e-3;
|
||||
@@ -72,7 +67,10 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
|
||||
*/
|
||||
|
||||
// scale the constants according to the refinement of the grid
|
||||
if (!dx)
|
||||
_dx = 1.0f / (float)_maxRes;
|
||||
else
|
||||
_dx = dx;
|
||||
_constantScaling = 64.0f / _maxRes;
|
||||
_constantScaling = (_constantScaling < 1.0f) ? 1.0f : _constantScaling;
|
||||
_vorticityEps = 2.0f / _constantScaling; // Just in case set a default value
|
||||
@@ -94,8 +92,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
|
||||
_zForce = new float[_totalCells];
|
||||
_density = new float[_totalCells];
|
||||
_densityOld = new float[_totalCells];
|
||||
_heat = new float[_totalCells];
|
||||
_heatOld = new float[_totalCells];
|
||||
_obstacles = new unsigned char[_totalCells]; // set 0 at end of step
|
||||
|
||||
// For threaded version:
|
||||
@@ -103,7 +99,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
|
||||
_yVelocityTemp = new float[_totalCells];
|
||||
_zVelocityTemp = new float[_totalCells];
|
||||
_densityTemp = new float[_totalCells];
|
||||
_heatTemp = new float[_totalCells];
|
||||
|
||||
// DG TODO: check if alloc went fine
|
||||
|
||||
@@ -111,8 +106,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
|
||||
{
|
||||
_density[x] = 0.0f;
|
||||
_densityOld[x] = 0.0f;
|
||||
_heat[x] = 0.0f;
|
||||
_heatOld[x] = 0.0f;
|
||||
_xVelocity[x] = 0.0f;
|
||||
_yVelocity[x] = 0.0f;
|
||||
_zVelocity[x] = 0.0f;
|
||||
@@ -128,6 +121,25 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
|
||||
_obstacles[x] = false;
|
||||
}
|
||||
|
||||
/* heat */
|
||||
_heat = _heatOld = _heatTemp = NULL;
|
||||
if (init_heat) {
|
||||
initHeat();
|
||||
}
|
||||
// Fire simulation
|
||||
_flame = _fuel = _fuelTemp = _fuelOld = NULL;
|
||||
_react = _reactTemp = _reactOld = NULL;
|
||||
if (init_fire) {
|
||||
initFire();
|
||||
}
|
||||
// Smoke color
|
||||
_color_r = _color_rOld = _color_rTemp = NULL;
|
||||
_color_g = _color_gOld = _color_gTemp = NULL;
|
||||
_color_b = _color_bOld = _color_bTemp = NULL;
|
||||
if (init_colors) {
|
||||
initColors(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
// boundary conditions of the fluid domain
|
||||
// set default values -> vertically non-colliding
|
||||
_domainBcFront = true;
|
||||
@@ -138,9 +150,70 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
|
||||
_domainBcRight = _domainBcLeft;
|
||||
|
||||
_colloPrev = 1; // default value
|
||||
}
|
||||
|
||||
setBorderObstacles(); // walls
|
||||
void FLUID_3D::initHeat()
|
||||
{
|
||||
if (!_heat) {
|
||||
_heat = new float[_totalCells];
|
||||
_heatOld = new float[_totalCells];
|
||||
_heatTemp = new float[_totalCells];
|
||||
|
||||
for (int x = 0; x < _totalCells; x++)
|
||||
{
|
||||
_heat[x] = 0.0f;
|
||||
_heatOld[x] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FLUID_3D::initFire()
|
||||
{
|
||||
if (!_flame) {
|
||||
_flame = new float[_totalCells];
|
||||
_fuel = new float[_totalCells];
|
||||
_fuelTemp = new float[_totalCells];
|
||||
_fuelOld = new float[_totalCells];
|
||||
_react = new float[_totalCells];
|
||||
_reactTemp = new float[_totalCells];
|
||||
_reactOld = new float[_totalCells];
|
||||
|
||||
for (int x = 0; x < _totalCells; x++)
|
||||
{
|
||||
_flame[x] = 0.0f;
|
||||
_fuel[x] = 0.0f;
|
||||
_fuelTemp[x] = 0.0f;
|
||||
_fuelOld[x] = 0.0f;
|
||||
_react[x] = 0.0f;
|
||||
_reactTemp[x] = 0.0f;
|
||||
_reactOld[x] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FLUID_3D::initColors(float init_r, float init_g, float init_b)
|
||||
{
|
||||
if (!_color_r) {
|
||||
_color_r = new float[_totalCells];
|
||||
_color_rOld = new float[_totalCells];
|
||||
_color_rTemp = new float[_totalCells];
|
||||
_color_g = new float[_totalCells];
|
||||
_color_gOld = new float[_totalCells];
|
||||
_color_gTemp = new float[_totalCells];
|
||||
_color_b = new float[_totalCells];
|
||||
_color_bOld = new float[_totalCells];
|
||||
_color_bTemp = new float[_totalCells];
|
||||
|
||||
for (int x = 0; x < _totalCells; x++)
|
||||
{
|
||||
_color_r[x] = _density[x] * init_r;
|
||||
_color_rOld[x] = 0.0f;
|
||||
_color_g[x] = _density[x] * init_g;
|
||||
_color_gOld[x] = 0.0f;
|
||||
_color_b[x] = _density[x] * init_b;
|
||||
_color_bOld[x] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FLUID_3D::setBorderObstacles()
|
||||
@@ -204,7 +277,6 @@ FLUID_3D::~FLUID_3D()
|
||||
if (_heat) delete[] _heat;
|
||||
if (_heatOld) delete[] _heatOld;
|
||||
if (_obstacles) delete[] _obstacles;
|
||||
// if (_wTurbulence) delete _wTurbulence;
|
||||
|
||||
if (_xVelocityTemp) delete[] _xVelocityTemp;
|
||||
if (_yVelocityTemp) delete[] _yVelocityTemp;
|
||||
@@ -212,23 +284,48 @@ FLUID_3D::~FLUID_3D()
|
||||
if (_densityTemp) delete[] _densityTemp;
|
||||
if (_heatTemp) delete[] _heatTemp;
|
||||
|
||||
if (_flame) delete[] _flame;
|
||||
if (_fuel) delete[] _fuel;
|
||||
if (_fuelTemp) delete[] _fuelTemp;
|
||||
if (_fuelOld) delete[] _fuelOld;
|
||||
if (_react) delete[] _react;
|
||||
if (_reactTemp) delete[] _reactTemp;
|
||||
if (_reactOld) delete[] _reactOld;
|
||||
|
||||
if (_color_r) delete[] _color_r;
|
||||
if (_color_rOld) delete[] _color_rOld;
|
||||
if (_color_rTemp) delete[] _color_rTemp;
|
||||
if (_color_g) delete[] _color_g;
|
||||
if (_color_gOld) delete[] _color_gOld;
|
||||
if (_color_gTemp) delete[] _color_gTemp;
|
||||
if (_color_b) delete[] _color_b;
|
||||
if (_color_bOld) delete[] _color_bOld;
|
||||
if (_color_bTemp) delete[] _color_bTemp;
|
||||
|
||||
// printf("deleted fluid\n");
|
||||
}
|
||||
|
||||
// init direct access functions from blender
|
||||
void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision)
|
||||
void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision, float *burning_rate,
|
||||
float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp)
|
||||
{
|
||||
_alpha = alpha;
|
||||
_beta = beta;
|
||||
_dtFactor = dt_factor;
|
||||
_vorticityRNA = vorticity;
|
||||
_borderColli = borderCollision;
|
||||
_burning_rate = burning_rate;
|
||||
_flame_smoke = flame_smoke;
|
||||
_flame_smoke_color = flame_smoke_color;
|
||||
_flame_vorticity = flame_vorticity;
|
||||
_ignition_temp = flame_ignition_temp;
|
||||
_max_temp = flame_max_temp;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// step simulation once
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void FLUID_3D::step(float dt)
|
||||
void FLUID_3D::step(float dt, float gravity[3])
|
||||
{
|
||||
#if 0
|
||||
// If border rules have been changed
|
||||
@@ -281,7 +378,7 @@ void FLUID_3D::step(float dt)
|
||||
|
||||
wipeBoundariesSL(zBegin, zEnd);
|
||||
addVorticity(zBegin, zEnd);
|
||||
addBuoyancy(_heat, _density, zBegin, zEnd);
|
||||
addBuoyancy(_heat, _density, gravity, zBegin, zEnd);
|
||||
addForce(zBegin, zEnd);
|
||||
|
||||
#if PARALLEL==1
|
||||
@@ -315,10 +412,12 @@ void FLUID_3D::step(float dt)
|
||||
project();
|
||||
#if PARALLEL==1
|
||||
}
|
||||
else
|
||||
else if (i==1)
|
||||
{
|
||||
#endif
|
||||
if (_heat) {
|
||||
diffuseHeat();
|
||||
}
|
||||
#if PARALLEL==1
|
||||
}
|
||||
}
|
||||
@@ -338,6 +437,13 @@ void FLUID_3D::step(float dt)
|
||||
SWAP_POINTERS(_density, _densityOld);
|
||||
SWAP_POINTERS(_heat, _heatOld);
|
||||
|
||||
SWAP_POINTERS(_fuel, _fuelOld);
|
||||
SWAP_POINTERS(_react, _reactOld);
|
||||
|
||||
SWAP_POINTERS(_color_r, _color_rOld);
|
||||
SWAP_POINTERS(_color_g, _color_gOld);
|
||||
SWAP_POINTERS(_color_b, _color_bOld);
|
||||
|
||||
advectMacCormackBegin(0, _zRes);
|
||||
|
||||
#if PARALLEL==1
|
||||
@@ -398,9 +504,6 @@ void FLUID_3D::step(float dt)
|
||||
SWAP_POINTERS(_yVelocity, _yForce);
|
||||
SWAP_POINTERS(_zVelocity, _zForce);
|
||||
|
||||
|
||||
|
||||
|
||||
_totalTime += _dt;
|
||||
_totalSteps++;
|
||||
|
||||
@@ -643,6 +746,15 @@ void FLUID_3D::wipeBoundaries(int zBegin, int zEnd)
|
||||
setZeroBorder(_yVelocity, _res, zBegin, zEnd);
|
||||
setZeroBorder(_zVelocity, _res, zBegin, zEnd);
|
||||
setZeroBorder(_density, _res, zBegin, zEnd);
|
||||
if (_fuel) {
|
||||
setZeroBorder(_fuel, _res, zBegin, zEnd);
|
||||
setZeroBorder(_react, _res, zBegin, zEnd);
|
||||
}
|
||||
if (_color_r) {
|
||||
setZeroBorder(_color_r, _res, zBegin, zEnd);
|
||||
setZeroBorder(_color_g, _res, zBegin, zEnd);
|
||||
setZeroBorder(_color_b, _res, zBegin, zEnd);
|
||||
}
|
||||
}
|
||||
|
||||
void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
|
||||
@@ -668,6 +780,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
|
||||
_yVelocity[index] = 0.0f;
|
||||
_zVelocity[index] = 0.0f;
|
||||
_density[index] = 0.0f;
|
||||
if (_fuel) {
|
||||
_fuel[index] = 0.0f;
|
||||
_react[index] = 0.0f;
|
||||
}
|
||||
if (_color_r) {
|
||||
_color_r[index] = 0.0f;
|
||||
_color_g[index] = 0.0f;
|
||||
_color_b[index] = 0.0f;
|
||||
}
|
||||
|
||||
// right slab
|
||||
index += _xRes - 1;
|
||||
@@ -675,6 +796,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
|
||||
_yVelocity[index] = 0.0f;
|
||||
_zVelocity[index] = 0.0f;
|
||||
_density[index] = 0.0f;
|
||||
if (_fuel) {
|
||||
_fuel[index] = 0.0f;
|
||||
_react[index] = 0.0f;
|
||||
}
|
||||
if (_color_r) {
|
||||
_color_r[index] = 0.0f;
|
||||
_color_g[index] = 0.0f;
|
||||
_color_b[index] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
@@ -690,6 +820,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
|
||||
_yVelocity[index] = 0.0f;
|
||||
_zVelocity[index] = 0.0f;
|
||||
_density[index] = 0.0f;
|
||||
if (_fuel) {
|
||||
_fuel[index] = 0.0f;
|
||||
_react[index] = 0.0f;
|
||||
}
|
||||
if (_color_r) {
|
||||
_color_r[index] = 0.0f;
|
||||
_color_g[index] = 0.0f;
|
||||
_color_b[index] = 0.0f;
|
||||
}
|
||||
|
||||
// top slab
|
||||
index += slabSize - _xRes;
|
||||
@@ -697,6 +836,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
|
||||
_yVelocity[index] = 0.0f;
|
||||
_zVelocity[index] = 0.0f;
|
||||
_density[index] = 0.0f;
|
||||
if (_fuel) {
|
||||
_fuel[index] = 0.0f;
|
||||
_react[index] = 0.0f;
|
||||
}
|
||||
if (_color_r) {
|
||||
_color_r[index] = 0.0f;
|
||||
_color_g[index] = 0.0f;
|
||||
_color_b[index] = 0.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -717,6 +865,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
|
||||
_yVelocity[index] = 0.0f;
|
||||
_zVelocity[index] = 0.0f;
|
||||
_density[index] = 0.0f;
|
||||
if (_fuel) {
|
||||
_fuel[index] = 0.0f;
|
||||
_react[index] = 0.0f;
|
||||
}
|
||||
if (_color_r) {
|
||||
_color_r[index] = 0.0f;
|
||||
_color_g[index] = 0.0f;
|
||||
_color_b[index] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (zEnd == _zRes)
|
||||
@@ -735,6 +892,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
|
||||
_yVelocity[indexx] = 0.0f;
|
||||
_zVelocity[indexx] = 0.0f;
|
||||
_density[indexx] = 0.0f;
|
||||
if (_fuel) {
|
||||
_fuel[index] = 0.0f;
|
||||
_react[index] = 0.0f;
|
||||
}
|
||||
if (_color_r) {
|
||||
_color_r[index] = 0.0f;
|
||||
_color_g[index] = 0.0f;
|
||||
_color_b[index] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,35 +947,6 @@ void FLUID_3D::project()
|
||||
if(!_domainBcTop) 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)
|
||||
@@ -1007,7 +1144,6 @@ void FLUID_3D::diffuseHeat()
|
||||
for (int x = 0; x < _totalCells; x++)
|
||||
if (_obstacles[x])
|
||||
_heat[x] = 0.0f;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -1175,7 +1311,7 @@ void FLUID_3D::setObstacleBoundaries(float *_pressure, int zBegin, int zEnd)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// add buoyancy forces
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd)
|
||||
void FLUID_3D::addBuoyancy(float *heat, float *density, float gravity[3], int zBegin, int zEnd)
|
||||
{
|
||||
int index = zBegin*_slabSize;
|
||||
|
||||
@@ -1183,7 +1319,10 @@ void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd)
|
||||
for (int y = 0; y < _yRes; y++)
|
||||
for (int x = 0; x < _xRes; x++, index++)
|
||||
{
|
||||
_zForce[index] += *_alpha * density[index] + (*_beta * (heat[index] - _tempAmb)); // DG: was _yForce, changed for Blender
|
||||
float buoyancy = *_alpha * density[index] + (*_beta * (((heat) ? heat[index] : 0.0f) - _tempAmb));
|
||||
_xForce[index] -= gravity[0] * buoyancy;
|
||||
_yForce[index] -= gravity[1] * buoyancy;
|
||||
_zForce[index] -= gravity[2] * buoyancy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1192,8 +1331,10 @@ void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void FLUID_3D::addVorticity(int zBegin, int zEnd)
|
||||
{
|
||||
// set flame vorticity from RNA value
|
||||
float flame_vorticity = (*_flame_vorticity)/_constantScaling;
|
||||
//int x,y,z,index;
|
||||
if(_vorticityEps<=0.) return;
|
||||
if(_vorticityEps+flame_vorticity<=0.) return;
|
||||
|
||||
int _blockSize=zEnd-zBegin;
|
||||
int _blockTotalCells = _slabSize * (_blockSize+2);
|
||||
@@ -1300,14 +1441,15 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd)
|
||||
float magnitude = sqrtf(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]);
|
||||
if (magnitude > FLT_EPSILON)
|
||||
{
|
||||
float flame_vort = (_fuel) ? _fuel[index]*flame_vorticity : 0.0f;
|
||||
magnitude = 1.0f / magnitude;
|
||||
N[0] *= magnitude;
|
||||
N[1] *= magnitude;
|
||||
N[2] *= magnitude;
|
||||
|
||||
_xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * eps;
|
||||
_yForce[index] += (N[2] * _xVorticity[vIndex] - N[0] * _zVorticity[vIndex]) * _dx * eps;
|
||||
_zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * eps;
|
||||
_xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * (eps + flame_vort);
|
||||
_yForce[index] += (N[2] * _xVorticity[vIndex] - N[0] * _zVorticity[vIndex]) * _dx * (eps + flame_vort);
|
||||
_zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * (eps + flame_vort);
|
||||
}
|
||||
} // if
|
||||
vIndex++;
|
||||
@@ -1328,14 +1470,9 @@ void FLUID_3D::advectMacCormackBegin(int zBegin, int zEnd)
|
||||
{
|
||||
Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
|
||||
|
||||
if(!_domainBcLeft) copyBorderX(_xVelocityOld, res, zBegin, zEnd);
|
||||
else setZeroX(_xVelocityOld, res, zBegin, zEnd);
|
||||
|
||||
if(!_domainBcFront) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
|
||||
else setZeroY(_yVelocityOld, res, zBegin, zEnd);
|
||||
|
||||
if(!_domainBcTop) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
|
||||
else setZeroZ(_zVelocityOld, res, zBegin, zEnd);
|
||||
setZeroX(_xVelocityOld, res, zBegin, zEnd);
|
||||
setZeroY(_yVelocityOld, res, zBegin, zEnd);
|
||||
setZeroZ(_zVelocityOld, res, zBegin, zEnd);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -1355,7 +1492,18 @@ void FLUID_3D::advectMacCormackEnd1(int zBegin, int zEnd)
|
||||
// advectFieldMacCormack1(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res)
|
||||
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _densityTemp, res, zBegin, zEnd);
|
||||
if (_heat) {
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd);
|
||||
}
|
||||
if (_fuel) {
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _fuelOld, _fuelTemp, res, zBegin, zEnd);
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _reactOld, _reactTemp, res, zBegin, zEnd);
|
||||
}
|
||||
if (_color_r) {
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_rOld, _color_rTemp, res, zBegin, zEnd);
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_gOld, _color_gTemp, res, zBegin, zEnd);
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_bOld, _color_bTemp, res, zBegin, zEnd);
|
||||
}
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, res, zBegin, zEnd);
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, res, zBegin, zEnd);
|
||||
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, res, zBegin, zEnd);
|
||||
@@ -1371,17 +1519,30 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
|
||||
const float dt0 = _dt / _dx;
|
||||
Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
|
||||
|
||||
// use force array as temp arrays
|
||||
// use force array as temp array
|
||||
float* t1 = _xForce;
|
||||
|
||||
// advectFieldMacCormack2(dt, xVelocity, yVelocity, zVelocity, oldField, newField, tempfield, temp, res, obstacles)
|
||||
|
||||
/* finish advection */
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, _densityTemp, t1, res, _obstacles, zBegin, zEnd);
|
||||
if (_heat) {
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd);
|
||||
}
|
||||
if (_fuel) {
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _fuelOld, _fuel, _fuelTemp, t1, res, _obstacles, zBegin, zEnd);
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _reactOld, _react, _reactTemp, t1, res, _obstacles, zBegin, zEnd);
|
||||
}
|
||||
if (_color_r) {
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_rOld, _color_r, _color_rTemp, t1, res, _obstacles, zBegin, zEnd);
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_gOld, _color_g, _color_gTemp, t1, res, _obstacles, zBegin, zEnd);
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_bOld, _color_b, _color_bTemp, t1, res, _obstacles, zBegin, zEnd);
|
||||
}
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocityTemp, _xVelocity, t1, res, _obstacles, zBegin, zEnd);
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd);
|
||||
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd);
|
||||
|
||||
/* set boundary conditions for velocity */
|
||||
if(!_domainBcLeft) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
|
||||
else setZeroX(_xVelocityTemp, res, zBegin, zEnd);
|
||||
|
||||
@@ -1391,40 +1552,71 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
|
||||
if(!_domainBcTop) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
|
||||
else setZeroZ(_zVelocityTemp, res, zBegin, zEnd);
|
||||
|
||||
/* clear data boundaries */
|
||||
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 (_fuel) {
|
||||
setZeroBorder(_fuel, res, zBegin, zEnd);
|
||||
setZeroBorder(_react, res, zBegin, zEnd);
|
||||
}
|
||||
if (_color_r) {
|
||||
setZeroBorder(_color_r, res, zBegin, zEnd);
|
||||
setZeroBorder(_color_g, res, zBegin, zEnd);
|
||||
setZeroBorder(_color_b, res, zBegin, zEnd);
|
||||
}
|
||||
}
|
||||
|
||||
if (zBegin == 0) {bb = 1;}
|
||||
if (zEnd == _zRes) {bt = 1;}
|
||||
|
||||
for (int z = zBegin + bb; z < zEnd - bt; z++)
|
||||
void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat,
|
||||
float *r, float *g, float *b, int total_cells, float dt)
|
||||
{
|
||||
size_t index = index_ +(z-1)*_slabSize;
|
||||
float burning_rate = *_burning_rate;
|
||||
float flame_smoke = *_flame_smoke;
|
||||
float ignition_point = *_ignition_temp;
|
||||
float temp_max = *_max_temp;
|
||||
|
||||
for (int y = 1; y < _yRes - 1; y++, index += 2)
|
||||
for (int index = 0; index < total_cells; index++)
|
||||
{
|
||||
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
|
||||
float orig_fuel = fuel[index];
|
||||
float orig_smoke = smoke[index];
|
||||
float smoke_emit = 0.0f;
|
||||
float react_coord = 0.0f;
|
||||
|
||||
/*int begin=zBegin * _slabSize;
|
||||
int end=begin + (zEnd - zBegin) * _slabSize;
|
||||
for (int x = begin; x < end; x++)
|
||||
_xForce[x] = _yForce[x] = 0.0f;*/
|
||||
/* process fuel */
|
||||
fuel[index] -= burning_rate * dt;
|
||||
if (fuel[index] < 0.0f) fuel[index] = 0.0f;
|
||||
/* process reaction coordinate */
|
||||
if (orig_fuel) {
|
||||
react[index] *= fuel[index]/orig_fuel;
|
||||
react_coord = react[index];
|
||||
}
|
||||
else {
|
||||
react[index] = 0.0f;
|
||||
}
|
||||
|
||||
/* emit smoke based on fuel burn rate and "flame_smoke" factor */
|
||||
smoke_emit = (orig_fuel < 1.0f) ? (1.0f - orig_fuel)*0.5f : 0.0f;
|
||||
smoke_emit = (smoke_emit + 0.5f) * (orig_fuel-fuel[index]) * 0.1f * flame_smoke;
|
||||
smoke[index] += smoke_emit;
|
||||
CLAMP(smoke[index], 0.0f, 1.0f);
|
||||
|
||||
/* model flame temperature curve from the reaction coordinate (fuel) */
|
||||
if (react_coord>0.0f) {
|
||||
/* do a smooth falloff for rest of the values */
|
||||
flame[index] = pow(react_coord, 0.5f);
|
||||
}
|
||||
else
|
||||
flame[index] = 0.0f;
|
||||
|
||||
/* set fluid temperature from the flame temperature profile */
|
||||
if (heat && flame[index])
|
||||
heat[index] = (1.0f-flame[index])*ignition_point + flame[index]*temp_max;
|
||||
|
||||
/* mix new color */
|
||||
if (r && smoke_emit) {
|
||||
float smoke_factor = smoke[index]/(orig_smoke+smoke_emit);
|
||||
r[index] = (r[index] + _flame_smoke_color[0] * smoke_emit) * smoke_factor;
|
||||
g[index] = (g[index] + _flame_smoke_color[1] * smoke_emit) * smoke_factor;
|
||||
b[index] = (b[index] + _flame_smoke_color[2] * smoke_emit) * smoke_factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,16 @@ class WTURBULENCE;
|
||||
class FLUID_3D
|
||||
{
|
||||
public:
|
||||
FLUID_3D(int *res, /* int amplify, */ float *p0, float dtdef);
|
||||
FLUID_3D(int *res, float dx, float dtdef, int init_heat, int init_fire, int init_colors);
|
||||
FLUID_3D() {};
|
||||
virtual ~FLUID_3D();
|
||||
|
||||
void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli);
|
||||
void initHeat();
|
||||
void initFire();
|
||||
void initColors(float init_r, float init_g, float init_b);
|
||||
|
||||
void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate,
|
||||
float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *ignition_temp, float *max_temp);
|
||||
|
||||
// create & allocate vector noise advection
|
||||
void initVectorNoise(int amplify);
|
||||
@@ -58,7 +63,7 @@ class FLUID_3D
|
||||
void addSmokeColumn();
|
||||
static void addSmokeTestCase(float* field, Vec3Int res);
|
||||
|
||||
void step(float dt);
|
||||
void step(float dt, float gravity[3]);
|
||||
void addObstacle(OBSTACLE* obstacle);
|
||||
|
||||
const float* xVelocity() { return _xVelocity; };
|
||||
@@ -115,6 +120,27 @@ class FLUID_3D
|
||||
float* _heatTemp;
|
||||
float* _densityTemp;
|
||||
|
||||
// fire simulation
|
||||
float *_flame;
|
||||
float *_fuel;
|
||||
float *_fuelTemp;
|
||||
float *_fuelOld;
|
||||
float *_react;
|
||||
float *_reactTemp;
|
||||
float *_reactOld;
|
||||
|
||||
// smoke color
|
||||
float *_color_r;
|
||||
float *_color_rOld;
|
||||
float *_color_rTemp;
|
||||
float *_color_g;
|
||||
float *_color_gOld;
|
||||
float *_color_gTemp;
|
||||
float *_color_b;
|
||||
float *_color_bOld;
|
||||
float *_color_bTemp;
|
||||
|
||||
|
||||
// CG fields
|
||||
int _iterations;
|
||||
|
||||
@@ -153,14 +179,16 @@ class FLUID_3D
|
||||
void wipeBoundariesSL(int zBegin, int zEnd);
|
||||
void addForce(int zBegin, int zEnd);
|
||||
void addVorticity(int zBegin, int zEnd);
|
||||
void addBuoyancy(float *heat, float *density, int zBegin, int zEnd);
|
||||
void addBuoyancy(float *heat, float *density, float gravity[3], int zBegin, int zEnd);
|
||||
|
||||
// solver stuff
|
||||
void project();
|
||||
void diffuseHeat();
|
||||
void diffuseColor();
|
||||
void solvePressure(float* field, float* b, unsigned char* skip);
|
||||
void solvePressurePre(float* field, float* b, unsigned char* skip);
|
||||
void solveHeat(float* field, float* b, unsigned char* skip);
|
||||
void solveDiffusion(float* field, float* b, float* factor);
|
||||
|
||||
|
||||
// handle obstacle boundaries
|
||||
@@ -174,6 +202,16 @@ class FLUID_3D
|
||||
void advectMacCormackEnd1(int zBegin, int zEnd);
|
||||
void advectMacCormackEnd2(int zBegin, int zEnd);
|
||||
|
||||
/* burning */
|
||||
float *_burning_rate; // RNA pointer
|
||||
float *_flame_smoke; // RNA pointer
|
||||
float *_flame_smoke_color; // RNA pointer
|
||||
float *_flame_vorticity; // RNA pointer
|
||||
float *_ignition_temp; // RNA pointer
|
||||
float *_max_temp; // RNA pointer
|
||||
void processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat,
|
||||
float *r, float *g, float *b, int total_cells, float dt);
|
||||
|
||||
// boundary setting functions
|
||||
static void copyBorderX(float* field, Vec3Int res, int zBegin, int zEnd);
|
||||
static void copyBorderY(float* field, Vec3Int res, int zBegin, int zEnd);
|
||||
|
||||
@@ -165,7 +165,6 @@ void FLUID_3D::solveHeat(float* field, float* b, unsigned char* skip)
|
||||
if (_Acenter) delete[] _Acenter;
|
||||
}
|
||||
|
||||
|
||||
void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
@@ -92,18 +92,10 @@ void FLUID_3D::setNeumannX(float* field, Vec3Int res, int zBegin, int zEnd)
|
||||
// left slab
|
||||
index = y * res[0] + z * slabSize;
|
||||
field[index] = field[index + 2];
|
||||
/* only allow outwards flux */
|
||||
if(field[index]>0.) field[index] = 0.;
|
||||
index += 1;
|
||||
if(field[index]>0.) field[index] = 0.;
|
||||
|
||||
// right slab
|
||||
index = y * res[0] + z * slabSize + res[0] - 1;
|
||||
field[index] = field[index - 2];
|
||||
/* only allow outwards flux */
|
||||
if(field[index]<0.) field[index] = 0.;
|
||||
index -= 1;
|
||||
if(field[index]<0.) field[index] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,18 +112,10 @@ void FLUID_3D::setNeumannY(float* field, Vec3Int res, int zBegin, int zEnd)
|
||||
// front slab
|
||||
index = x + z * slabSize;
|
||||
field[index] = field[index + 2 * res[0]];
|
||||
/* only allow outwards flux */
|
||||
if(field[index]>0.) field[index] = 0.;
|
||||
index += res[0];
|
||||
if(field[index]>0.) field[index] = 0.;
|
||||
|
||||
// back slab
|
||||
index = x + z * slabSize + slabSize - res[0];
|
||||
field[index] = field[index - 2 * res[0]];
|
||||
/* only allow outwards flux */
|
||||
if(field[index]<0.) field[index] = 0.;
|
||||
index -= res[0];
|
||||
if(field[index]<0.) field[index] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,14 +136,6 @@ void FLUID_3D::setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd)
|
||||
// front slab
|
||||
index = x + y * res[0];
|
||||
field[index] = field[index + 2 * slabSize];
|
||||
/* only allow outwards flux */
|
||||
|
||||
// DG: Disable this for z-axis.
|
||||
// The problem is that smoke somehow gets sucked in again
|
||||
// from the TOP slab when this is enabled
|
||||
// if(field[index]>0.) field[index] = 0.;
|
||||
// index += slabSize;
|
||||
// if(field[index]>0.) field[index] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,10 +146,6 @@ void FLUID_3D::setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd)
|
||||
// back slab
|
||||
index = x + y * res[0] + cellsslab;
|
||||
field[index] = field[index - 2 * slabSize];
|
||||
/* only allow outwards flux */
|
||||
if(field[index]<0.) field[index] = 0.;
|
||||
index -= slabSize;
|
||||
if(field[index]<0.) field[index] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ static const float persistence = 0.56123f;
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// constructor
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype)
|
||||
WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors)
|
||||
{
|
||||
// if noise magnitude is below this threshold, its contribution
|
||||
// is negilgible, so stop evaluating new octaves
|
||||
@@ -94,6 +94,20 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no
|
||||
_densityBigOld[i] = 0.;
|
||||
}
|
||||
|
||||
/* fire */
|
||||
_flameBig = _fuelBig = _fuelBigOld = NULL;
|
||||
_reactBig = _reactBigOld = NULL;
|
||||
if (init_fire) {
|
||||
initFire();
|
||||
}
|
||||
/* colors */
|
||||
_color_rBig = _color_rBigOld = NULL;
|
||||
_color_gBig = _color_gBigOld = NULL;
|
||||
_color_bBig = _color_bBigOld = NULL;
|
||||
if (init_colors) {
|
||||
initColors(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
// allocate & init texture coordinates
|
||||
_tcU = new float[_totalCellsSm];
|
||||
_tcV = new float[_totalCellsSm];
|
||||
@@ -128,12 +142,64 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no
|
||||
*/
|
||||
}
|
||||
|
||||
void WTURBULENCE::initFire()
|
||||
{
|
||||
if (!_fuelBig) {
|
||||
_flameBig = new float[_totalCellsBig];
|
||||
_fuelBig = new float[_totalCellsBig];
|
||||
_fuelBigOld = new float[_totalCellsBig];
|
||||
_reactBig = new float[_totalCellsBig];
|
||||
_reactBigOld = new float[_totalCellsBig];
|
||||
|
||||
for(int i = 0; i < _totalCellsBig; i++) {
|
||||
_flameBig[i] =
|
||||
_fuelBig[i] =
|
||||
_fuelBigOld[i] = 0.;
|
||||
_reactBig[i] =
|
||||
_reactBigOld[i] = 0.;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WTURBULENCE::initColors(float init_r, float init_g, float init_b)
|
||||
{
|
||||
if (!_color_rBig) {
|
||||
_color_rBig = new float[_totalCellsBig];
|
||||
_color_rBigOld = new float[_totalCellsBig];
|
||||
_color_gBig = new float[_totalCellsBig];
|
||||
_color_gBigOld = new float[_totalCellsBig];
|
||||
_color_bBig = new float[_totalCellsBig];
|
||||
_color_bBigOld = new float[_totalCellsBig];
|
||||
|
||||
for(int i = 0; i < _totalCellsBig; i++) {
|
||||
_color_rBig[i] = _densityBig[i] * init_r;
|
||||
_color_rBigOld[i] = 0.0f;
|
||||
_color_gBig[i] = _densityBig[i] * init_g;
|
||||
_color_gBigOld[i] = 0.0f;
|
||||
_color_bBig[i] = _densityBig[i] * init_b;
|
||||
_color_bBigOld[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// destructor
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
WTURBULENCE::~WTURBULENCE() {
|
||||
delete[] _densityBig;
|
||||
delete[] _densityBigOld;
|
||||
if (_flameBig) delete[] _flameBig;
|
||||
if (_fuelBig) delete[] _fuelBig;
|
||||
if (_fuelBigOld) delete[] _fuelBigOld;
|
||||
if (_reactBig) delete[] _reactBig;
|
||||
if (_reactBigOld) delete[] _reactBigOld;
|
||||
|
||||
if (_color_rBig) delete[] _color_rBig;
|
||||
if (_color_rBigOld) delete[] _color_rBigOld;
|
||||
if (_color_gBig) delete[] _color_gBig;
|
||||
if (_color_gBigOld) delete[] _color_gBigOld;
|
||||
if (_color_bBig) delete[] _color_bBig;
|
||||
if (_color_bBigOld) delete[] _color_bBigOld;
|
||||
|
||||
delete[] _tcU;
|
||||
delete[] _tcV;
|
||||
@@ -757,8 +823,10 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
|
||||
// enlarge timestep to match grid
|
||||
const float dt = dtOrg * _amplify;
|
||||
const float invAmp = 1.0f / _amplify;
|
||||
float *tempBig1 = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
float *tempBig2 = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
float *tempFuelBig = NULL, *tempReactBig = NULL;
|
||||
float *tempColor_rBig = NULL, *tempColor_gBig = NULL, *tempColor_bBig = NULL;
|
||||
float *tempDensityBig = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
float *tempBig = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
float *bigUx = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
float *bigUy = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
float *bigUz = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
@@ -767,11 +835,21 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
|
||||
float *eigMin = (float *)calloc(_totalCellsSm, sizeof(float));
|
||||
float *eigMax = (float *)calloc(_totalCellsSm, sizeof(float));
|
||||
|
||||
if (_fuelBig) {
|
||||
tempFuelBig = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
tempReactBig = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
}
|
||||
if (_color_rBig) {
|
||||
tempColor_rBig = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
tempColor_gBig = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
tempColor_bBig = (float *)calloc(_totalCellsBig, sizeof(float));
|
||||
}
|
||||
|
||||
memset(_tcTemp, 0, sizeof(float)*_totalCellsSm);
|
||||
|
||||
|
||||
// prepare textures
|
||||
advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempBig1, tempBig2);
|
||||
advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempDensityBig, tempBig);
|
||||
|
||||
// do wavelet decomposition of energy
|
||||
computeEnergy(_energy, xvel, yvel, zvel, obstacles);
|
||||
@@ -972,6 +1050,11 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
|
||||
|
||||
// prepare density for an advection
|
||||
SWAP_POINTERS(_densityBig, _densityBigOld);
|
||||
SWAP_POINTERS(_fuelBig, _fuelBigOld);
|
||||
SWAP_POINTERS(_reactBig, _reactBigOld);
|
||||
SWAP_POINTERS(_color_rBig, _color_rBigOld);
|
||||
SWAP_POINTERS(_color_gBig, _color_gBigOld);
|
||||
SWAP_POINTERS(_color_bBig, _color_bBigOld);
|
||||
|
||||
// based on the maximum velocity present, see if we need to substep,
|
||||
// but cap the maximum number of substeps to 5
|
||||
@@ -1017,7 +1100,21 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
|
||||
int zEnd = (int)((float)(i+1)*partSize + 0.5f);
|
||||
#endif
|
||||
FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_densityBigOld, tempBig1, _resBig, zBegin, zEnd);
|
||||
_densityBigOld, tempDensityBig, _resBig, zBegin, zEnd);
|
||||
if (_fuelBig) {
|
||||
FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_fuelBigOld, tempFuelBig, _resBig, zBegin, zEnd);
|
||||
FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_reactBigOld, tempReactBig, _resBig, zBegin, zEnd);
|
||||
}
|
||||
if (_color_rBig) {
|
||||
FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_color_rBigOld, tempColor_rBig, _resBig, zBegin, zEnd);
|
||||
FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_color_gBigOld, tempColor_gBig, _resBig, zBegin, zEnd);
|
||||
FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_color_bBigOld, tempColor_bBig, _resBig, zBegin, zEnd);
|
||||
}
|
||||
#if PARALLEL==1
|
||||
}
|
||||
|
||||
@@ -1030,18 +1127,43 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
|
||||
int zEnd = (int)((float)(i+1)*partSize + 0.5f);
|
||||
#endif
|
||||
FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_densityBigOld, _densityBig, tempBig1, tempBig2, _resBig, NULL, zBegin, zEnd);
|
||||
_densityBigOld, _densityBig, tempDensityBig, tempBig, _resBig, NULL, zBegin, zEnd);
|
||||
if (_fuelBig) {
|
||||
FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_fuelBigOld, _fuelBig, tempFuelBig, tempBig, _resBig, NULL, zBegin, zEnd);
|
||||
FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_reactBigOld, _reactBig, tempReactBig, tempBig, _resBig, NULL, zBegin, zEnd);
|
||||
}
|
||||
if (_color_rBig) {
|
||||
FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_color_rBigOld, _color_rBig, tempColor_rBig, tempBig, _resBig, NULL, zBegin, zEnd);
|
||||
FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_color_gBigOld, _color_gBig, tempColor_gBig, tempBig, _resBig, NULL, zBegin, zEnd);
|
||||
FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz,
|
||||
_color_bBigOld, _color_bBig, tempColor_bBig, tempBig, _resBig, NULL, zBegin, zEnd);
|
||||
}
|
||||
#if PARALLEL==1
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (substep < totalSubsteps - 1)
|
||||
if (substep < totalSubsteps - 1) {
|
||||
SWAP_POINTERS(_densityBig, _densityBigOld);
|
||||
SWAP_POINTERS(_fuelBig, _fuelBigOld);
|
||||
SWAP_POINTERS(_reactBig, _reactBigOld);
|
||||
SWAP_POINTERS(_color_rBig, _color_rBigOld);
|
||||
SWAP_POINTERS(_color_gBig, _color_gBigOld);
|
||||
SWAP_POINTERS(_color_bBig, _color_bBigOld);
|
||||
}
|
||||
} // substep
|
||||
|
||||
free(tempBig1);
|
||||
free(tempBig2);
|
||||
free(tempDensityBig);
|
||||
if (tempFuelBig) free(tempFuelBig);
|
||||
if (tempReactBig) free(tempReactBig);
|
||||
if (tempColor_rBig) free(tempColor_rBig);
|
||||
if (tempColor_gBig) free(tempColor_gBig);
|
||||
if (tempColor_bBig) free(tempColor_bBig);
|
||||
free(tempBig);
|
||||
free(bigUx);
|
||||
free(bigUy);
|
||||
free(bigUz);
|
||||
@@ -1050,6 +1172,15 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa
|
||||
|
||||
// wipe the density borders
|
||||
FLUID_3D::setZeroBorder(_densityBig, _resBig, 0 , _resBig[2]);
|
||||
if (_fuelBig) {
|
||||
FLUID_3D::setZeroBorder(_fuelBig, _resBig, 0 , _resBig[2]);
|
||||
FLUID_3D::setZeroBorder(_reactBig, _resBig, 0 , _resBig[2]);
|
||||
}
|
||||
if (_color_rBig) {
|
||||
FLUID_3D::setZeroBorder(_color_rBig, _resBig, 0 , _resBig[2]);
|
||||
FLUID_3D::setZeroBorder(_color_gBig, _resBig, 0 , _resBig[2]);
|
||||
FLUID_3D::setZeroBorder(_color_bBig, _resBig, 0 , _resBig[2]);
|
||||
}
|
||||
|
||||
// reset texture coordinates now in preparation for next timestep
|
||||
// Shouldn't do this before generating the noise because then the
|
||||
|
||||
@@ -36,11 +36,14 @@ class WTURBULENCE
|
||||
{
|
||||
public:
|
||||
// both config files can be NULL, altCfg might override values from noiseCfg
|
||||
WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype);
|
||||
WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors);
|
||||
|
||||
/// destructor
|
||||
virtual ~WTURBULENCE();
|
||||
|
||||
void initFire();
|
||||
void initColors(float init_r, float init_g, float init_b);
|
||||
|
||||
void setNoise(int type);
|
||||
void initBlenderRNA(float *strength);
|
||||
|
||||
@@ -63,6 +66,8 @@ class WTURBULENCE
|
||||
|
||||
// access functions
|
||||
inline float* getDensityBig() { return _densityBig; }
|
||||
inline float* getFlameBig() { return _flameBig; }
|
||||
inline float* getFuelBig() { return _fuelBig; }
|
||||
inline float* getArrayTcU() { return _tcU; }
|
||||
inline float* getArrayTcV() { return _tcV; }
|
||||
inline float* getArrayTcW() { return _tcW; }
|
||||
@@ -111,6 +116,18 @@ class WTURBULENCE
|
||||
|
||||
float* _densityBig;
|
||||
float* _densityBigOld;
|
||||
float* _flameBig;
|
||||
float* _fuelBig;
|
||||
float* _fuelBigOld;
|
||||
float* _reactBig;
|
||||
float* _reactBigOld;
|
||||
|
||||
float* _color_rBig;
|
||||
float* _color_rBigOld;
|
||||
float* _color_gBig;
|
||||
float* _color_gBigOld;
|
||||
float* _color_bBig;
|
||||
float* _color_bBigOld;
|
||||
|
||||
// texture coordinates for noise
|
||||
float* _tcU;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "FLUID_3D.h"
|
||||
#include "WTURBULENCE.h"
|
||||
#include "spectrum.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -37,22 +38,16 @@
|
||||
|
||||
#include "../extern/smoke_API.h" /* to ensure valid prototypes */
|
||||
|
||||
// y in smoke is z in blender
|
||||
extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef)
|
||||
extern "C" FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, int use_fire, int use_colors)
|
||||
{
|
||||
// smoke lib uses y as top-bottom/vertical axis where blender uses z
|
||||
FLUID_3D *fluid = new FLUID_3D(res, p0, dtdef);
|
||||
|
||||
// printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
|
||||
|
||||
FLUID_3D *fluid = new FLUID_3D(res, dx, dtdef, use_heat, use_fire, use_colors);
|
||||
return fluid;
|
||||
}
|
||||
|
||||
extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype)
|
||||
extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, int use_fire, int use_colors)
|
||||
{
|
||||
// initialize wavelet turbulence
|
||||
if(amplify)
|
||||
return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype);
|
||||
return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype, use_fire, use_colors);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@@ -71,7 +66,6 @@ extern "C" void smoke_turbulence_free(WTURBULENCE *wt)
|
||||
|
||||
extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
|
||||
{
|
||||
// // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1];
|
||||
return x + y * max_x + z * max_x*max_y;
|
||||
}
|
||||
|
||||
@@ -80,100 +74,28 @@ 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, float dtSubdiv)
|
||||
extern "C" void smoke_step(FLUID_3D *fluid, float gravity[3], float dtSubdiv)
|
||||
{
|
||||
fluid->step(dtSubdiv);
|
||||
if (fluid->_fuel) {
|
||||
fluid->processBurn(fluid->_fuel, fluid->_density, fluid->_react, fluid->_flame, fluid->_heat,
|
||||
fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, (*fluid->_dtFactor)*dtSubdiv);
|
||||
}
|
||||
fluid->step(dtSubdiv, gravity);
|
||||
}
|
||||
|
||||
extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
|
||||
{
|
||||
if (wt->_fuelBig) {
|
||||
fluid->processBurn(wt->_fuelBig, wt->_densityBig, wt->_reactBig, wt->_flameBig, 0,
|
||||
wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, fluid->_dt);
|
||||
}
|
||||
wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles);
|
||||
}
|
||||
|
||||
extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli)
|
||||
extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate,
|
||||
float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp)
|
||||
{
|
||||
fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli);
|
||||
}
|
||||
|
||||
extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
|
||||
{
|
||||
float *density = fluid->_density;
|
||||
//float *densityOld = fluid->_densityOld;
|
||||
float *heat = fluid->_heat;
|
||||
|
||||
if(log)
|
||||
{
|
||||
/* max density/speed = dydx */
|
||||
float dydx = 1.0 / (float)speed;
|
||||
size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
|
||||
|
||||
for(size_t i = 0; i < size; i++)
|
||||
{
|
||||
density[i] *= (1.0 - dydx);
|
||||
|
||||
if(density[i] < 0.0f)
|
||||
density[i] = 0.0f;
|
||||
|
||||
heat[i] *= (1.0 - dydx);
|
||||
|
||||
/*if(heat[i] < 0.0f)
|
||||
heat[i] = 0.0f;*/
|
||||
}
|
||||
}
|
||||
else // linear falloff
|
||||
{
|
||||
/* max density/speed = dydx */
|
||||
float dydx = 1.0 / (float)speed;
|
||||
size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
|
||||
|
||||
for(size_t i = 0; i < size; i++)
|
||||
{
|
||||
density[i] -= dydx;
|
||||
|
||||
if(density[i] < 0.0f)
|
||||
density[i] = 0.0f;
|
||||
|
||||
if(abs(heat[i]) < dydx) heat[i] = 0.0f;
|
||||
else if (heat[i]>0.0f) heat[i] -= dydx;
|
||||
else if (heat[i]<0.0f) heat[i] += dydx;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log)
|
||||
{
|
||||
float *density = wt->getDensityBig();
|
||||
Vec3Int r = wt->getResBig();
|
||||
|
||||
if(log)
|
||||
{
|
||||
/* max density/speed = dydx */
|
||||
float dydx = 1.0 / (float)speed;
|
||||
size_t size= r[0] * r[1] * r[2];
|
||||
|
||||
for(size_t i = 0; i < size; i++)
|
||||
{
|
||||
density[i] *= (1.0 - dydx);
|
||||
|
||||
if(density[i] < 0.0f)
|
||||
density[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
else // linear falloff
|
||||
{
|
||||
/* max density/speed = dydx */
|
||||
float dydx = 1.0 / (float)speed;
|
||||
size_t size= r[0] * r[1] * r[2];
|
||||
|
||||
for(size_t i = 0; i < size; i++)
|
||||
{
|
||||
density[i] -= dydx;
|
||||
|
||||
if(density[i] < 0.0f)
|
||||
density[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli, burning_rate, flame_smoke, flame_smoke_color, flame_vorticity, flame_ignition_temp, flame_max_temp);
|
||||
}
|
||||
|
||||
extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength)
|
||||
@@ -181,36 +103,105 @@ extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength)
|
||||
wt->initBlenderRNA(strength);
|
||||
}
|
||||
|
||||
template < class T > inline T ABS( T a )
|
||||
static void data_dissolve(float *density, float *heat, float *r, float *g, float *b, int total_cells, int speed, int log)
|
||||
{
|
||||
return (0 < a) ? a : -a ;
|
||||
if(log)
|
||||
{
|
||||
/* max density/speed = dydx */
|
||||
float fac = 1.0f - (1.0f / (float)speed);
|
||||
|
||||
for(size_t i = 0; i < total_cells; i++)
|
||||
{
|
||||
/* density */
|
||||
density[i] *= fac;
|
||||
|
||||
/* heat */
|
||||
if (heat) {
|
||||
heat[i] *= fac;
|
||||
}
|
||||
|
||||
extern "C" void smoke_export(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)
|
||||
/* color */
|
||||
if (r) {
|
||||
r[i] *= fac;
|
||||
g[i] *= fac;
|
||||
b[i] *= fac;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // linear falloff
|
||||
{
|
||||
/* max density/speed = dydx */
|
||||
float dydx = 1.0f / (float)speed;
|
||||
|
||||
for(size_t i = 0; i < total_cells; i++)
|
||||
{
|
||||
float d = density[i];
|
||||
/* density */
|
||||
density[i] -= dydx;
|
||||
if(density[i] < 0.0f)
|
||||
density[i] = 0.0f;
|
||||
|
||||
/* heat */
|
||||
if (heat) {
|
||||
if(abs(heat[i]) < dydx) heat[i] = 0.0f;
|
||||
else if (heat[i]>0.0f) heat[i] -= dydx;
|
||||
else if (heat[i]<0.0f) heat[i] += dydx;
|
||||
}
|
||||
|
||||
/* color */
|
||||
if (r && d) {
|
||||
r[i] *= (density[i]/d);
|
||||
g[i] *= (density[i]/d);
|
||||
b[i] *= (density[i]/d);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
|
||||
{
|
||||
data_dissolve(fluid->_density, fluid->_heat, fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, speed, log);
|
||||
}
|
||||
|
||||
extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log)
|
||||
{
|
||||
data_dissolve(wt->_densityBig, 0, wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, speed, log);
|
||||
}
|
||||
|
||||
extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens, float **react, float **flame, float **fuel, float **heat,
|
||||
float **heatold, float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles)
|
||||
{
|
||||
*dens = fluid->_density;
|
||||
*densold = fluid->_densityOld;
|
||||
*fuel = fluid->_fuel;
|
||||
*react = fluid->_react;
|
||||
*flame = fluid->_flame;
|
||||
*heat = fluid->_heat;
|
||||
*heatold = fluid->_heatOld;
|
||||
*vx = fluid->_xVelocity;
|
||||
*vy = fluid->_yVelocity;
|
||||
*vz = fluid->_zVelocity;
|
||||
*vxold = fluid->_xVelocityOld;
|
||||
*vyold = fluid->_yVelocityOld;
|
||||
*vzold = fluid->_zVelocityOld;
|
||||
*r = fluid->_color_r;
|
||||
*g = fluid->_color_g;
|
||||
*b = fluid->_color_b;
|
||||
*obstacles = fluid->_obstacles;
|
||||
*dt = fluid->_dt;
|
||||
*dx = fluid->_dx;
|
||||
|
||||
}
|
||||
|
||||
extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw)
|
||||
extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **react, float **flame, float **fuel,
|
||||
float **r, float **g, float **b , float **tcu, float **tcv, float **tcw)
|
||||
{
|
||||
if(!wt)
|
||||
return;
|
||||
|
||||
*dens = wt->_densityBig;
|
||||
*densold = wt->_densityBigOld;
|
||||
*fuel = wt->_fuelBig;
|
||||
*react = wt->_reactBig;
|
||||
*flame = wt->_flameBig;
|
||||
*r = wt->_color_rBig;
|
||||
*g = wt->_color_gBig;
|
||||
*b = wt->_color_bBig;
|
||||
*tcu = wt->_tcU;
|
||||
*tcv = wt->_tcV;
|
||||
*tcw = wt->_tcW;
|
||||
@@ -221,6 +212,16 @@ extern "C" float *smoke_get_density(FLUID_3D *fluid)
|
||||
return fluid->_density;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_get_fuel(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_fuel;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_get_react(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_react;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_get_heat(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_heat;
|
||||
@@ -256,15 +257,137 @@ extern "C" float *smoke_get_force_z(FLUID_3D *fluid)
|
||||
return fluid->_zForce;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_get_flame(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_flame;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_get_color_r(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_color_r;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_get_color_g(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_color_g;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_get_color_b(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_color_b;
|
||||
}
|
||||
|
||||
static void get_rgba(float *r, float *g, float *b, float *a, int total_cells, float *data, int sequential)
|
||||
{
|
||||
int i;
|
||||
int m = 4, i_g = 1, i_b = 2, i_a = 3;
|
||||
/* sequential data */
|
||||
if (sequential) {
|
||||
m = 1;
|
||||
i_g *= total_cells;
|
||||
i_b *= total_cells;
|
||||
i_a *= total_cells;
|
||||
}
|
||||
|
||||
for (i=0; i<total_cells; i++) {
|
||||
float alpha = a[i];
|
||||
if (alpha) {
|
||||
data[i*m ] = r[i];
|
||||
data[i*m+i_g] = g[i];
|
||||
data[i*m+i_b] = b[i];
|
||||
}
|
||||
else {
|
||||
data[i*m ] = data[i*m+i_g] = data[i*m+i_b] = 0.0f;
|
||||
}
|
||||
data[i*m+i_a] = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void smoke_get_rgba(FLUID_3D *fluid, float *data, int sequential)
|
||||
{
|
||||
get_rgba(fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_density, fluid->_totalCells, data, sequential);
|
||||
}
|
||||
|
||||
extern "C" void smoke_turbulence_get_rgba(WTURBULENCE *wt, float *data, int sequential)
|
||||
{
|
||||
get_rgba(wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_densityBig, wt->_totalCellsBig, data, sequential);
|
||||
}
|
||||
|
||||
/* get a single color premultiplied voxel grid */
|
||||
static void get_rgba_from_density(float color[3], float *a, int total_cells, float *data, int sequential)
|
||||
{
|
||||
int i;
|
||||
int m = 4, i_g = 1, i_b = 2, i_a = 3;
|
||||
/* sequential data */
|
||||
if (sequential) {
|
||||
m = 1;
|
||||
i_g *= total_cells;
|
||||
i_b *= total_cells;
|
||||
i_a *= total_cells;
|
||||
}
|
||||
|
||||
for (i=0; i<total_cells; i++) {
|
||||
float alpha = a[i];
|
||||
if (alpha) {
|
||||
data[i*m ] = color[0] * alpha;
|
||||
data[i*m+i_g] = color[1] * alpha;
|
||||
data[i*m+i_b] = color[2] * alpha;
|
||||
}
|
||||
else {
|
||||
data[i*m ] = data[i*m+i_g] = data[i*m+i_b] = 0.0f;
|
||||
}
|
||||
data[i*m+i_a] = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void smoke_get_rgba_from_density(FLUID_3D *fluid, float color[3], float *data, int sequential)
|
||||
{
|
||||
get_rgba_from_density(color, fluid->_density, fluid->_totalCells, data, sequential);
|
||||
}
|
||||
|
||||
extern "C" void smoke_turbulence_get_rgba_from_density(WTURBULENCE *wt, float color[3], float *data, int sequential)
|
||||
{
|
||||
get_rgba_from_density(color, wt->_densityBig, wt->_totalCellsBig, data, sequential);
|
||||
}
|
||||
|
||||
extern "C" float *smoke_turbulence_get_density(WTURBULENCE *wt)
|
||||
{
|
||||
return wt ? wt->getDensityBig() : NULL;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_turbulence_get_fuel(WTURBULENCE *wt)
|
||||
{
|
||||
return wt ? wt->getFuelBig() : NULL;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_turbulence_get_react(WTURBULENCE *wt)
|
||||
{
|
||||
return wt ? wt->_reactBig : NULL;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_turbulence_get_color_r(WTURBULENCE *wt)
|
||||
{
|
||||
return wt ? wt->_color_rBig : NULL;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_turbulence_get_color_g(WTURBULENCE *wt)
|
||||
{
|
||||
return wt ? wt->_color_gBig : NULL;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_turbulence_get_color_b(WTURBULENCE *wt)
|
||||
{
|
||||
return wt ? wt->_color_bBig : NULL;
|
||||
}
|
||||
|
||||
extern "C" float *smoke_turbulence_get_flame(WTURBULENCE *wt)
|
||||
{
|
||||
return wt ? wt->getFlameBig() : NULL;
|
||||
}
|
||||
|
||||
extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res)
|
||||
{
|
||||
if(wt)
|
||||
{
|
||||
if(wt) {
|
||||
Vec3Int r = wt->getResBig();
|
||||
res[0] = r[0];
|
||||
res[1] = r[1];
|
||||
@@ -272,6 +395,15 @@ extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int smoke_turbulence_get_cells(WTURBULENCE *wt)
|
||||
{
|
||||
if(wt) {
|
||||
Vec3Int r = wt->getResBig();
|
||||
return r[0]*r[1]*r[2];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_obstacles;
|
||||
@@ -295,3 +427,61 @@ extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
|
||||
{
|
||||
wt->setNoise(type);
|
||||
}
|
||||
|
||||
extern "C" void flame_get_spectrum(unsigned char *spec, int width, float t1, float t2)
|
||||
{
|
||||
spectrum(t1, t2, width, spec);
|
||||
}
|
||||
|
||||
extern "C" int smoke_has_heat(FLUID_3D *fluid)
|
||||
{
|
||||
return (fluid->_heat) ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" int smoke_has_fuel(FLUID_3D *fluid)
|
||||
{
|
||||
return (fluid->_fuel) ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" int smoke_has_colors(FLUID_3D *fluid)
|
||||
{
|
||||
return (fluid->_color_r && fluid->_color_g && fluid->_color_b) ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" int smoke_turbulence_has_fuel(WTURBULENCE *wt)
|
||||
{
|
||||
return (wt->_fuelBig) ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" int smoke_turbulence_has_colors(WTURBULENCE *wt)
|
||||
{
|
||||
return (wt->_color_rBig && wt->_color_gBig && wt->_color_bBig) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* additional field initialization */
|
||||
extern "C" void smoke_ensure_heat(FLUID_3D *fluid)
|
||||
{
|
||||
if (fluid) {
|
||||
fluid->initHeat();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void smoke_ensure_fire(FLUID_3D *fluid, WTURBULENCE *wt)
|
||||
{
|
||||
if (fluid) {
|
||||
fluid->initFire();
|
||||
}
|
||||
if (wt) {
|
||||
wt->initFire();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void smoke_ensure_colors(FLUID_3D *fluid, WTURBULENCE *wt, float init_r, float init_g, float init_b)
|
||||
{
|
||||
if (fluid) {
|
||||
fluid->initColors(init_r, init_g, init_b);
|
||||
}
|
||||
if (wt) {
|
||||
wt->initColors(init_r, init_g, init_b);
|
||||
}
|
||||
}
|
||||
411
intern/smoke/intern/spectrum.cpp
Normal file
411
intern/smoke/intern/spectrum.cpp
Normal file
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
Colour Rendering of Spectra
|
||||
|
||||
by John Walker
|
||||
http://www.fourmilab.ch/
|
||||
|
||||
Last updated: March 9, 2003
|
||||
|
||||
This program is in the public domain.
|
||||
|
||||
For complete information about the techniques employed in
|
||||
this program, see the World-Wide Web document:
|
||||
|
||||
http://www.fourmilab.ch/documents/specrend/
|
||||
|
||||
The xyz_to_rgb() function, which was wrong in the original
|
||||
version of this program, was corrected by:
|
||||
|
||||
Andrew J. S. Hamilton 21 May 1999
|
||||
Andrew.Hamilton@Colorado.EDU
|
||||
http://casa.colorado.edu/~ajsh/
|
||||
|
||||
who also added the gamma correction facilities and
|
||||
modified constrain_rgb() to work by desaturating the
|
||||
colour by adding white.
|
||||
|
||||
A program which uses these functions to plot CIE
|
||||
"tongue" diagrams called "ppmcie" is included in
|
||||
the Netpbm graphics toolkit:
|
||||
http://netpbm.sourceforge.net/
|
||||
(The program was called cietoppm in earlier
|
||||
versions of Netpbm.)
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
/* A colour system is defined by the CIE x and y coordinates of
|
||||
its three primary illuminants and the x and y coordinates of
|
||||
the white point. */
|
||||
|
||||
struct colourSystem {
|
||||
char *name; /* Colour system name */
|
||||
double xRed, yRed, /* Red x, y */
|
||||
xGreen, yGreen, /* Green x, y */
|
||||
xBlue, yBlue, /* Blue x, y */
|
||||
xWhite, yWhite, /* White point x, y */
|
||||
gamma; /* Gamma correction for system */
|
||||
};
|
||||
|
||||
/* White point chromaticities. */
|
||||
|
||||
#define IlluminantC 0.3101, 0.3162 /* For NTSC television */
|
||||
#define IlluminantD65 0.3127, 0.3291 /* For EBU and SMPTE */
|
||||
#define IlluminantE 0.33333333, 0.33333333 /* CIE equal-energy illuminant */
|
||||
|
||||
/* Gamma of nonlinear correction.
|
||||
|
||||
See Charles Poynton's ColorFAQ Item 45 and GammaFAQ Item 6 at:
|
||||
|
||||
http://www.poynton.com/ColorFAQ.html
|
||||
http://www.poynton.com/GammaFAQ.html
|
||||
|
||||
*/
|
||||
|
||||
#define GAMMA_REC709 0 /* Rec. 709 */
|
||||
|
||||
static struct colourSystem
|
||||
/* Name xRed yRed xGreen yGreen xBlue yBlue White point Gamma */
|
||||
NTSCsystem = { "NTSC", 0.67, 0.33, 0.21, 0.71, 0.14, 0.08, IlluminantC, GAMMA_REC709 },
|
||||
EBUsystem = { "EBU (PAL/SECAM)", 0.64, 0.33, 0.29, 0.60, 0.15, 0.06, IlluminantD65, GAMMA_REC709 },
|
||||
SMPTEsystem = { "SMPTE", 0.630, 0.340, 0.310, 0.595, 0.155, 0.070, IlluminantD65, GAMMA_REC709 },
|
||||
HDTVsystem = { "HDTV", 0.670, 0.330, 0.210, 0.710, 0.150, 0.060, IlluminantD65, GAMMA_REC709 },
|
||||
CIEsystem = { "CIE", 0.7355, 0.2645, 0.2658, 0.7243, 0.1669, 0.0085, IlluminantE, GAMMA_REC709 },
|
||||
Rec709system = { "CIE REC 709", 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, IlluminantD65, GAMMA_REC709 };
|
||||
|
||||
/* UPVP_TO_XY
|
||||
|
||||
Given 1976 coordinates u', v', determine 1931 chromaticities x, y
|
||||
|
||||
*/
|
||||
|
||||
void upvp_to_xy(double up, double vp, double *xc, double *yc)
|
||||
{
|
||||
*xc = (9 * up) / ((6 * up) - (16 * vp) + 12);
|
||||
*yc = (4 * vp) / ((6 * up) - (16 * vp) + 12);
|
||||
}
|
||||
|
||||
/* XY_TO_UPVP
|
||||
|
||||
Given 1931 chromaticities x, y, determine 1976 coordinates u', v'
|
||||
|
||||
*/
|
||||
|
||||
void xy_to_upvp(double xc, double yc, double *up, double *vp)
|
||||
{
|
||||
*up = (4 * xc) / ((-2 * xc) + (12 * yc) + 3);
|
||||
*vp = (9 * yc) / ((-2 * xc) + (12 * yc) + 3);
|
||||
}
|
||||
|
||||
/* XYZ_TO_RGB
|
||||
|
||||
Given an additive tricolour system CS, defined by the CIE x
|
||||
and y chromaticities of its three primaries (z is derived
|
||||
trivially as 1-(x+y)), and a desired chromaticity (XC, YC,
|
||||
ZC) in CIE space, determine the contribution of each
|
||||
primary in a linear combination which sums to the desired
|
||||
chromaticity. If the requested chromaticity falls outside
|
||||
the Maxwell triangle (colour gamut) formed by the three
|
||||
primaries, one of the r, g, or b weights will be negative.
|
||||
|
||||
Caller can use constrain_rgb() to desaturate an
|
||||
outside-gamut colour to the closest representation within
|
||||
the available gamut and/or norm_rgb to normalise the RGB
|
||||
components so the largest nonzero component has value 1.
|
||||
|
||||
*/
|
||||
|
||||
void xyz_to_rgb(struct colourSystem *cs,
|
||||
double xc, double yc, double zc,
|
||||
double *r, double *g, double *b)
|
||||
{
|
||||
double xr, yr, zr, xg, yg, zg, xb, yb, zb;
|
||||
double xw, yw, zw;
|
||||
double rx, ry, rz, gx, gy, gz, bx, by, bz;
|
||||
double rw, gw, bw;
|
||||
|
||||
xr = cs->xRed; yr = cs->yRed; zr = 1 - (xr + yr);
|
||||
xg = cs->xGreen; yg = cs->yGreen; zg = 1 - (xg + yg);
|
||||
xb = cs->xBlue; yb = cs->yBlue; zb = 1 - (xb + yb);
|
||||
|
||||
xw = cs->xWhite; yw = cs->yWhite; zw = 1 - (xw + yw);
|
||||
|
||||
/* xyz -> rgb matrix, before scaling to white. */
|
||||
|
||||
rx = (yg * zb) - (yb * zg); ry = (xb * zg) - (xg * zb); rz = (xg * yb) - (xb * yg);
|
||||
gx = (yb * zr) - (yr * zb); gy = (xr * zb) - (xb * zr); gz = (xb * yr) - (xr * yb);
|
||||
bx = (yr * zg) - (yg * zr); by = (xg * zr) - (xr * zg); bz = (xr * yg) - (xg * yr);
|
||||
|
||||
/* White scaling factors.
|
||||
Dividing by yw scales the white luminance to unity, as conventional. */
|
||||
|
||||
rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw;
|
||||
gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw;
|
||||
bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw;
|
||||
|
||||
/* xyz -> rgb matrix, correctly scaled to white. */
|
||||
|
||||
rx = rx / rw; ry = ry / rw; rz = rz / rw;
|
||||
gx = gx / gw; gy = gy / gw; gz = gz / gw;
|
||||
bx = bx / bw; by = by / bw; bz = bz / bw;
|
||||
|
||||
/* rgb of the desired point */
|
||||
|
||||
*r = (rx * xc) + (ry * yc) + (rz * zc);
|
||||
*g = (gx * xc) + (gy * yc) + (gz * zc);
|
||||
*b = (bx * xc) + (by * yc) + (bz * zc);
|
||||
}
|
||||
|
||||
/* INSIDE_GAMUT
|
||||
|
||||
Test whether a requested colour is within the gamut
|
||||
achievable with the primaries of the current colour
|
||||
system. This amounts simply to testing whether all the
|
||||
primary weights are non-negative. */
|
||||
|
||||
int inside_gamut(double r, double g, double b)
|
||||
{
|
||||
return (r >= 0) && (g >= 0) && (b >= 0);
|
||||
}
|
||||
|
||||
/* CONSTRAIN_RGB
|
||||
|
||||
If the requested RGB shade contains a negative weight for
|
||||
one of the primaries, it lies outside the colour gamut
|
||||
accessible from the given triple of primaries. Desaturate
|
||||
it by adding white, equal quantities of R, G, and B, enough
|
||||
to make RGB all positive. The function returns 1 if the
|
||||
components were modified, zero otherwise.
|
||||
|
||||
*/
|
||||
|
||||
int constrain_rgb(double *r, double *g, double *b)
|
||||
{
|
||||
double w;
|
||||
|
||||
/* Amount of white needed is w = - min(0, *r, *g, *b) */
|
||||
|
||||
w = (0 < *r) ? 0 : *r;
|
||||
w = (w < *g) ? w : *g;
|
||||
w = (w < *b) ? w : *b;
|
||||
w = -w;
|
||||
|
||||
/* Add just enough white to make r, g, b all positive. */
|
||||
|
||||
if (w > 0) {
|
||||
*r += w; *g += w; *b += w;
|
||||
return 1; /* Colour modified to fit RGB gamut */
|
||||
}
|
||||
|
||||
return 0; /* Colour within RGB gamut */
|
||||
}
|
||||
|
||||
/* GAMMA_CORRECT_RGB
|
||||
|
||||
Transform linear RGB values to nonlinear RGB values. Rec.
|
||||
709 is ITU-R Recommendation BT. 709 (1990) ``Basic
|
||||
Parameter Values for the HDTV Standard for the Studio and
|
||||
for International Programme Exchange'', formerly CCIR Rec.
|
||||
709. For details see
|
||||
|
||||
http://www.poynton.com/ColorFAQ.html
|
||||
http://www.poynton.com/GammaFAQ.html
|
||||
*/
|
||||
|
||||
void gamma_correct(const struct colourSystem *cs, double *c)
|
||||
{
|
||||
double gamma;
|
||||
|
||||
gamma = cs->gamma;
|
||||
|
||||
if (gamma == GAMMA_REC709) {
|
||||
/* Rec. 709 gamma correction. */
|
||||
double cc = 0.018;
|
||||
|
||||
if (*c < cc) {
|
||||
*c *= ((1.099 * pow(cc, 0.45)) - 0.099) / cc;
|
||||
} else {
|
||||
*c = (1.099 * pow(*c, 0.45)) - 0.099;
|
||||
}
|
||||
} else {
|
||||
/* Nonlinear colour = (Linear colour)^(1/gamma) */
|
||||
*c = pow(*c, 1.0 / gamma);
|
||||
}
|
||||
}
|
||||
|
||||
void gamma_correct_rgb(const struct colourSystem *cs, double *r, double *g, double *b)
|
||||
{
|
||||
gamma_correct(cs, r);
|
||||
gamma_correct(cs, g);
|
||||
gamma_correct(cs, b);
|
||||
}
|
||||
|
||||
/* NORM_RGB
|
||||
|
||||
Normalise RGB components so the most intense (unless all
|
||||
are zero) has a value of 1.
|
||||
|
||||
*/
|
||||
|
||||
void norm_rgb(double *r, double *g, double *b)
|
||||
{
|
||||
#define Max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
double greatest = Max(*r, Max(*g, *b));
|
||||
|
||||
if (greatest > 0) {
|
||||
*r /= greatest;
|
||||
*g /= greatest;
|
||||
*b /= greatest;
|
||||
}
|
||||
#undef Max
|
||||
}
|
||||
|
||||
/* SPECTRUM_TO_XYZ
|
||||
|
||||
Calculate the CIE X, Y, and Z coordinates corresponding to
|
||||
a light source with spectral distribution given by the
|
||||
function SPEC_INTENS, which is called with a series of
|
||||
wavelengths between 380 and 780 nm (the argument is
|
||||
expressed in meters), which returns emittance at that
|
||||
wavelength in arbitrary units. The chromaticity
|
||||
coordinates of the spectrum are returned in the x, y, and z
|
||||
arguments which respect the identity:
|
||||
|
||||
x + y + z = 1.
|
||||
*/
|
||||
|
||||
void spectrum_to_xyz(double (*spec_intens)(double wavelength),
|
||||
double *x, double *y, double *z)
|
||||
{
|
||||
int i;
|
||||
double lambda, X = 0, Y = 0, Z = 0, XYZ;
|
||||
|
||||
/* CIE colour matching functions xBar, yBar, and zBar for
|
||||
wavelengths from 380 through 780 nanometers, every 5
|
||||
nanometers. For a wavelength lambda in this range:
|
||||
|
||||
cie_colour_match[(lambda - 380) / 5][0] = xBar
|
||||
cie_colour_match[(lambda - 380) / 5][1] = yBar
|
||||
cie_colour_match[(lambda - 380) / 5][2] = zBar
|
||||
|
||||
To save memory, this table can be declared as floats
|
||||
rather than doubles; (IEEE) float has enough
|
||||
significant bits to represent the values. It's declared
|
||||
as a double here to avoid warnings about "conversion
|
||||
between floating-point types" from certain persnickety
|
||||
compilers. */
|
||||
|
||||
static double cie_colour_match[81][3] = {
|
||||
{0.0014,0.0000,0.0065}, {0.0022,0.0001,0.0105}, {0.0042,0.0001,0.0201},
|
||||
{0.0076,0.0002,0.0362}, {0.0143,0.0004,0.0679}, {0.0232,0.0006,0.1102},
|
||||
{0.0435,0.0012,0.2074}, {0.0776,0.0022,0.3713}, {0.1344,0.0040,0.6456},
|
||||
{0.2148,0.0073,1.0391}, {0.2839,0.0116,1.3856}, {0.3285,0.0168,1.6230},
|
||||
{0.3483,0.0230,1.7471}, {0.3481,0.0298,1.7826}, {0.3362,0.0380,1.7721},
|
||||
{0.3187,0.0480,1.7441}, {0.2908,0.0600,1.6692}, {0.2511,0.0739,1.5281},
|
||||
{0.1954,0.0910,1.2876}, {0.1421,0.1126,1.0419}, {0.0956,0.1390,0.8130},
|
||||
{0.0580,0.1693,0.6162}, {0.0320,0.2080,0.4652}, {0.0147,0.2586,0.3533},
|
||||
{0.0049,0.3230,0.2720}, {0.0024,0.4073,0.2123}, {0.0093,0.5030,0.1582},
|
||||
{0.0291,0.6082,0.1117}, {0.0633,0.7100,0.0782}, {0.1096,0.7932,0.0573},
|
||||
{0.1655,0.8620,0.0422}, {0.2257,0.9149,0.0298}, {0.2904,0.9540,0.0203},
|
||||
{0.3597,0.9803,0.0134}, {0.4334,0.9950,0.0087}, {0.5121,1.0000,0.0057},
|
||||
{0.5945,0.9950,0.0039}, {0.6784,0.9786,0.0027}, {0.7621,0.9520,0.0021},
|
||||
{0.8425,0.9154,0.0018}, {0.9163,0.8700,0.0017}, {0.9786,0.8163,0.0014},
|
||||
{1.0263,0.7570,0.0011}, {1.0567,0.6949,0.0010}, {1.0622,0.6310,0.0008},
|
||||
{1.0456,0.5668,0.0006}, {1.0026,0.5030,0.0003}, {0.9384,0.4412,0.0002},
|
||||
{0.8544,0.3810,0.0002}, {0.7514,0.3210,0.0001}, {0.6424,0.2650,0.0000},
|
||||
{0.5419,0.2170,0.0000}, {0.4479,0.1750,0.0000}, {0.3608,0.1382,0.0000},
|
||||
{0.2835,0.1070,0.0000}, {0.2187,0.0816,0.0000}, {0.1649,0.0610,0.0000},
|
||||
{0.1212,0.0446,0.0000}, {0.0874,0.0320,0.0000}, {0.0636,0.0232,0.0000},
|
||||
{0.0468,0.0170,0.0000}, {0.0329,0.0119,0.0000}, {0.0227,0.0082,0.0000},
|
||||
{0.0158,0.0057,0.0000}, {0.0114,0.0041,0.0000}, {0.0081,0.0029,0.0000},
|
||||
{0.0058,0.0021,0.0000}, {0.0041,0.0015,0.0000}, {0.0029,0.0010,0.0000},
|
||||
{0.0020,0.0007,0.0000}, {0.0014,0.0005,0.0000}, {0.0010,0.0004,0.0000},
|
||||
{0.0007,0.0002,0.0000}, {0.0005,0.0002,0.0000}, {0.0003,0.0001,0.0000},
|
||||
{0.0002,0.0001,0.0000}, {0.0002,0.0001,0.0000}, {0.0001,0.0000,0.0000},
|
||||
{0.0001,0.0000,0.0000}, {0.0001,0.0000,0.0000}, {0.0000,0.0000,0.0000}
|
||||
};
|
||||
|
||||
for (i = 0, lambda = 380; lambda < 780.1; i++, lambda += 5) {
|
||||
double Me;
|
||||
|
||||
Me = (*spec_intens)(lambda);
|
||||
X += Me * cie_colour_match[i][0];
|
||||
Y += Me * cie_colour_match[i][1];
|
||||
Z += Me * cie_colour_match[i][2];
|
||||
}
|
||||
XYZ = (X + Y + Z);
|
||||
*x = X / XYZ;
|
||||
*y = Y / XYZ;
|
||||
*z = Z / XYZ;
|
||||
}
|
||||
|
||||
/* BB_SPECTRUM
|
||||
|
||||
Calculate, by Planck's radiation law, the emittance of a black body
|
||||
of temperature bbTemp at the given wavelength (in metres). */
|
||||
|
||||
double bbTemp = 5000; /* Hidden temperature argument
|
||||
to BB_SPECTRUM. */
|
||||
double bb_spectrum(double wavelength)
|
||||
{
|
||||
double wlm = wavelength * 1e-9; /* Wavelength in meters */
|
||||
|
||||
return (3.74183e-16 * pow(wlm, -5.0)) /
|
||||
(exp(1.4388e-2 / (wlm * bbTemp)) - 1.0);
|
||||
}
|
||||
|
||||
void xyz_to_lms(double x, double y, double z, double* l, double* m, double* s)
|
||||
{
|
||||
*l = 0.3897*x + 0.6890*y - 0.0787*z;
|
||||
*m = -0.2298*x + 1.1834*y + 0.0464*z;
|
||||
*s = z;
|
||||
}
|
||||
|
||||
void lms_to_xyz(double l, double m, double s, double* x, double *y, double* z)
|
||||
{
|
||||
*x = 1.9102*l - 1.1121*m + 0.2019*s;
|
||||
*y = 0.3709*l + 0.6290*m + 0.0000*s;
|
||||
*z = s;
|
||||
}
|
||||
|
||||
void spectrum(double t1, double t2, int N, unsigned char* d)
|
||||
{
|
||||
int i,j,dj;
|
||||
double X,Y,Z,R,G,B,L,M,S, Lw, Mw, Sw;
|
||||
struct colourSystem *cs = &CIEsystem;
|
||||
|
||||
j = 0; dj = 1;
|
||||
if (t1<t2) {
|
||||
double t = t1;
|
||||
t1 = t2;
|
||||
t2 = t;
|
||||
j = N-1; dj=-1;
|
||||
}
|
||||
|
||||
for (i=0; i<N; i++) {
|
||||
bbTemp = t1 + (t2-t1)/N*i;
|
||||
|
||||
// integrate blackbody radiation spectrum to XYZ
|
||||
spectrum_to_xyz(bb_spectrum, &X, &Y, &Z);
|
||||
|
||||
// normalize highest temperature to white (in LMS system)
|
||||
xyz_to_lms(X,Y,Z,&L,&M,&S);
|
||||
if (i==0) {
|
||||
Lw=1/L; Mw=1/M; Sw=1/S;
|
||||
}
|
||||
L *= Lw; M *= Mw; S *= Sw;
|
||||
lms_to_xyz(L,M,S,&X,&Y,&Z);
|
||||
|
||||
// convert to RGB
|
||||
xyz_to_rgb(cs, X, Y, Z, &R, &G, &B);
|
||||
constrain_rgb(&R, &G, &B);
|
||||
norm_rgb(&R, &G, &B);
|
||||
d[(j<<2)] = (unsigned char) ((double)R*255);
|
||||
d[(j<<2)+1] = (unsigned char) ((double)G*255);
|
||||
d[(j<<2)+2] = (unsigned char) ((double)B*255);
|
||||
d[(j<<2)+3] = (B>0.1)? B*255 : 0;
|
||||
j += dj;
|
||||
}
|
||||
}
|
||||
6
intern/smoke/intern/spectrum.h
Normal file
6
intern/smoke/intern/spectrum.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef __SPECTRUM_H
|
||||
#define __SPECTRUM_H
|
||||
|
||||
void spectrum(double t1, double t2, int n, unsigned char* d);
|
||||
|
||||
#endif
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 222 KiB After Width: | Height: | Size: 204 KiB |
@@ -299,7 +299,6 @@ class QuickSmoke(Operator):
|
||||
style = EnumProperty(
|
||||
name="Smoke Style",
|
||||
items=(('STREAM', "Stream", ""),
|
||||
('PUFF', "Puff", ""),
|
||||
('FIRE', "Fire", ""),
|
||||
),
|
||||
default='STREAM',
|
||||
@@ -328,20 +327,9 @@ class QuickSmoke(Operator):
|
||||
bpy.ops.object.modifier_add(fake_context, type='SMOKE')
|
||||
obj.modifiers[-1].smoke_type = 'FLOW'
|
||||
|
||||
psys = obj.particle_systems[-1]
|
||||
if self.style == 'PUFF':
|
||||
psys.settings.frame_end = psys.settings.frame_start
|
||||
psys.settings.emit_from = 'VOLUME'
|
||||
psys.settings.distribution = 'RAND'
|
||||
elif self.style == 'FIRE':
|
||||
psys.settings.effector_weights.gravity = -1
|
||||
psys.settings.lifetime = 5
|
||||
psys.settings.count = 100000
|
||||
if self.style == 'FIRE':
|
||||
obj.modifiers[-1].flow_settings.smoke_flow_type = 'FIRE'
|
||||
|
||||
obj.modifiers[-2].flow_settings.initial_velocity = True
|
||||
obj.modifiers[-2].flow_settings.temperature = 2
|
||||
|
||||
psys.settings.use_render_emitter = self.show_flows
|
||||
if not self.show_flows:
|
||||
obj.draw_type = 'WIRE'
|
||||
|
||||
@@ -361,8 +349,6 @@ class QuickSmoke(Operator):
|
||||
bpy.ops.object.modifier_add(type='SMOKE')
|
||||
obj.modifiers[-1].smoke_type = 'DOMAIN'
|
||||
if self.style == 'FIRE':
|
||||
obj.modifiers[-1].domain_settings.use_dissolve_smoke = True
|
||||
obj.modifiers[-1].domain_settings.dissolve_speed = 20
|
||||
obj.modifiers[-1].domain_settings.use_high_resolution = True
|
||||
|
||||
# create a volume material with a voxel data texture for the domain
|
||||
@@ -373,6 +359,7 @@ class QuickSmoke(Operator):
|
||||
mat.type = 'VOLUME'
|
||||
mat.volume.density = 0
|
||||
mat.volume.density_scale = 5
|
||||
mat.volume.step_size = 0.1
|
||||
|
||||
tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
|
||||
tex.voxel_data.domain_object = obj
|
||||
@@ -381,29 +368,35 @@ class QuickSmoke(Operator):
|
||||
tex_slot.texture = tex
|
||||
tex_slot.use_map_color_emission = False
|
||||
tex_slot.use_map_density = True
|
||||
tex_slot.use_map_color_reflection = True
|
||||
|
||||
# for fire add a second texture for emission and emission color
|
||||
if self.style == 'FIRE':
|
||||
mat.volume.emission = 5
|
||||
tex = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA')
|
||||
# for fire add a second texture for flame emission
|
||||
mat.volume.emission_color = Vector((0.0, 0.0, 0.0))
|
||||
tex = bpy.data.textures.new("Flame", 'VOXEL_DATA')
|
||||
tex.voxel_data.domain_object = obj
|
||||
tex.voxel_data.smoke_data_type = 'SMOKEFLAME'
|
||||
tex.use_color_ramp = True
|
||||
|
||||
tex_slot = mat.texture_slots.add()
|
||||
tex_slot.texture = tex
|
||||
|
||||
# add color ramp for flame color
|
||||
ramp = tex.color_ramp
|
||||
|
||||
# dark orange
|
||||
elem = ramp.elements.new(0.333)
|
||||
elem.color[0] = elem.color[3] = 1
|
||||
elem.color[1] = elem.color[2] = 0
|
||||
|
||||
elem = ramp.elements.new(0.666)
|
||||
elem.color[0] = elem.color[1] = elem.color[3] = 1
|
||||
elem.color[0] = 0.2
|
||||
elem.color[1] = 0.03
|
||||
elem.color[2] = 0
|
||||
elem.color[3] = 1
|
||||
# yellow glow
|
||||
elem = ramp.elements.new(0.666)
|
||||
elem.color[0] = elem.color[3] = 1
|
||||
elem.color[1] = 0.65
|
||||
elem.color[2] = 0.25
|
||||
|
||||
mat.texture_slots[1].use_map_density = True
|
||||
mat.texture_slots[1].use_map_emission = True
|
||||
mat.texture_slots[1].blend_type = 'MULTIPLY'
|
||||
mat.texture_slots[1].emission_factor = 5
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@@ -1124,7 +1124,7 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
|
||||
|
||||
def draw(self, context):
|
||||
part = particle_get_settings(context)
|
||||
effector_weights_ui(self, context, part.effector_weights)
|
||||
effector_weights_ui(self, context, part.effector_weights, 'PSYS')
|
||||
|
||||
if part.type == 'HAIR':
|
||||
row = self.layout.row()
|
||||
|
||||
@@ -197,7 +197,7 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
|
||||
|
||||
def draw(self, context):
|
||||
cloth = context.cloth.settings
|
||||
effector_weights_ui(self, context, cloth.effector_weights)
|
||||
effector_weights_ui(self, context, cloth.effector_weights, 'CLOTH')
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
bpy.utils.register_module(__name__)
|
||||
|
||||
@@ -179,7 +179,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
|
||||
col.operator("ptcache.bake_all", text="Update All To Frame").bake = False
|
||||
|
||||
|
||||
def effector_weights_ui(self, context, weights):
|
||||
def effector_weights_ui(self, context, weights, weight_type):
|
||||
layout = self.layout
|
||||
|
||||
layout.prop(weights, "group")
|
||||
@@ -200,6 +200,8 @@ def effector_weights_ui(self, context, weights):
|
||||
col.prop(weights, "wind", slider=True)
|
||||
col.prop(weights, "curve_guide", slider=True)
|
||||
col.prop(weights, "texture", slider=True)
|
||||
if weight_type != 'SMOKE':
|
||||
col.prop(weights, "smokeflow", slider=True)
|
||||
|
||||
col = split.column()
|
||||
col.prop(weights, "harmonic", slider=True)
|
||||
|
||||
@@ -349,7 +349,7 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
|
||||
|
||||
col = layout.column()
|
||||
col.active = surface.use_drip
|
||||
effector_weights_ui(self, context, surface.effector_weights)
|
||||
effector_weights_ui(self, context, surface.effector_weights, 'DYNAMIC_PAINT')
|
||||
|
||||
layout.label(text="Surface Movement:")
|
||||
row = layout.row()
|
||||
|
||||
@@ -112,6 +112,14 @@ class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
|
||||
col = split.column()
|
||||
col.prop(field, "use_object_coords")
|
||||
col.prop(field, "use_2d_force")
|
||||
elif field.type == 'SMOKE_FLOW':
|
||||
col = split.column()
|
||||
col.prop(field, "strength")
|
||||
col.prop(field, "flow")
|
||||
col = split.column()
|
||||
col.label(text="Domain Object:")
|
||||
col.prop(field, "source_object", "")
|
||||
col.prop(field, "use_smoke_density")
|
||||
else:
|
||||
basic_force_field_settings_ui(self, context, field)
|
||||
|
||||
|
||||
@@ -77,27 +77,39 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
|
||||
|
||||
flow = md.flow_settings
|
||||
|
||||
split = layout.split()
|
||||
layout.prop(flow, "smoke_flow_type", expand=False)
|
||||
|
||||
if flow.smoke_flow_type != "OUTFLOW":
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.prop(flow, "use_outflow")
|
||||
col.label(text="Flow Source:")
|
||||
col.prop(flow, "smoke_flow_source", expand=False, text="")
|
||||
if flow.smoke_flow_source == "PARTICLES":
|
||||
col.label(text="Particle System:")
|
||||
col.prop_search(flow, "particle_system", ob, "particle_systems", text="")
|
||||
else:
|
||||
col.prop(flow, "surface_distance")
|
||||
col.prop(flow, "volume_density")
|
||||
|
||||
sub = col.column()
|
||||
sub.active = not md.flow_settings.use_outflow
|
||||
sub = col.column(align=True)
|
||||
|
||||
sub.prop(flow, "initial_velocity", text="Initial Velocity")
|
||||
sub.prop(flow, "initial_velocity")
|
||||
sub = sub.column()
|
||||
sub.active = flow.initial_velocity
|
||||
sub.prop(flow, "velocity_factor", text="Multiplier")
|
||||
sub.prop(flow, "velocity_factor")
|
||||
if flow.smoke_flow_source == "MESH":
|
||||
sub.prop(flow, "velocity_normal")
|
||||
#sub.prop(flow, "velocity_random")
|
||||
|
||||
sub = split.column()
|
||||
sub.active = not md.flow_settings.use_outflow
|
||||
sub.label(text="Initial Values:")
|
||||
sub.prop(flow, "use_absolute")
|
||||
if flow.smoke_flow_type in {'SMOKE', 'BOTH'}:
|
||||
sub.prop(flow, "density")
|
||||
sub.prop(flow, "temperature")
|
||||
sub.prop(flow, "smoke_color")
|
||||
if flow.smoke_flow_type in {'FIRE', 'BOTH'}:
|
||||
sub.prop(flow, "fuel_amount")
|
||||
|
||||
elif md.smoke_type == 'COLLISION':
|
||||
coll = md.coll_settings
|
||||
@@ -107,35 +119,98 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
|
||||
col = split.column()
|
||||
col.prop(coll, "collision_type")
|
||||
|
||||
|
||||
class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Smoke Groups"
|
||||
class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Smoke Flow Advanced"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
md = context.smoke
|
||||
rd = context.scene.render
|
||||
return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine)
|
||||
return md and (md.smoke_type == 'FLOW') and (md.flow_settings.smoke_flow_source == "MESH")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob = context.object
|
||||
flow = context.smoke.flow_settings
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
|
||||
col.prop(flow, "use_texture")
|
||||
sub = col.column()
|
||||
sub.active = flow.use_texture
|
||||
sub.prop(flow, "noise_texture", text="")
|
||||
sub.label(text="Mapping:")
|
||||
sub.prop(flow, "texture_map_type", expand=False, text="")
|
||||
if flow.texture_map_type == "UV":
|
||||
sub.prop_search(flow, "uv_layer", ob.data, "uv_textures", text="")
|
||||
if flow.texture_map_type == "AUTO":
|
||||
sub.prop(flow, "texture_size")
|
||||
sub.prop(flow, "texture_offset")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Vertex Group:")
|
||||
col.prop_search(flow, "density_vertex_group", ob, "vertex_groups", text="")
|
||||
|
||||
class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Smoke Flames"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
md = context.smoke
|
||||
return md and (md.smoke_type == 'DOMAIN')
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
domain = context.smoke.domain_settings
|
||||
|
||||
split = layout.split()
|
||||
split.enabled = not domain.point_cache.is_baked
|
||||
|
||||
col = split.column(align=True)
|
||||
col.label(text="Reaction:")
|
||||
col.prop(domain, "burning_rate")
|
||||
col.prop(domain, "flame_smoke")
|
||||
col.prop(domain, "flame_vorticity")
|
||||
|
||||
col = split.column(align=True)
|
||||
col.label(text="Temperatures:")
|
||||
col.prop(domain, "flame_ignition")
|
||||
col.prop(domain, "flame_max_temp")
|
||||
col.prop(domain, "flame_smoke_color")
|
||||
|
||||
class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Smoke Adaptive Domain"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
md = context.smoke
|
||||
return md and (md.smoke_type == 'DOMAIN')
|
||||
|
||||
def draw_header(self, context):
|
||||
md = context.smoke.domain_settings
|
||||
|
||||
self.layout.prop(md, "use_adaptive_domain", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
group = context.smoke.domain_settings
|
||||
domain = context.smoke.domain_settings
|
||||
layout.active = domain.use_adaptive_domain
|
||||
|
||||
split = layout.split()
|
||||
split.enabled = not domain.point_cache.is_baked
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Flow Group:")
|
||||
col.prop(group, "fluid_group", text="")
|
||||
|
||||
#col.label(text="Effector Group:")
|
||||
#col.prop(group, "effector_group", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Collision Group:")
|
||||
col.prop(group, "collision_group", text="")
|
||||
col = split.column(align=True)
|
||||
col.label(text="Resolution:")
|
||||
col.prop(domain, "additional_res")
|
||||
col.prop(domain, "adapt_margin")
|
||||
|
||||
col = split.column(align=True)
|
||||
col.label(text="Advanced:")
|
||||
col.prop(domain, "adapt_threshold")
|
||||
|
||||
class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Smoke High Resolution"
|
||||
@@ -174,6 +249,32 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
|
||||
|
||||
layout.prop(md, "show_high_resolution")
|
||||
|
||||
class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Smoke Groups"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
md = context.smoke
|
||||
rd = context.scene.render
|
||||
return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
domain = context.smoke.domain_settings
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Flow Group:")
|
||||
col.prop(domain, "fluid_group", text="")
|
||||
|
||||
#col.label(text="Effector Group:")
|
||||
#col.prop(domain, "effector_group", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Collision Group:")
|
||||
col.prop(domain, "collision_group", text="")
|
||||
|
||||
class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
|
||||
bl_label = "Smoke Cache"
|
||||
@@ -209,7 +310,7 @@ class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel):
|
||||
|
||||
def draw(self, context):
|
||||
domain = context.smoke.domain_settings
|
||||
effector_weights_ui(self, context, domain.effector_weights)
|
||||
effector_weights_ui(self, context, domain.effector_weights, 'SMOKE')
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
bpy.utils.register_module(__name__)
|
||||
|
||||
@@ -231,7 +231,7 @@ class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel):
|
||||
md = context.soft_body
|
||||
softbody = md.settings
|
||||
|
||||
effector_weights_ui(self, context, softbody.effector_weights)
|
||||
effector_weights_ui(self, context, softbody.effector_weights, 'SOFTBODY')
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
bpy.utils.register_module(__name__)
|
||||
|
||||
@@ -887,8 +887,12 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
|
||||
col = split.column()
|
||||
if tex.texture_coords in {'ORCO', 'UV'}:
|
||||
col.prop(tex, "use_from_dupli")
|
||||
if (idblock.type == 'VOLUME' and tex.texture_coords == 'ORCO'):
|
||||
col.prop(tex, "use_map_to_bounds")
|
||||
elif tex.texture_coords == 'OBJECT':
|
||||
col.prop(tex, "use_from_original")
|
||||
if (idblock.type == 'VOLUME'):
|
||||
col.prop(tex, "use_map_to_bounds")
|
||||
else:
|
||||
col.label()
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@
|
||||
|
||||
typedef float (*bresenham_callback)(float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
|
||||
|
||||
void smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
|
||||
struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
|
||||
|
||||
void smoke_reallocate_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old);
|
||||
void smoke_reallocate_highres_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old);
|
||||
void smokeModifier_free(struct SmokeModifierData *smd);
|
||||
void smokeModifier_reset(struct SmokeModifierData *smd);
|
||||
void smokeModifier_reset_turbulence(struct SmokeModifierData *smd);
|
||||
@@ -44,5 +46,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd);
|
||||
void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData *tsmd);
|
||||
|
||||
long long smoke_get_mem_req(int xres, int yres, int zres, int amplify);
|
||||
float smoke_get_velocity_at(struct Object *ob, float position[3], float velocity[3]);
|
||||
int smoke_get_data_flags(struct SmokeDomainSettings *sds);
|
||||
|
||||
#endif /* __BKE_SMOKE_H__ */
|
||||
|
||||
@@ -400,8 +400,7 @@ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Mat
|
||||
}
|
||||
}
|
||||
|
||||
static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node)
|
||||
{
|
||||
static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield){
|
||||
Base *base;
|
||||
DagNode *node2;
|
||||
|
||||
@@ -411,6 +410,8 @@ static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Objec
|
||||
if ((base->lay & ob->lay) && base->object->pd) {
|
||||
Object *ob1 = base->object;
|
||||
if ((ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) {
|
||||
if (skip_forcefield && ob1->pd->forcefield == skip_forcefield)
|
||||
continue;
|
||||
node2 = dag_get_node(dag, ob1);
|
||||
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Collision");
|
||||
}
|
||||
@@ -572,10 +573,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
|
||||
if (ob->particlesystem.first ||
|
||||
modifiers_isModifierEnabled(ob, eModifierType_Softbody) ||
|
||||
modifiers_isModifierEnabled(ob, eModifierType_Cloth) ||
|
||||
modifiers_isModifierEnabled(ob, eModifierType_Smoke) ||
|
||||
modifiers_isModifierEnabled(ob, eModifierType_DynamicPaint))
|
||||
{
|
||||
dag_add_collision_field_relation(dag, scene, ob, node); /* TODO: use effectorweight->group */
|
||||
dag_add_collision_field_relation(dag, scene, ob, node, 0); /* TODO: use effectorweight->group */
|
||||
}
|
||||
else if (modifiers_isModifierEnabled(ob, eModifierType_Smoke)) {
|
||||
dag_add_collision_field_relation(dag, scene, ob, node, PFIELD_SMOKEFLOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_smoke.h"
|
||||
|
||||
|
||||
#include "RE_render_ext.h"
|
||||
@@ -137,6 +138,9 @@ PartDeflect *object_add_collision_fields(int type)
|
||||
case PFIELD_TEXTURE:
|
||||
pd->f_size = 1.0f;
|
||||
break;
|
||||
case PFIELD_SMOKEFLOW:
|
||||
pd->f_flow = 1.0f;
|
||||
break;
|
||||
}
|
||||
pd->flag = PFIELD_DO_LOCATION|PFIELD_DO_ROTATION;
|
||||
|
||||
@@ -922,12 +926,27 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected
|
||||
|
||||
mul_v3_fl(force, -efd->falloff * fac * (strength * fac + damp));
|
||||
break;
|
||||
case PFIELD_SMOKEFLOW:
|
||||
zero_v3(force);
|
||||
if (pd->f_source) {
|
||||
float density;
|
||||
if ((density = smoke_get_velocity_at(pd->f_source, point->loc, force)) >= 0.0f) {
|
||||
float influence = strength * efd->falloff;
|
||||
if (pd->flag & PFIELD_SMOKE_DENSITY)
|
||||
influence *= density;
|
||||
mul_v3_fl(force, influence);
|
||||
/* apply flow */
|
||||
madd_v3_v3fl(total_force, point->vel, -pd->f_flow * influence);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (pd->flag & PFIELD_DO_LOCATION) {
|
||||
madd_v3_v3fl(total_force, force, 1.0f/point->vel_to_sec);
|
||||
|
||||
if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)==0 && pd->f_flow != 0.0f) {
|
||||
if (ELEM3(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) {
|
||||
madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,20 +532,31 @@ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
|
||||
if (sds->fluid) {
|
||||
return sds->res[0]*sds->res[1]*sds->res[2];
|
||||
return sds->base_res[0]*sds->base_res[1]*sds->base_res[2];
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SMOKE_CACHE_VERSION "1.04"
|
||||
|
||||
static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
|
||||
{
|
||||
SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
int ret = 0;
|
||||
int fluid_fields = smoke_get_data_flags(sds);
|
||||
|
||||
/* version header */
|
||||
ptcache_file_write(pf, SMOKE_CACHE_VERSION, 4, sizeof(char));
|
||||
ptcache_file_write(pf, &fluid_fields, 1, sizeof(int));
|
||||
ptcache_file_write(pf, &sds->active_fields, 1, sizeof(int));
|
||||
ptcache_file_write(pf, &sds->res, 3, sizeof(int));
|
||||
ptcache_file_write(pf, &sds->dx, 1, sizeof(float));
|
||||
|
||||
if (sds->fluid) {
|
||||
size_t res = sds->res[0]*sds->res[1]*sds->res[2];
|
||||
float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold;
|
||||
float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
|
||||
unsigned char *obstacles;
|
||||
unsigned int in_len = sizeof(float)*(unsigned int)res;
|
||||
unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
|
||||
@@ -553,22 +564,40 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
|
||||
int mode=1; // light
|
||||
if (sds->cache_comp == SM_CACHE_HEAVY) mode=2; // heavy
|
||||
|
||||
smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
|
||||
smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
|
||||
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len, out, mode);
|
||||
if (fluid_fields & SM_ACTIVE_HEAT) {
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode);
|
||||
}
|
||||
if (fluid_fields & SM_ACTIVE_FIRE) {
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)react, in_len, out, mode);
|
||||
}
|
||||
if (fluid_fields & SM_ACTIVE_COLORS) {
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)r, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)g, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)b, in_len, out, mode);
|
||||
}
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)vxold, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)vyold, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)vzold, in_len, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
|
||||
ptcache_file_write(pf, &dt, 1, sizeof(float));
|
||||
ptcache_file_write(pf, &dx, 1, sizeof(float));
|
||||
ptcache_file_write(pf, &sds->p0, 3, sizeof(float));
|
||||
ptcache_file_write(pf, &sds->p1, 3, sizeof(float));
|
||||
ptcache_file_write(pf, &sds->dp0, 3, sizeof(float));
|
||||
ptcache_file_write(pf, &sds->shift, 3, sizeof(int));
|
||||
ptcache_file_write(pf, &sds->obj_shift_f, 3, sizeof(float));
|
||||
ptcache_file_write(pf, &sds->obmat, 16, sizeof(float));
|
||||
ptcache_file_write(pf, &sds->base_res, 3, sizeof(int));
|
||||
ptcache_file_write(pf, &sds->res_min, 3, sizeof(int));
|
||||
ptcache_file_write(pf, &sds->res_max, 3, sizeof(int));
|
||||
ptcache_file_write(pf, &sds->active_color, 3, sizeof(float));
|
||||
|
||||
MEM_freeN(out);
|
||||
|
||||
@@ -579,7 +608,7 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
|
||||
int res_big_array[3];
|
||||
int res_big;
|
||||
int res = sds->res[0]*sds->res[1]*sds->res[2];
|
||||
float *dens, *densold, *tcu, *tcv, *tcw;
|
||||
float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
|
||||
unsigned int in_len = sizeof(float)*(unsigned int)res;
|
||||
unsigned int in_len_big;
|
||||
unsigned char *out;
|
||||
@@ -593,11 +622,20 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
|
||||
|
||||
in_len_big = sizeof(float) * (unsigned int)res_big;
|
||||
|
||||
smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
|
||||
smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
|
||||
|
||||
out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len_big, out, mode);
|
||||
if (fluid_fields & SM_ACTIVE_FIRE) {
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len_big, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len_big, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)react, in_len_big, out, mode);
|
||||
}
|
||||
if (fluid_fields & SM_ACTIVE_COLORS) {
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)r, in_len_big, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)g, in_len_big, out, mode);
|
||||
ptcache_file_compressed_write(pf, (unsigned char *)b, in_len_big, out, mode);
|
||||
}
|
||||
MEM_freeN(out);
|
||||
|
||||
out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
|
||||
@@ -615,34 +653,95 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
|
||||
{
|
||||
SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
char version[4];
|
||||
int ch_res[3];
|
||||
float ch_dx;
|
||||
int fluid_fields = smoke_get_data_flags(sds);
|
||||
int cache_fields = 0;
|
||||
int active_fields = 0;
|
||||
int reallocate = 0;
|
||||
|
||||
/* version header */
|
||||
ptcache_file_read(pf, version, 4, sizeof(char));
|
||||
if (strncmp(version, SMOKE_CACHE_VERSION, 4)) return 0;
|
||||
/* fluid info */
|
||||
ptcache_file_read(pf, &cache_fields, 1, sizeof(int));
|
||||
ptcache_file_read(pf, &active_fields, 1, sizeof(int));
|
||||
ptcache_file_read(pf, &ch_res, 3, sizeof(int));
|
||||
ptcache_file_read(pf, &ch_dx, 1, sizeof(float));
|
||||
|
||||
/* check if resolution has changed */
|
||||
if (sds->res[0] != ch_res[0] ||
|
||||
sds->res[1] != ch_res[1] ||
|
||||
sds->res[2] != ch_res[2]) {
|
||||
if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)
|
||||
reallocate = 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
/* check if active fields have changed */
|
||||
if (fluid_fields != cache_fields ||
|
||||
active_fields != sds->active_fields)
|
||||
reallocate = 1;
|
||||
|
||||
/* reallocate fluid if needed*/
|
||||
if (reallocate) {
|
||||
sds->active_fields = active_fields;
|
||||
smoke_reallocate_fluid(sds, ch_dx, ch_res, 1);
|
||||
sds->dx = ch_dx;
|
||||
VECCOPY(sds->res, ch_res);
|
||||
sds->total_cells = ch_res[0]*ch_res[1]*ch_res[2];
|
||||
if(sds->flags & MOD_SMOKE_HIGHRES) {
|
||||
smoke_reallocate_highres_fluid(sds, ch_dx, ch_res, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (sds->fluid) {
|
||||
size_t res = sds->res[0]*sds->res[1]*sds->res[2];
|
||||
float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold;
|
||||
float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
|
||||
unsigned char *obstacles;
|
||||
unsigned int out_len = (unsigned int)res * sizeof(float);
|
||||
|
||||
smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
|
||||
smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
|
||||
|
||||
ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len);
|
||||
if (cache_fields & SM_ACTIVE_HEAT) {
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len);
|
||||
}
|
||||
if (cache_fields & SM_ACTIVE_FIRE) {
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)flame, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)fuel, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)react, out_len);
|
||||
}
|
||||
if (cache_fields & SM_ACTIVE_COLORS) {
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)r, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)g, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)b, out_len);
|
||||
}
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)vxold, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)vyold, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)vzold, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res);
|
||||
ptcache_file_read(pf, &dt, 1, sizeof(float));
|
||||
ptcache_file_read(pf, &dx, 1, sizeof(float));
|
||||
ptcache_file_read(pf, &sds->p0, 3, sizeof(float));
|
||||
ptcache_file_read(pf, &sds->p1, 3, sizeof(float));
|
||||
ptcache_file_read(pf, &sds->dp0, 3, sizeof(float));
|
||||
ptcache_file_read(pf, &sds->shift, 3, sizeof(int));
|
||||
ptcache_file_read(pf, &sds->obj_shift_f, 3, sizeof(float));
|
||||
ptcache_file_read(pf, &sds->obmat, 16, sizeof(float));
|
||||
ptcache_file_read(pf, &sds->base_res, 3, sizeof(int));
|
||||
ptcache_file_read(pf, &sds->res_min, 3, sizeof(int));
|
||||
ptcache_file_read(pf, &sds->res_max, 3, sizeof(int));
|
||||
ptcache_file_read(pf, &sds->active_color, 3, sizeof(float));
|
||||
}
|
||||
|
||||
if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
|
||||
int res = sds->res[0]*sds->res[1]*sds->res[2];
|
||||
int res_big, res_big_array[3];
|
||||
float *dens, *densold, *tcu, *tcv, *tcw;
|
||||
float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
|
||||
unsigned int out_len = sizeof(float)*(unsigned int)res;
|
||||
unsigned int out_len_big;
|
||||
|
||||
@@ -650,16 +749,23 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
|
||||
res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
|
||||
out_len_big = sizeof(float) * (unsigned int)res_big;
|
||||
|
||||
smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
|
||||
smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
|
||||
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len_big);
|
||||
if (cache_fields & SM_ACTIVE_FIRE) {
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)flame, out_len_big);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)fuel, out_len_big);
|
||||
}
|
||||
if (cache_fields & SM_ACTIVE_COLORS) {
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)r, out_len_big);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)g, out_len_big);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)b, out_len_big);
|
||||
}
|
||||
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len);
|
||||
ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2466,10 +2572,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
|
||||
sbFreeSimulation(pid->calldata);
|
||||
else if (pid->type == PTCACHE_TYPE_PARTICLES)
|
||||
psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
|
||||
else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
|
||||
/*else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
|
||||
smokeModifier_reset(pid->calldata);
|
||||
else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES)
|
||||
smokeModifier_reset_turbulence(pid->calldata);
|
||||
smokeModifier_reset_turbulence(pid->calldata);*/
|
||||
else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT)
|
||||
dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -571,7 +571,7 @@ void default_mtex(MTex *mtex)
|
||||
mtex->size[1] = 1.0;
|
||||
mtex->size[2] = 1.0;
|
||||
mtex->tex = NULL;
|
||||
mtex->texflag = MTEX_3TAP_BUMP | MTEX_BUMP_OBJECTSPACE;
|
||||
mtex->texflag = MTEX_3TAP_BUMP | MTEX_BUMP_OBJECTSPACE | MTEX_MAPTO_BOUNDS;
|
||||
mtex->colormodel = 0;
|
||||
mtex->r = 1.0;
|
||||
mtex->g = 0.0;
|
||||
|
||||
@@ -67,6 +67,7 @@ MINLINE void copy_v2_v2_short(short r[2], const short a[2]);
|
||||
MINLINE void copy_v3_v3_short(short r[3], const short a[3]);
|
||||
MINLINE void copy_v4_v4_short(short r[4], const short a[4]);
|
||||
/* int */
|
||||
MINLINE void zero_v3_int(int r[3]);
|
||||
MINLINE void copy_v2_v2_int(int r[2], const int a[2]);
|
||||
MINLINE void copy_v3_v3_int(int r[3], const int a[3]);
|
||||
MINLINE void copy_v4_v4_int(int r[4], const int a[4]);
|
||||
|
||||
@@ -193,6 +193,11 @@
|
||||
*(v1 + 1) = *(v2 + 1) + *(v3 + 1) * (fac); \
|
||||
*(v1 + 2) = *(v2 + 2) + *(v3 + 2) * (fac); \
|
||||
} (void)0
|
||||
#define VECMADD(v1, v2, v3, v4) { \
|
||||
*(v1) = *(v2) + *(v3) * (*(v4)); \
|
||||
*(v1 + 1) = *(v2 + 1) + *(v3 + 1) * (*(v4 + 1)); \
|
||||
*(v1 + 2) = *(v2 + 2) + *(v3 + 2) * (*(v4 + 2)); \
|
||||
} (void)0
|
||||
#define VECSUBFAC(v1, v2, v3, fac) { \
|
||||
*(v1) = *(v2) - *(v3) * (fac); \
|
||||
*(v1 + 1) = *(v2 + 1) - *(v3 + 1) * (fac); \
|
||||
|
||||
@@ -121,6 +121,13 @@ MINLINE void copy_v4_v4_char(char r[4], const char a[4])
|
||||
}
|
||||
|
||||
/* short */
|
||||
MINLINE void zero_v3_int(int r[3])
|
||||
{
|
||||
r[0] = 0;
|
||||
r[1] = 0;
|
||||
r[2] = 0;
|
||||
}
|
||||
|
||||
MINLINE void copy_v2_v2_short(short r[2], const short a[2])
|
||||
{
|
||||
r[0] = a[0];
|
||||
|
||||
@@ -3335,6 +3335,8 @@ static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd)
|
||||
{
|
||||
if (pd && pd->tex)
|
||||
pd->tex = newlibadr_us(fd, id->lib, pd->tex);
|
||||
if (pd && pd->f_source)
|
||||
pd->f_source = newlibadr_us(fd, id->lib, pd->f_source);
|
||||
}
|
||||
|
||||
static void lib_link_particlesettings(FileData *fd, Main *main)
|
||||
@@ -4333,6 +4335,9 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
|
||||
smd->coll = NULL;
|
||||
smd->flow = newdataadr(fd, smd->flow);
|
||||
smd->flow->smd = smd;
|
||||
smd->flow->dm = NULL;
|
||||
smd->flow->verts_old = NULL;
|
||||
smd->flow->numverts = 0;
|
||||
smd->flow->psys = newdataadr(fd, smd->flow->psys);
|
||||
}
|
||||
else if (smd->type == MOD_SMOKE_TYPE_COLL) {
|
||||
@@ -4341,11 +4346,15 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
|
||||
smd->coll = newdataadr(fd, smd->coll);
|
||||
if (smd->coll) {
|
||||
smd->coll->smd = smd;
|
||||
smd->coll->points = NULL;
|
||||
smd->coll->numpoints = 0;
|
||||
smd->coll->verts_old = NULL;
|
||||
smd->coll->numverts = 0;
|
||||
smd->coll->dm = NULL;
|
||||
}
|
||||
else {
|
||||
smd->type = 0;
|
||||
smd->flow = NULL;
|
||||
smd->domain = NULL;
|
||||
smd->coll = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8038,6 +8047,44 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
|
||||
|
||||
{
|
||||
Object *ob;
|
||||
|
||||
for (ob = main->object.first; ob; ob = ob->id.next) {
|
||||
ModifierData *md;
|
||||
for (md = ob->modifiers.first; md; md = md->next) {
|
||||
if (md->type == eModifierType_Smoke) {
|
||||
SmokeModifierData *smd = (SmokeModifierData *)md;
|
||||
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
|
||||
/* keep branch saves if possible */
|
||||
if (!smd->domain->flame_max_temp) {
|
||||
smd->domain->burning_rate = 0.75f;
|
||||
smd->domain->flame_smoke = 1.0f;
|
||||
smd->domain->flame_vorticity = 0.5f;
|
||||
smd->domain->flame_ignition = 1.25f;
|
||||
smd->domain->flame_max_temp = 1.75f;
|
||||
smd->domain->adapt_threshold = 0.02f;
|
||||
smd->domain->adapt_margin = 4;
|
||||
smd->domain->flame_smoke_color[0] = 0.7f;
|
||||
smd->domain->flame_smoke_color[1] = 0.7f;
|
||||
smd->domain->flame_smoke_color[2] = 0.7f;
|
||||
}
|
||||
}
|
||||
else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
|
||||
if (!smd->flow->texture_size) {
|
||||
smd->flow->fuel_amount = 1.0;
|
||||
smd->flow->surface_distance = 1.5;
|
||||
smd->flow->color[0] = 0.7f;
|
||||
smd->flow->color[1] = 0.7f;
|
||||
smd->flow->color[2] = 0.7f;
|
||||
smd->flow->texture_size = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* don't forget to set version number in blender.c! */
|
||||
}
|
||||
|
||||
|
||||
@@ -450,8 +450,8 @@ DEF_ICON(FORCE_CURVE)
|
||||
DEF_ICON(FORCE_BOID)
|
||||
DEF_ICON(FORCE_TURBULENCE)
|
||||
DEF_ICON(FORCE_DRAG)
|
||||
DEF_ICON(FORCE_SMOKEFLOW)
|
||||
#ifndef DEF_ICON_BLANK_SKIP
|
||||
DEF_ICON(BLANK672)
|
||||
DEF_ICON(BLANK673)
|
||||
DEF_ICON(BLANK674)
|
||||
DEF_ICON(BLANK675)
|
||||
|
||||
@@ -136,6 +136,7 @@ static EnumPropertyItem field_type_items[] = {
|
||||
{PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""},
|
||||
{PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""},
|
||||
{PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""},
|
||||
{PFIELD_SMOKEFLOW, "SMOKE", ICON_FORCE_SMOKEFLOW, "Smoke Flow", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -356,7 +357,7 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *ob;
|
||||
|
||||
/* For as long scene has editmode... */
|
||||
/* for as long scene has editmode... */
|
||||
if (CTX_data_edit_object(C))
|
||||
ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
|
||||
|
||||
|
||||
@@ -6625,73 +6625,75 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
|
||||
}
|
||||
|
||||
/* only draw domains */
|
||||
if (smd->domain && smd->domain->fluid) {
|
||||
if (CFRA < smd->domain->point_cache[0]->startframe) {
|
||||
/* don't show smoke before simulation starts, this could be made an option in the future */
|
||||
}
|
||||
else if (!smd->domain->wt || !(smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
|
||||
// #if 0
|
||||
smd->domain->tex = NULL;
|
||||
GPU_create_smoke(smd, 0);
|
||||
draw_volume(ar, smd->domain->tex,
|
||||
smd->domain->p0, smd->domain->p1,
|
||||
smd->domain->res, smd->domain->dx,
|
||||
smd->domain->tex_shadow);
|
||||
GPU_free_smoke(smd);
|
||||
// #endif
|
||||
#if 0
|
||||
int x, y, z;
|
||||
float *density = smoke_get_density(smd->domain->fluid);
|
||||
if (smd->domain) {
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
float p0[3], p1[3], viewnormal[3];
|
||||
BoundBox bb;
|
||||
|
||||
glLoadMatrixf(rv3d->viewmat);
|
||||
// glMultMatrixf(ob->obmat);
|
||||
|
||||
if (col || (ob->flag & SELECT)) cpack(0xFFFFFF);
|
||||
glDepthMask(GL_FALSE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
|
||||
// glPointSize(3.0);
|
||||
bglBegin(GL_POINTS);
|
||||
|
||||
for (x = 0; x < smd->domain->res[0]; x++) {
|
||||
for (y = 0; y < smd->domain->res[1]; y++) {
|
||||
for (z = 0; z < smd->domain->res[2]; z++) {
|
||||
float tmp[3];
|
||||
int index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z);
|
||||
|
||||
if (density[index] > FLT_EPSILON) {
|
||||
float color[3];
|
||||
copy_v3_v3(tmp, smd->domain->p0);
|
||||
tmp[0] += smd->domain->dx * x + smd->domain->dx * 0.5;
|
||||
tmp[1] += smd->domain->dx * y + smd->domain->dx * 0.5;
|
||||
tmp[2] += smd->domain->dx * z + smd->domain->dx * 0.5;
|
||||
color[0] = color[1] = color[2] = density[index];
|
||||
glColor3fv(color);
|
||||
bglVertex3fv(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bglEnd();
|
||||
glPointSize(1.0);
|
||||
|
||||
glMultMatrixf(ob->obmat);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
if (col) cpack(col);
|
||||
#endif
|
||||
|
||||
/* draw adaptive domain bounds */
|
||||
if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
|
||||
/* draw domain max bounds */
|
||||
VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res);
|
||||
VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res);
|
||||
BKE_boundbox_init_from_minmax(&bb, p0, p1);
|
||||
draw_box(bb.vec);
|
||||
|
||||
/* draw base resolution bounds */
|
||||
/*BKE_boundbox_init_from_minmax(&bb, sds->p0, sds->p1);
|
||||
draw_box(bb.vec);*/
|
||||
}
|
||||
else if (smd->domain->wt && (smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
|
||||
|
||||
/* don't show smoke before simulation starts, this could be made an option in the future */
|
||||
if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) {
|
||||
|
||||
// get view vector
|
||||
copy_v3_v3(viewnormal, rv3d->viewinv[2]);
|
||||
mul_mat3_m4_v3(ob->imat, viewnormal);
|
||||
normalize_v3(viewnormal);
|
||||
|
||||
/* set dynamic boundaries to draw the volume */
|
||||
p0[0] = sds->p0[0] + sds->cell_size[0]*sds->res_min[0] + sds->obj_shift_f[0];
|
||||
p0[1] = sds->p0[1] + sds->cell_size[1]*sds->res_min[1] + sds->obj_shift_f[1];
|
||||
p0[2] = sds->p0[2] + sds->cell_size[2]*sds->res_min[2] + sds->obj_shift_f[2];
|
||||
p1[0] = sds->p0[0] + sds->cell_size[0]*sds->res_max[0] + sds->obj_shift_f[0];
|
||||
p1[1] = sds->p0[1] + sds->cell_size[1]*sds->res_max[1] + sds->obj_shift_f[1];
|
||||
p1[2] = sds->p0[2] + sds->cell_size[2]*sds->res_max[2] + sds->obj_shift_f[2];
|
||||
|
||||
/* scale cube to global space to equalize volume slicing on all axises
|
||||
* (its scaled back before drawing) */
|
||||
mul_v3_v3(p0, ob->size);
|
||||
mul_v3_v3(p1, ob->size);
|
||||
|
||||
if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
|
||||
smd->domain->tex = NULL;
|
||||
GPU_create_smoke(smd, 1);
|
||||
draw_volume(ar, smd->domain->tex,
|
||||
smd->domain->p0, smd->domain->p1,
|
||||
smd->domain->res_wt, smd->domain->dx_wt,
|
||||
smd->domain->tex_shadow);
|
||||
GPU_create_smoke(smd, 0);
|
||||
draw_smoke_volume(sds, ob, ar, sds->tex,
|
||||
p0, p1,
|
||||
sds->res, sds->dx, sds->scale*sds->maxres,
|
||||
viewnormal, sds->tex_shadow, sds->tex_flame);
|
||||
GPU_free_smoke(smd);
|
||||
}
|
||||
else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
|
||||
sds->tex = NULL;
|
||||
GPU_create_smoke(smd, 1);
|
||||
draw_smoke_volume(sds, ob, ar, sds->tex,
|
||||
p0, p1,
|
||||
sds->res_wt, sds->dx, sds->scale*sds->maxres,
|
||||
viewnormal, sds->tex_shadow, sds->tex_flame);
|
||||
GPU_free_smoke(smd);
|
||||
}
|
||||
|
||||
/* smoke debug render */
|
||||
#ifdef SMOKE_DEBUG_VELOCITY
|
||||
draw_smoke_velocity(smd->domain, ob);
|
||||
#endif
|
||||
#ifdef SMOKE_DEBUG_HEAT
|
||||
draw_smoke_heat(smd->domain, ob);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_smoke_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
@@ -156,12 +157,9 @@ static int convex(const float p0[3], const float up[3], const float a[3], const
|
||||
return dot_v3v3(up, tmp) >= 0;
|
||||
}
|
||||
|
||||
void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int res[3], float dx, GPUTexture *tex_shadow)
|
||||
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, ARegion *ar, GPUTexture *tex, float min[3], float max[3], int res[3], float dx, float base_scale, float viewnormal[3], GPUTexture *tex_shadow, GPUTexture *tex_flame)
|
||||
{
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
float viewnormal[3];
|
||||
int i, j, n, good_index;
|
||||
int i, j, k, n, good_index;
|
||||
float d /*, d0 */ /* UNUSED */, dd, ds;
|
||||
float *points = NULL;
|
||||
int numpoints = 0;
|
||||
@@ -193,24 +191,72 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
|
||||
};
|
||||
|
||||
unsigned char *spec_data;
|
||||
float *spec_pixels;
|
||||
GPUTexture *tex_spec;
|
||||
|
||||
/* Fragment program to calculate the view3d of smoke */
|
||||
/* using 2 textures, density and shadow */
|
||||
const char *text = "!!ARBfp1.0\n"
|
||||
/* using 4 textures, density, shadow, flame and flame spectrum */
|
||||
const char *shader_basic = "!!ARBfp1.0\n"
|
||||
"PARAM dx = program.local[0];\n"
|
||||
"PARAM darkness = program.local[1];\n"
|
||||
"PARAM render = program.local[2];\n"
|
||||
"PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
|
||||
"TEMP temp, shadow, value;\n"
|
||||
"TEMP temp, shadow, flame, spec, value;\n"
|
||||
"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
|
||||
"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
|
||||
"MUL value, temp, darkness;\n"
|
||||
"MUL value, value, dx;\n"
|
||||
"MUL value, value, f;\n"
|
||||
"TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
|
||||
"TEX spec, flame.r, texture[3], 1D;\n"
|
||||
/* calculate shading factor from density */
|
||||
"MUL value.r, temp.a, darkness.a;\n"
|
||||
"MUL value.r, value.r, dx.r;\n"
|
||||
"MUL value.r, value.r, f.r;\n"
|
||||
"EX2 temp, -value.r;\n"
|
||||
/* alpha */
|
||||
"SUB temp.a, 1.0, temp.r;\n"
|
||||
/* shade colors */
|
||||
"MUL temp.r, temp.r, shadow.r;\n"
|
||||
"MUL temp.g, temp.g, shadow.r;\n"
|
||||
"MUL temp.b, temp.b, shadow.r;\n"
|
||||
"MOV result.color, temp;\n"
|
||||
"MUL temp.r, temp.r, darkness.r;\n"
|
||||
"MUL temp.g, temp.g, darkness.g;\n"
|
||||
"MUL temp.b, temp.b, darkness.b;\n"
|
||||
/* for now this just replace smoke shading if rendering fire */
|
||||
"CMP result.color, render.r, temp, spec;\n"
|
||||
"END\n";
|
||||
|
||||
/* color shader */
|
||||
const char *shader_color = "!!ARBfp1.0\n"
|
||||
"PARAM dx = program.local[0];\n"
|
||||
"PARAM darkness = program.local[1];\n"
|
||||
"PARAM render = program.local[2];\n"
|
||||
"PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n"
|
||||
"TEMP temp, shadow, flame, spec, value;\n"
|
||||
"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
|
||||
"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
|
||||
"TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
|
||||
"TEX spec, flame.r, texture[3], 1D;\n"
|
||||
/* unpremultiply volume texture */
|
||||
"RCP value.r, temp.a;\n"
|
||||
"MUL temp.r, temp.r, value.r;\n"
|
||||
"MUL temp.g, temp.g, value.r;\n"
|
||||
"MUL temp.b, temp.b, value.r;\n"
|
||||
/* calculate shading factor from density */
|
||||
"MUL value.r, temp.a, darkness.a;\n"
|
||||
"MUL value.r, value.r, dx.r;\n"
|
||||
"MUL value.r, value.r, f.r;\n"
|
||||
"EX2 value.r, -value.r;\n"
|
||||
/* alpha */
|
||||
"SUB temp.a, 1.0, value.r;\n"
|
||||
/* shade colors */
|
||||
"MUL temp.r, temp.r, shadow.r;\n"
|
||||
"MUL temp.g, temp.g, shadow.r;\n"
|
||||
"MUL temp.b, temp.b, shadow.r;\n"
|
||||
"MUL temp.r, temp.r, value.r;\n"
|
||||
"MUL temp.g, temp.g, value.r;\n"
|
||||
"MUL temp.b, temp.b, value.r;\n"
|
||||
/* for now this just replace smoke shading if rendering fire */
|
||||
"CMP result.color, render.r, temp, spec;\n"
|
||||
"END\n";
|
||||
GLuint prog;
|
||||
|
||||
@@ -223,6 +269,32 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
}
|
||||
|
||||
tstart();
|
||||
/* generate flame spectrum texture */
|
||||
#define SPEC_WIDTH 256
|
||||
#define FIRE_THRESH 7
|
||||
#define MAX_FIRE_ALPHA 0.06f
|
||||
#define FULL_ON_FIRE 100
|
||||
spec_data = malloc(SPEC_WIDTH*4 * sizeof(unsigned char));
|
||||
flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000);
|
||||
spec_pixels = malloc(SPEC_WIDTH*4*16*16 * sizeof(float));
|
||||
for (i=0;i<16;i++){
|
||||
for (j=0;j<16;j++) {
|
||||
for (k=0;k<SPEC_WIDTH;k++) {
|
||||
int index = (j*SPEC_WIDTH*16+i*SPEC_WIDTH+k)*4;
|
||||
if (k>=FIRE_THRESH) {
|
||||
spec_pixels[index] = ((float)spec_data[k*4])/255.0f;
|
||||
spec_pixels[index+1] = ((float)spec_data[k*4+1])/255.0f;
|
||||
spec_pixels[index+2] = ((float)spec_data[k*4+2])/255.0f;
|
||||
spec_pixels[index+3] = MAX_FIRE_ALPHA*(
|
||||
(k>FULL_ON_FIRE) ? 1.0f : (k-FIRE_THRESH)/((float)FULL_ON_FIRE-FIRE_THRESH));
|
||||
} else {
|
||||
spec_pixels[index] = spec_pixels[index+1] = spec_pixels[index+2] = spec_pixels[index+3] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
|
||||
|
||||
sub_v3_v3v3(size, max, min);
|
||||
|
||||
@@ -296,24 +368,9 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
|
||||
glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
|
||||
|
||||
glLoadMatrixf(rv3d->viewmat);
|
||||
// glMultMatrixf(ob->obmat);
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
#if 0
|
||||
printf("Viewinv:\n");
|
||||
printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]);
|
||||
printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]);
|
||||
printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]);
|
||||
#endif
|
||||
|
||||
/* get view vector */
|
||||
copy_v3_v3(viewnormal, rv3d->viewinv[2]);
|
||||
normalize_v3(viewnormal);
|
||||
|
||||
/* find cube vertex that is closest to the viewer */
|
||||
for (i = 0; i < 8; i++) {
|
||||
@@ -344,12 +401,19 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
glGenProgramsARB(1, &prog);
|
||||
|
||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
|
||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text);
|
||||
/* set shader */
|
||||
if (sds->active_fields & SM_ACTIVE_COLORS)
|
||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color);
|
||||
else
|
||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic);
|
||||
|
||||
/* cell spacing */
|
||||
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
|
||||
/* custom parameter for smoke style (higher = thicker) */
|
||||
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0);
|
||||
if (sds->active_fields & SM_ACTIVE_COLORS)
|
||||
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0);
|
||||
else
|
||||
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
|
||||
}
|
||||
else
|
||||
printf("Your gfx card does not support 3D View smoke drawing.\n");
|
||||
@@ -360,6 +424,11 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
else
|
||||
printf("No volume shadow\n");
|
||||
|
||||
if (tex_flame) {
|
||||
GPU_texture_bind(tex_flame, 2);
|
||||
GPU_texture_bind(tex_spec, 3);
|
||||
}
|
||||
|
||||
if (!GPU_non_power_of_two_support()) {
|
||||
cor[0] = (float)res[0] / (float)power_of_2_max_i(res[0]);
|
||||
cor[1] = (float)res[1] / (float)power_of_2_max_i(res[1]);
|
||||
@@ -373,7 +442,7 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
|
||||
/* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
|
||||
ds = (ABS(viewnormal[0]) * size[0] + ABS(viewnormal[1]) * size[1] + ABS(viewnormal[2]) * size[2]);
|
||||
dd = ds / 96.f;
|
||||
dd = MAX3(sds->global_size[0],sds->global_size[1],sds->global_size[2])/128.f;
|
||||
n = 0;
|
||||
good_index = i;
|
||||
|
||||
@@ -416,14 +485,29 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
}
|
||||
}
|
||||
|
||||
// printf("numpoints: %d\n", numpoints);
|
||||
/* render fire slice */
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0);
|
||||
glBegin(GL_POLYGON);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
for (i = 0; i < numpoints; i++) {
|
||||
glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
|
||||
(points[i * 3 + 1] - min[1]) * cor[1] / size[1],
|
||||
(points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
|
||||
glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]);
|
||||
glVertex3f(points[i * 3 + 0]/ob->size[0], points[i * 3 + 1]/ob->size[1], points[i * 3 + 2]/ob->size[2]);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* render smoke slice */
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0);
|
||||
glBegin(GL_POLYGON);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
for (i = 0; i < numpoints; i++) {
|
||||
glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
|
||||
(points[i * 3 + 1] - min[1]) * cor[1] / size[1],
|
||||
(points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
|
||||
glVertex3f(points[i * 3 + 0]/ob->size[0], points[i * 3 + 1]/ob->size[1], points[i * 3 + 2]/ob->size[2]);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
@@ -436,6 +520,14 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
if (tex_shadow)
|
||||
GPU_texture_unbind(tex_shadow);
|
||||
GPU_texture_unbind(tex);
|
||||
if (tex_flame) {
|
||||
GPU_texture_unbind(tex_flame);
|
||||
GPU_texture_unbind(tex_spec);
|
||||
}
|
||||
GPU_texture_free(tex_spec);
|
||||
|
||||
free(spec_data);
|
||||
free(spec_pixels);
|
||||
|
||||
if (GLEW_ARB_fragment_program) {
|
||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
@@ -454,3 +546,106 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SMOKE_DEBUG_VELOCITY
|
||||
void draw_smoke_velocity(SmokeDomainSettings *domain, Object *ob)
|
||||
{
|
||||
float x,y,z;
|
||||
float x0,y0,z0;
|
||||
int *base_res = domain->base_res;
|
||||
int *res = domain->res;
|
||||
int *res_min = domain->res_min;
|
||||
int *res_max = domain->res_max;
|
||||
float *vel_x = smoke_get_velocity_x(domain->fluid);
|
||||
float *vel_y = smoke_get_velocity_y(domain->fluid);
|
||||
float *vel_z = smoke_get_velocity_z(domain->fluid);
|
||||
|
||||
float min[3];
|
||||
float *cell_size = domain->cell_size;
|
||||
float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2]))/16.f;
|
||||
float vf = domain->scale / 16.f * 2.f; /* velocity factor */
|
||||
|
||||
glLineWidth(1.0f);
|
||||
|
||||
/* set first position so that it doesn't jump when domain moves */
|
||||
x0 = res_min[0] + fmod(-(float)domain->shift[0]+res_min[0],step_size);
|
||||
y0 = res_min[1] + fmod(-(float)domain->shift[1]+res_min[1],step_size);
|
||||
z0 = res_min[2] + fmod(-(float)domain->shift[2]+res_min[2],step_size);
|
||||
if (x0<res_min[0]) x0+=step_size;
|
||||
if (y0<res_min[1]) y0+=step_size;
|
||||
if (z0<res_min[2]) z0+=step_size;
|
||||
add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
|
||||
|
||||
for (x=floor(x0); x<res_max[0]; x+=step_size)
|
||||
for (y=floor(y0); y<res_max[1]; y+=step_size)
|
||||
for (z=floor(z0); z<res_max[2]; z+=step_size) {
|
||||
int index = (floor(x)-res_min[0]) + (floor(y)-res_min[1])*res[0] + (floor(z)-res_min[2])*res[0]*res[1];
|
||||
|
||||
float pos[3] = {min[0]+((float)x + 0.5f)*cell_size[0], min[1]+((float)y + 0.5f)*cell_size[1], min[2]+((float)z + 0.5f)*cell_size[2]};
|
||||
float vel = sqrtf(vel_x[index]*vel_x[index] + vel_y[index]*vel_y[index] + vel_z[index]*vel_z[index]);
|
||||
|
||||
/* draw heat as scaled "arrows" */
|
||||
if (vel >= 0.01f) {
|
||||
float col_g = 1.0f - vel;
|
||||
CLAMP(col_g, 0.0f, 1.0f);
|
||||
glColor3f(1.0f, col_g, 0.0f);
|
||||
glPointSize(10.0f * vel);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(pos[0], pos[1], pos[2]);
|
||||
glVertex3f(pos[0]+vel_x[index]*vf, pos[1]+vel_y[index]*vf, pos[2]+vel_z[index]*vf);
|
||||
glEnd();
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3f(pos[0]+vel_x[index]*vf, pos[1]+vel_y[index]*vf, pos[2]+vel_z[index]*vf);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SMOKE_DEBUG_HEAT
|
||||
void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob)
|
||||
{
|
||||
float x,y,z;
|
||||
float x0,y0,z0;
|
||||
int *base_res = domain->base_res;
|
||||
int *res = domain->res;
|
||||
int *res_min = domain->res_min;
|
||||
int *res_max = domain->res_max;
|
||||
float *heat = smoke_get_heat(domain->fluid);
|
||||
|
||||
float min[3];
|
||||
float *cell_size = domain->cell_size;
|
||||
float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2]))/16.f;
|
||||
float vf = domain->scale / 16.f * 2.f; /* velocity factor */
|
||||
|
||||
/* set first position so that it doesn't jump when domain moves */
|
||||
x0 = res_min[0] + fmod(-(float)domain->shift[0]+res_min[0],step_size);
|
||||
y0 = res_min[1] + fmod(-(float)domain->shift[1]+res_min[1],step_size);
|
||||
z0 = res_min[2] + fmod(-(float)domain->shift[2]+res_min[2],step_size);
|
||||
if (x0<res_min[0]) x0+=step_size;
|
||||
if (y0<res_min[1]) y0+=step_size;
|
||||
if (z0<res_min[2]) z0+=step_size;
|
||||
add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
|
||||
|
||||
for (x=floor(x0); x<res_max[0]; x+=step_size)
|
||||
for (y=floor(y0); y<res_max[1]; y+=step_size)
|
||||
for (z=floor(z0); z<res_max[2]; z+=step_size) {
|
||||
int index = (floor(x)-res_min[0]) + (floor(y)-res_min[1])*res[0] + (floor(z)-res_min[2])*res[0]*res[1];
|
||||
|
||||
float pos[3] = {min[0]+((float)x + 0.5f)*cell_size[0], min[1]+((float)y + 0.5f)*cell_size[1], min[2]+((float)z + 0.5f)*cell_size[2]};
|
||||
|
||||
/* draw heat as different sized points */
|
||||
if (heat[index] >= 0.01f) {
|
||||
float col_gb = 1.0f - heat[index];
|
||||
CLAMP(col_gb, 0.0f, 1.0f);
|
||||
glColor3f(1.0f, col_gb, col_gb);
|
||||
glPointSize(24.0f * heat[index]);
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3f(pos[0], pos[1], pos[2]);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -212,7 +212,16 @@ ARegion *view3d_has_tools_region(ScrArea *sa);
|
||||
extern const char *view3d_context_dir[]; /* doc access */
|
||||
|
||||
/* draw_volume.c */
|
||||
void draw_volume(struct ARegion *ar, struct GPUTexture *tex, float min[3], float max[3], int res[3], float dx, struct GPUTexture *tex_shadow);
|
||||
void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob, struct ARegion *ar, struct GPUTexture *tex, float min[3], float max[3], int res[3], float dx, float base_scale, float viewnormal[3], struct GPUTexture *tex_shadow, struct GPUTexture *tex_flame);
|
||||
//#define SMOKE_DEBUG_VELOCITY
|
||||
//#define SMOKE_DEBUG_HEAT
|
||||
|
||||
#ifdef SMOKE_DEBUG_VELOCITY
|
||||
void draw_smoke_velocity(struct SmokeDomainSettings *domain, struct Object *ob);
|
||||
#endif
|
||||
#ifdef SMOKE_DEBUG_HEAT
|
||||
void draw_smoke_heat(struct SmokeDomainSettings *domain, struct Object *ob);
|
||||
#endif
|
||||
|
||||
/* workaround for trivial but noticeable camera bug caused by imprecision
|
||||
* between view border calculation in 2D/3D space, workaround for bug [#28037].
|
||||
|
||||
@@ -107,7 +107,7 @@ int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
|
||||
|
||||
GPUTexture *GPU_texture_create_1D(int w, float *pixels, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels);
|
||||
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels);
|
||||
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
|
||||
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
|
||||
GPUTexture *GPU_texture_from_blender(struct Image *ima,
|
||||
|
||||
@@ -1019,21 +1019,53 @@ void GPU_free_smoke(SmokeModifierData *smd)
|
||||
if (smd->domain->tex_shadow)
|
||||
GPU_texture_free(smd->domain->tex_shadow);
|
||||
smd->domain->tex_shadow = NULL;
|
||||
|
||||
if (smd->domain->tex_flame)
|
||||
GPU_texture_free(smd->domain->tex_flame);
|
||||
smd->domain->tex_flame = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_create_smoke(SmokeModifierData *smd, int highres)
|
||||
{
|
||||
#ifdef WITH_SMOKE
|
||||
if (smd->type & MOD_SMOKE_TYPE_DOMAIN && !smd->domain->tex && !highres)
|
||||
smd->domain->tex = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smoke_get_density(smd->domain->fluid));
|
||||
else if (smd->type & MOD_SMOKE_TYPE_DOMAIN && !smd->domain->tex && highres)
|
||||
smd->domain->tex = GPU_texture_create_3D(smd->domain->res_wt[0], smd->domain->res_wt[1], smd->domain->res_wt[2], smoke_turbulence_get_density(smd->domain->wt));
|
||||
if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
if (!sds->tex && !highres) {
|
||||
/* rgba texture for color + density */
|
||||
if (smoke_has_colors(sds->fluid)) {
|
||||
float *data = MEM_callocN(sizeof(float)*sds->total_cells*4, "smokeColorTexture");
|
||||
smoke_get_rgba(sds->fluid, data, 0);
|
||||
sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data);
|
||||
MEM_freeN(data);
|
||||
}
|
||||
/* density only */
|
||||
else {
|
||||
sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_density(sds->fluid));
|
||||
}
|
||||
sds->tex_flame = (smoke_has_fuel(sds->fluid)) ? GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_flame(sds->fluid)) : NULL;
|
||||
}
|
||||
else if (!sds->tex && highres) {
|
||||
/* rgba texture for color + density */
|
||||
if (smoke_turbulence_has_colors(sds->wt)) {
|
||||
float *data = MEM_callocN(sizeof(float)*smoke_turbulence_get_cells(sds->wt)*4, "smokeColorTexture");
|
||||
smoke_turbulence_get_rgba(sds->wt, data, 0);
|
||||
sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data);
|
||||
MEM_freeN(data);
|
||||
}
|
||||
/* density only */
|
||||
else {
|
||||
sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_density(sds->wt));
|
||||
}
|
||||
sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ? GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_flame(sds->wt)) : NULL;
|
||||
}
|
||||
|
||||
smd->domain->tex_shadow = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smd->domain->shadow);
|
||||
sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, sds->shadow);
|
||||
}
|
||||
#else // WITH_SMOKE
|
||||
(void)highres;
|
||||
smd->domain->tex= NULL;
|
||||
smd->domain->tex_flame= NULL;
|
||||
smd->domain->tex_shadow= NULL;
|
||||
#endif // WITH_SMOKE
|
||||
}
|
||||
|
||||
@@ -442,7 +442,7 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
|
||||
}
|
||||
|
||||
|
||||
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels)
|
||||
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels)
|
||||
{
|
||||
GPUTexture *tex;
|
||||
GLenum type, format, internalformat;
|
||||
@@ -480,9 +480,15 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels)
|
||||
|
||||
GPU_print_error("3D glBindTexture");
|
||||
|
||||
type = GL_FLOAT; // GL_UNSIGNED_BYTE
|
||||
type = GL_FLOAT;
|
||||
if (channels == 4) {
|
||||
format = GL_RGBA;
|
||||
internalformat = GL_RGBA;
|
||||
}
|
||||
else {
|
||||
format = GL_RED;
|
||||
internalformat = GL_INTENSITY;
|
||||
}
|
||||
|
||||
//if (fpixels)
|
||||
// pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
|
||||
|
||||
@@ -54,6 +54,7 @@ typedef enum PFieldType {
|
||||
PFIELD_BOID = 10, /* Defines predator / goal for boids */
|
||||
PFIELD_TURBULENCE = 11, /* Force defined by BLI_gTurbulence */
|
||||
PFIELD_DRAG = 12, /* Linear & quadratic drag */
|
||||
PFIELD_SMOKEFLOW = 13, /* Force based on smoke simulation air flow */
|
||||
NUM_PFIELD_TYPES
|
||||
} PFieldType;
|
||||
|
||||
@@ -110,14 +111,17 @@ typedef struct PartDeflect {
|
||||
struct RNG *rng; /* random noise generator for e.g. wind */
|
||||
float f_noise; /* noise of force */
|
||||
int seed; /* noise random seed */
|
||||
|
||||
struct Object *f_source; /* force source object */
|
||||
} PartDeflect;
|
||||
|
||||
typedef struct EffectorWeights {
|
||||
struct Group *group; /* only use effectors from this group of objects */
|
||||
|
||||
float weight[13]; /* effector type specific weights */
|
||||
float weight[14]; /* effector type specific weights */
|
||||
float global_gravity;
|
||||
short flag, rt[3];
|
||||
int pad;
|
||||
} EffectorWeights;
|
||||
|
||||
/* EffectorWeights->flag */
|
||||
@@ -365,6 +369,7 @@ typedef struct SoftBody {
|
||||
#define PFIELD_DO_LOCATION (1<<14)
|
||||
#define PFIELD_DO_ROTATION (1<<15)
|
||||
#define PFIELD_GUIDE_PATH_WEIGHT (1<<16) /* apply curve weights */
|
||||
#define PFIELD_SMOKE_DENSITY (1<<17) /* multiply smoke force by density */
|
||||
|
||||
/* pd->falloff */
|
||||
#define PFIELD_FALL_SPHERE 0
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#define MOD_SMOKE_HIGH_SMOOTH (1<<5) /* smoothens high res emission*/
|
||||
#define MOD_SMOKE_FILE_LOAD (1<<6) /* flag for file load */
|
||||
#define MOD_SMOKE_ADAPTIVE_DOMAIN (1<<7)
|
||||
|
||||
/* noise */
|
||||
#define MOD_SMOKE_NOISEWAVE (1<<0)
|
||||
@@ -61,6 +62,12 @@
|
||||
#define SM_COLL_RIGID 1
|
||||
#define SM_COLL_ANIMATED 2
|
||||
|
||||
/* smoke data fileds (active_fields) */
|
||||
#define SM_ACTIVE_HEAT (1<<0)
|
||||
#define SM_ACTIVE_FIRE (1<<1)
|
||||
#define SM_ACTIVE_COLORS (1<<2)
|
||||
#define SM_ACTIVE_COLOR_SET (1<<3)
|
||||
|
||||
typedef struct SmokeDomainSettings {
|
||||
struct SmokeModifierData *smd; /* for fast RNA access */
|
||||
struct FLUID_3D *fluid;
|
||||
@@ -71,17 +78,37 @@ typedef struct SmokeDomainSettings {
|
||||
struct GPUTexture *tex;
|
||||
struct GPUTexture *tex_wt;
|
||||
struct GPUTexture *tex_shadow;
|
||||
struct GPUTexture *tex_flame;
|
||||
float *shadow;
|
||||
float p0[3]; /* start point of BB */
|
||||
float p1[3]; /* end point of BB */
|
||||
float dx; /* edge length of one cell */
|
||||
float omega; /* smoke color - from 0 to 1 */
|
||||
float temp; /* fluid temperature */
|
||||
float tempAmb; /* ambient temperature */
|
||||
|
||||
/* simulation data */
|
||||
float p0[3]; /* start point of BB in local space (includes sub-cell shift for adaptive domain)*/
|
||||
float p1[3]; /* end point of BB in local space */
|
||||
float dp0[3]; /* difference from object center to grid start point */
|
||||
float cell_size[3]; /* size of simulation cell in local space */
|
||||
float global_size[3]; /* global size of domain axises */
|
||||
float prev_loc[3];
|
||||
int shift[3]; /* current domain shift in simulation cells */
|
||||
float shift_f[3]; /* exact domain shift */
|
||||
float obj_shift_f[3]; /* how much object has shifted since previous smoke frame (used to "lock" domain while drawing) */
|
||||
float imat[4][4]; /* domain object imat */
|
||||
float obmat[4][4]; /* domain obmat */
|
||||
|
||||
int base_res[3]; /* initial "non-adapted" resolution */
|
||||
int res_min[3]; /* cell min */
|
||||
int res_max[3]; /* cell max */
|
||||
int res[3]; /* data resolution (res_max-res_min) */
|
||||
int total_cells;
|
||||
float dx; /* 1.0f / res */
|
||||
float scale; /* largest domain size */
|
||||
|
||||
/* user settings */
|
||||
int adapt_margin;
|
||||
int adapt_res;
|
||||
float adapt_threshold;
|
||||
|
||||
float alpha;
|
||||
float beta;
|
||||
float scale; /* largest domain size */
|
||||
int res[3]; /* domain resolution */
|
||||
int amplify; /* wavelet amplification */
|
||||
int maxres; /* longest axis on the BB gets this resolution assigned */
|
||||
int flags; /* show up-res or low res, etc */
|
||||
@@ -92,7 +119,6 @@ typedef struct SmokeDomainSettings {
|
||||
float strength;
|
||||
int res_wt[3];
|
||||
float dx_wt;
|
||||
int v3dnum;
|
||||
int cache_comp;
|
||||
int cache_high_comp;
|
||||
|
||||
@@ -103,31 +129,67 @@ typedef struct SmokeDomainSettings {
|
||||
int border_collisions; /* How domain border collisions are handled */
|
||||
float time_scale;
|
||||
float vorticity;
|
||||
int pad2;
|
||||
int active_fields;
|
||||
float active_color[3]; /* monitor color situation of simulation */
|
||||
int pad;
|
||||
|
||||
/* flame parameters */
|
||||
float burning_rate, flame_smoke, flame_vorticity;
|
||||
float flame_ignition, flame_max_temp;
|
||||
float flame_smoke_color[3];
|
||||
} SmokeDomainSettings;
|
||||
|
||||
|
||||
/* inflow / outflow */
|
||||
|
||||
/* type */
|
||||
#define MOD_SMOKE_FLOW_TYPE_OUTFLOW (1<<1)
|
||||
#define MOD_SMOKE_FLOW_TYPE_SMOKE 0
|
||||
#define MOD_SMOKE_FLOW_TYPE_FIRE 1
|
||||
#define MOD_SMOKE_FLOW_TYPE_OUTFLOW 2
|
||||
#define MOD_SMOKE_FLOW_TYPE_SMOKEFIRE 3
|
||||
|
||||
/* flow source */
|
||||
#define MOD_SMOKE_FLOW_SOURCE_PARTICLES 0
|
||||
#define MOD_SMOKE_FLOW_SOURCE_MESH 1
|
||||
|
||||
/* flow texture type */
|
||||
#define MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO 0
|
||||
#define MOD_SMOKE_FLOW_TEXTURE_MAP_UV 1
|
||||
|
||||
/* flags */
|
||||
#define MOD_SMOKE_FLOW_ABSOLUTE (1<<1) /*old style emission*/
|
||||
#define MOD_SMOKE_FLOW_INITVELOCITY (1<<2) /* passes particles speed to the smoke */
|
||||
#define MOD_SMOKE_FLOW_TEXTUREEMIT (1<<3) /* use texture to control emission speed */
|
||||
|
||||
typedef struct SmokeFlowSettings {
|
||||
struct SmokeModifierData *smd; /* for fast RNA access */
|
||||
struct DerivedMesh *dm;
|
||||
struct ParticleSystem *psys;
|
||||
struct Tex *noise_texture;
|
||||
|
||||
/* initial velocity */
|
||||
float *verts_old; /* previous vertex positions in domain space */
|
||||
int numverts;
|
||||
float vel_multi; // Multiplier for inherited velocity
|
||||
float vel_normal;
|
||||
float vel_random;
|
||||
/* emission */
|
||||
float density;
|
||||
float color[3];
|
||||
float fuel_amount;
|
||||
float temp; /* delta temperature (temp - ambient temp) */
|
||||
float velocity[2]; /* UNUSED, velocity taken from particles */
|
||||
float vel_multi; // Multiplier for particle velocity
|
||||
float vgrp_heat_scale[2]; /* min and max scaling for vgroup_heat */
|
||||
short vgroup_flow; /* where inflow/outflow happens - red=1=action */
|
||||
float volume_density; /* density emitted within mesh volume */
|
||||
float surface_distance; /* maximum emission distance from mesh surface */
|
||||
/* texture control */
|
||||
float texture_size;
|
||||
float texture_offset;
|
||||
int pad;
|
||||
char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
|
||||
short vgroup_density;
|
||||
short vgroup_heat;
|
||||
short type; /* inflow =0 or outflow = 1 */
|
||||
|
||||
short type; /* smoke, flames, both, outflow */
|
||||
short source;
|
||||
short texture_type;
|
||||
int flags; /* absolute emission etc*/
|
||||
} SmokeFlowSettings;
|
||||
|
||||
@@ -139,20 +201,11 @@ typedef struct SmokeFlowSettings {
|
||||
/* collision objects (filled with smoke) */
|
||||
typedef struct SmokeCollSettings {
|
||||
struct SmokeModifierData *smd; /* for fast RNA access */
|
||||
struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
|
||||
float *points;
|
||||
float *points_old;
|
||||
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) */
|
||||
struct DerivedMesh *dm;
|
||||
float *verts_old;
|
||||
int numverts;
|
||||
short type; // static = 0, rigid = 1, dynamic = 2
|
||||
short pad;
|
||||
int pad2;
|
||||
} SmokeCollSettings;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -171,6 +171,9 @@ typedef struct VoxelData {
|
||||
short flag;
|
||||
short extend;
|
||||
short smoked_type;
|
||||
short data_type;
|
||||
short pad;
|
||||
int _pad;
|
||||
|
||||
struct Object *object; /* for rendering smoke sims */
|
||||
float int_multiplier;
|
||||
@@ -470,6 +473,7 @@ typedef struct ColorMapping {
|
||||
#define MTEX_BUMP_TEXTURESPACE 2048
|
||||
/* #define MTEX_BUMP_FLIPPED 4096 */ /* UNUSED */
|
||||
#define MTEX_BICUBIC_BUMP 8192
|
||||
#define MTEX_MAPTO_BOUNDS 16384
|
||||
|
||||
/* blendtype */
|
||||
#define MTEX_BLEND 0
|
||||
@@ -577,6 +581,11 @@ typedef struct ColorMapping {
|
||||
#define TEX_VD_SMOKEDENSITY 0
|
||||
#define TEX_VD_SMOKEHEAT 1
|
||||
#define TEX_VD_SMOKEVEL 2
|
||||
#define TEX_VD_SMOKEFLAME 3
|
||||
|
||||
/* data_type */
|
||||
#define TEX_VD_INTENSITY 0
|
||||
#define TEX_VD_RGBA_PREMUL 1
|
||||
|
||||
/******************** Ocean *****************************/
|
||||
/* output */
|
||||
|
||||
@@ -468,6 +468,12 @@ static void rna_def_material_mtex(BlenderRNA *brna)
|
||||
"from their parent");
|
||||
RNA_def_property_update(prop, 0, "rna_Material_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_map_to_bounds", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_MAPTO_BOUNDS);
|
||||
RNA_def_property_ui_text(prop, "Map to Bounds",
|
||||
"Map coordinates in object bounds");
|
||||
RNA_def_property_update(prop, 0, "rna_Material_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_from_original", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_OB_DUPLI_ORIG);
|
||||
RNA_def_property_ui_text(prop, "From Original",
|
||||
|
||||
@@ -257,9 +257,6 @@ static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
SmokeModifierData *smd = (SmokeModifierData *)ptr->data;
|
||||
Object *ob = (Object *)ptr->id.data;
|
||||
ParticleSystemModifierData *psmd = NULL;
|
||||
ParticleSystem *psys = NULL;
|
||||
ParticleSettings *part = NULL;
|
||||
|
||||
/* nothing changed */
|
||||
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
|
||||
@@ -273,28 +270,6 @@ static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
ob->dt = OB_WIRE;
|
||||
break;
|
||||
case MOD_SMOKE_TYPE_FLOW:
|
||||
for (psys = ob->particlesystem.first; psys; psys = psys->next)
|
||||
if (psys->part->type == PART_EMITTER)
|
||||
break;
|
||||
if (ob->type == OB_MESH && !psys) {
|
||||
/* add particle system */
|
||||
psmd = (ParticleSystemModifierData *)object_add_particle_system(scene, ob, NULL);
|
||||
if (psmd) {
|
||||
psys = psmd->psys;
|
||||
part = psys->part;
|
||||
part->lifetime = 1.0f;
|
||||
part->sta = 1.0f;
|
||||
part->end = 250.0f;
|
||||
part->ren_as = PART_DRAW_NOT;
|
||||
part->flag |= PART_UNBORN;
|
||||
part->draw_as = PART_DRAW_DOT;
|
||||
BLI_strncpy(psys->name, "SmokeParticles", sizeof(psys->name));
|
||||
psys->recalc |= (PSYS_RECALC_RESET | PSYS_RECALC_PHYS);
|
||||
DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
|
||||
}
|
||||
}
|
||||
if (smd->flow)
|
||||
smd->flow->psys = psys;
|
||||
case MOD_SMOKE_TYPE_COLL:
|
||||
case 0:
|
||||
default:
|
||||
|
||||
@@ -1056,6 +1056,13 @@ static void rna_def_effector_weight(BlenderRNA *brna)
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Drag", "Drag effector weight");
|
||||
RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
|
||||
|
||||
prop = RNA_def_property(srna, "smokeflow", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "weight[13]");
|
||||
RNA_def_property_range(prop, -200.0f, 200.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Smoke Flow", "Smoke Flow effector weight");
|
||||
RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
|
||||
}
|
||||
|
||||
static void rna_def_field(BlenderRNA *brna)
|
||||
@@ -1082,6 +1089,7 @@ static void rna_def_field(BlenderRNA *brna)
|
||||
{PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""},
|
||||
{PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", "Create turbulence with a noise field"},
|
||||
{PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", "Create a force that dampens motion"},
|
||||
{PFIELD_SMOKEFLOW, "SMOKE_FLOW", ICON_FORCE_SMOKEFLOW, "Smoke Flow", "Create a force based on smoke simulation air flow"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -1335,6 +1343,11 @@ static void rna_def_field(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Multiple Springs", "Every point is effected by multiple springs");
|
||||
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_smoke_density", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_SMOKE_DENSITY);
|
||||
RNA_def_property_ui_text(prop, "Apply Density", "Adjust force strength based on smoke density");
|
||||
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
|
||||
|
||||
/* Pointer */
|
||||
|
||||
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
|
||||
@@ -1343,6 +1356,12 @@ static void rna_def_field(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Texture", "Texture to use as force");
|
||||
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "source_object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "f_source");
|
||||
RNA_def_property_ui_text(prop, "Domain Object", "Select domain object of the smoke simulation");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
|
||||
|
||||
/********** Curve Guide Field Settings **********/
|
||||
|
||||
prop = RNA_def_property(srna, "guide_minimum", PROP_FLOAT, PROP_NONE);
|
||||
|
||||
@@ -65,14 +65,20 @@ static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *p
|
||||
DAG_scene_sort(bmain, scene);
|
||||
}
|
||||
|
||||
static void rna_Smoke_resetCache(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
|
||||
if (settings->smd && settings->smd->domain)
|
||||
settings->point_cache[0]->flag |= PTCACHE_OUTDATED;
|
||||
DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
|
||||
}
|
||||
|
||||
static void rna_Smoke_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
|
||||
|
||||
smokeModifier_reset(settings->smd);
|
||||
|
||||
if (settings->smd && settings->smd->domain)
|
||||
settings->point_cache[0]->flag |= PTCACHE_OUTDATED;
|
||||
rna_Smoke_resetCache(bmain, scene, ptr);
|
||||
|
||||
rna_Smoke_update(bmain, scene, ptr);
|
||||
}
|
||||
@@ -142,6 +148,30 @@ static void rna_SmokeModifier_density_get(PointerRNA *ptr, float *values)
|
||||
memcpy(values, density, size * sizeof(float));
|
||||
}
|
||||
|
||||
static void rna_SmokeFlow_density_vgroup_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_get(ptr, value, flow->vgroup_density);
|
||||
}
|
||||
|
||||
static int rna_SmokeFlow_density_vgroup_length(PointerRNA *ptr)
|
||||
{
|
||||
SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
|
||||
return rna_object_vgroup_name_index_length(ptr, flow->vgroup_density);
|
||||
}
|
||||
|
||||
static void rna_SmokeFlow_density_vgroup_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
|
||||
rna_object_vgroup_name_index_set(ptr, value, &flow->vgroup_density);
|
||||
}
|
||||
|
||||
static void rna_SmokeFlow_uvlayer_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
|
||||
rna_object_uvlayer_name_set(ptr, value, flow->uvlayer_name, sizeof(flow->uvlayer_name));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
@@ -217,7 +247,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
|
||||
RNA_def_property_ui_text(prop, "Density",
|
||||
"How much density affects smoke motion (higher value results in faster rising smoke)");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "beta");
|
||||
@@ -225,7 +255,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
|
||||
RNA_def_property_ui_text(prop, "Heat",
|
||||
"How much heat affects smoke motion (higher value results in faster rising smoke)");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "coll_group");
|
||||
@@ -253,24 +283,24 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0, 10.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 2);
|
||||
RNA_def_property_ui_text(prop, "Strength", "Strength of noise");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "diss_speed");
|
||||
RNA_def_property_range(prop, 1.0, 10000.0);
|
||||
RNA_def_property_ui_range(prop, 1.0, 10000.0, 1, 0);
|
||||
RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "use_dissolve_smoke", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE);
|
||||
RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "use_dissolve_smoke_log", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE_LOG);
|
||||
RNA_def_property_ui_text(prop, "Logarithmic dissolve", "Using 1/x ");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
@@ -297,21 +327,21 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
prop = RNA_def_property(srna, "smooth_emitter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGH_SMOOTH);
|
||||
RNA_def_property_ui_text(prop, "Smooth Emitter", "Smooth emitted smoke to avoid blockiness");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "time_scale");
|
||||
RNA_def_property_range(prop, 0.2, 1.5);
|
||||
RNA_def_property_ui_range(prop, 0.2, 1.5, 0.02, 5);
|
||||
RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "vorticity");
|
||||
RNA_def_property_range(prop, 0.01, 4.0);
|
||||
RNA_def_property_ui_range(prop, 0.01, 4.0, 0.02, 5);
|
||||
RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence/rotation in fluid");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_array(prop, 32);
|
||||
@@ -321,25 +351,80 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
RNA_def_property_float_funcs(prop, "rna_SmokeModifier_density_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Density", "Smoke density");
|
||||
|
||||
prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "dx");
|
||||
prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_XYZ); /* can change each frame when using adaptive domain */
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "dx", "Cell Size");
|
||||
RNA_def_property_ui_text(prop, "cell_size", "Cell Size");
|
||||
|
||||
prop = RNA_def_property(srna, "start_point", PROP_FLOAT, PROP_XYZ);
|
||||
prop = RNA_def_property(srna, "start_point", PROP_FLOAT, PROP_XYZ); /* can change each frame when using adaptive domain */
|
||||
RNA_def_property_float_sdna(prop, NULL, "p0");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "p0", "Start point");
|
||||
|
||||
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "scale");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "scale", "Domain scale factor");
|
||||
|
||||
prop = RNA_def_property(srna, "domain_resolution", PROP_INT, PROP_XYZ);
|
||||
prop = RNA_def_property(srna, "domain_resolution", PROP_INT, PROP_XYZ); /* can change each frame when using adaptive domain */
|
||||
RNA_def_property_int_sdna(prop, NULL, "res");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "res", "Smoke Grid Resolution");
|
||||
|
||||
prop = RNA_def_property(srna, "burning_rate", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.01, 4.0);
|
||||
RNA_def_property_ui_range(prop, 0.01, 2.0, 1.0, 5);
|
||||
RNA_def_property_ui_text(prop, "Speed", "Speed of the burning reaction. Use larger values for smaller flame");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "flame_smoke", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 8.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 4.0, 1.0, 5);
|
||||
RNA_def_property_ui_text(prop, "Smoke", "Amount of smoke created by burning fuel");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "flame_vorticity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 2.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 5);
|
||||
RNA_def_property_ui_text(prop, "Vorticity", "Additional vorticity for the flames");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "flame_ignition", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.5, 5.0);
|
||||
RNA_def_property_ui_range(prop, 0.5, 2.5, 1.0, 5);
|
||||
RNA_def_property_ui_text(prop, "Ignition", "Minimum temperature of flames");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "flame_max_temp", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 1.0, 10.0);
|
||||
RNA_def_property_ui_range(prop, 1.0, 5.0, 1.0, 5);
|
||||
RNA_def_property_ui_text(prop, "Maximum", "Maximum temperature of flames");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "flame_smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke emitted from burning fuel");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "use_adaptive_domain", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_ADAPTIVE_DOMAIN);
|
||||
RNA_def_property_ui_text(prop, "Adaptive Domain", "Adapt simulation resolution and size to fluid");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "additional_res", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "adapt_res");
|
||||
RNA_def_property_range(prop, 0, 512);
|
||||
RNA_def_property_ui_range(prop, 0, 512, 2, 0);
|
||||
RNA_def_property_ui_text(prop, "Additional", "Maximum number of additional cells");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "adapt_margin", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "adapt_margin");
|
||||
RNA_def_property_range(prop, 2, 24);
|
||||
RNA_def_property_ui_range(prop, 2, 24, 2, 0);
|
||||
RNA_def_property_ui_text(prop, "Margin", "Margin added around fluid to minimize boundary interference");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
|
||||
prop = RNA_def_property(srna, "adapt_threshold", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.01, 0.5);
|
||||
RNA_def_property_ui_range(prop, 0.01, 0.5, 1.0, 5);
|
||||
RNA_def_property_ui_text(prop, "Threshold", "Maximum amount of fluid cell can contain before it's considered empty");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
|
||||
}
|
||||
|
||||
static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
@@ -347,6 +432,26 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem smoke_flow_types[] = {
|
||||
{MOD_SMOKE_FLOW_TYPE_OUTFLOW, "OUTFLOW", 0, "Outflow", "Delete smoke from simulation"},
|
||||
{MOD_SMOKE_FLOW_TYPE_SMOKE, "SMOKE", 0, "Smoke", "Add smoke"},
|
||||
{MOD_SMOKE_FLOW_TYPE_SMOKEFIRE, "BOTH", 0, "Fire + Smoke", "Add fire and smoke"},
|
||||
{MOD_SMOKE_FLOW_TYPE_FIRE, "FIRE", 0, "Fire", "Add fire"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static EnumPropertyItem smoke_flow_sources[] = {
|
||||
{MOD_SMOKE_FLOW_SOURCE_PARTICLES, "PARTICLES", ICON_PARTICLES, "Particle System", "Emit smoke from particles"},
|
||||
{MOD_SMOKE_FLOW_SOURCE_MESH, "MESH", ICON_META_CUBE, "Mesh", "Emit smoke from mesh surface or volume"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static EnumPropertyItem smoke_flow_texture_types[] = {
|
||||
{MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO, "AUTO", 0, "Generated", "Generated coordinates centered to flow object"},
|
||||
{MOD_SMOKE_FLOW_TEXTURE_MAP_UV, "UV", 0, "UV", "Use UV layer for texture coordinates"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "SmokeFlowSettings", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Flow Settings", "Smoke flow settings");
|
||||
RNA_def_struct_sdna(srna, "SmokeFlowSettings");
|
||||
@@ -354,11 +459,23 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
|
||||
prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "density");
|
||||
RNA_def_property_range(prop, 0.001, 1);
|
||||
RNA_def_property_ui_range(prop, 0.001, 1.0, 1.0, 4);
|
||||
RNA_def_property_range(prop, 0.0, 1);
|
||||
RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 4);
|
||||
RNA_def_property_ui_text(prop, "Density", "");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_float_sdna(prop, NULL, "color");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "fuel_amount", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 10);
|
||||
RNA_def_property_ui_range(prop, 0.0, 5.0, 1.0, 4);
|
||||
RNA_def_property_ui_text(prop, "Flame Rate", "");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "temperature", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "temp");
|
||||
RNA_def_property_range(prop, -10, 10);
|
||||
@@ -373,9 +490,16 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object");
|
||||
RNA_def_property_update(prop, 0, "rna_Smoke_reset_dependancy");
|
||||
|
||||
prop = RNA_def_property(srna, "use_outflow", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "type", MOD_SMOKE_FLOW_TYPE_OUTFLOW);
|
||||
RNA_def_property_ui_text(prop, "Outflow", "Delete smoke from simulation");
|
||||
prop = RNA_def_property(srna, "smoke_flow_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "type");
|
||||
RNA_def_property_enum_items(prop, smoke_flow_types);
|
||||
RNA_def_property_ui_text(prop, "Flow Type", "Change how flow affects the simulation");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "smoke_flow_source", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "source");
|
||||
RNA_def_property_enum_items(prop, smoke_flow_sources);
|
||||
RNA_def_property_ui_text(prop, "Source", "Change how smoke is emitted");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "use_absolute", PROP_BOOLEAN, PROP_NONE);
|
||||
@@ -385,14 +509,82 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
|
||||
prop = RNA_def_property(srna, "initial_velocity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_INITVELOCITY);
|
||||
RNA_def_property_ui_text(prop, "Initial Velocity", "Smoke inherits its velocity from the emitter particle");
|
||||
RNA_def_property_ui_text(prop, "Initial Velocity", "Smoke has some initial velocity when it is emitted");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "vel_multi");
|
||||
RNA_def_property_range(prop, -2.0, 2.0);
|
||||
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
|
||||
RNA_def_property_ui_text(prop, "Multiplier", "Multiplier to adjust velocity passed to smoke");
|
||||
RNA_def_property_ui_text(prop, "Source", "Multiplier of source velocity passed to smoke");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "velocity_normal", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "vel_normal");
|
||||
RNA_def_property_range(prop, -2.0, 2.0);
|
||||
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
|
||||
RNA_def_property_ui_text(prop, "Normal", "Amount of normal directional velocity");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "velocity_random", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "vel_random");
|
||||
RNA_def_property_range(prop, 0.0, 2.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 2.0, 0.05, 5);
|
||||
RNA_def_property_ui_text(prop, "Random", "Amount of random velocity");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "volume_density", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.05, 5);
|
||||
RNA_def_property_ui_text(prop, "Volume", "Factor for smoke emitted from inside the mesh volume");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.5, 10.0);
|
||||
RNA_def_property_ui_range(prop, 0.5, 5.0, 0.05, 5);
|
||||
RNA_def_property_ui_text(prop, "Surface", "Maximum distance from mesh surface to emit smoke");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "density_vertex_group", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop, "rna_SmokeFlow_density_vgroup_get",
|
||||
"rna_SmokeFlow_density_vgroup_length",
|
||||
"rna_SmokeFlow_density_vgroup_set");
|
||||
RNA_def_property_ui_text(prop, "Vertex Group",
|
||||
"Name of Vertex Group which determines surface emission rate");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "use_texture", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_TEXTUREEMIT);
|
||||
RNA_def_property_ui_text(prop, "Use Texture", "Use a texture to controll emission strength");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "texture_map_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "texture_type");
|
||||
RNA_def_property_enum_items(prop, smoke_flow_texture_types);
|
||||
RNA_def_property_ui_text(prop, "Mapping", "Texture mapping type");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "uvlayer_name");
|
||||
RNA_def_property_ui_text(prop, "UV Map", "UV map name");
|
||||
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SmokeFlow_uvlayer_set");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "noise_texture", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Texture", "Texture that controls emission strength");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "texture_size", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.01, 10.0);
|
||||
RNA_def_property_ui_range(prop, 0.1, 5.0, 0.05, 5);
|
||||
RNA_def_property_ui_text(prop, "Size", "Size of texture mapping");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop = RNA_def_property(srna, "texture_offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 200.0);
|
||||
RNA_def_property_ui_range(prop, 0.0, 100.0, 0.05, 5);
|
||||
RNA_def_property_ui_text(prop, "Offset", "Z-offset of texture mapping");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
|
||||
}
|
||||
|
||||
|
||||
@@ -1800,7 +1800,8 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
|
||||
};
|
||||
|
||||
static EnumPropertyItem smoked_type_items[] = {
|
||||
{TEX_VD_SMOKEDENSITY, "SMOKEDENSITY", 0, "Density", "Use smoke density as texture data"},
|
||||
{TEX_VD_SMOKEDENSITY, "SMOKEDENSITY", 0, "Smoke", "Use smoke density and color as texture data"},
|
||||
{TEX_VD_SMOKEFLAME, "SMOKEFLAME", 0, "Flame", "Use flame temperature as texture data"},
|
||||
{TEX_VD_SMOKEHEAT, "SMOKEHEAT", 0, "Heat", "Use smoke heat as texture data. Values from -2.0 to 2.0 are used"},
|
||||
{TEX_VD_SMOKEVEL, "SMOKEVEL", 0, "Velocity", "Use smoke velocity as texture data"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
|
||||
@@ -81,19 +81,31 @@ static void freeData(ModifierData *md)
|
||||
smokeModifier_free(smd);
|
||||
}
|
||||
|
||||
static void deformVerts(ModifierData *md, Object *ob,
|
||||
DerivedMesh *derivedData,
|
||||
float (*vertexCos)[3],
|
||||
int UNUSED(numVerts),
|
||||
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
|
||||
{
|
||||
SmokeModifierData *smd = (SmokeModifierData *)md;
|
||||
CustomDataMask dataMask = 0;
|
||||
|
||||
if (smd && (smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
|
||||
if (smd->flow->source == MOD_SMOKE_FLOW_SOURCE_MESH) {
|
||||
/* vertex groups */
|
||||
if (smd->flow->vgroup_density)
|
||||
dataMask |= CD_MASK_MDEFORMVERT;
|
||||
/* uv layer */
|
||||
if (smd->flow->texture_type == MOD_SMOKE_FLOW_TEXTURE_MAP_UV)
|
||||
dataMask |= CD_MASK_MTFACE;
|
||||
}
|
||||
}
|
||||
return dataMask;
|
||||
}
|
||||
|
||||
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
|
||||
DerivedMesh *dm,
|
||||
ModifierApplyFlag UNUSED(flag))
|
||||
{
|
||||
SmokeModifierData *smd = (SmokeModifierData *) md;
|
||||
DerivedMesh *dm = get_cddm(ob, NULL, derivedData, vertexCos);
|
||||
|
||||
smokeModifier_do(smd, md->scene, ob, dm);
|
||||
|
||||
if (dm != derivedData)
|
||||
dm->release(dm);
|
||||
return smokeModifier_do(smd, md->scene, ob, dm);
|
||||
}
|
||||
|
||||
static int dependsOnTime(ModifierData *UNUSED(md))
|
||||
@@ -102,11 +114,11 @@ static int dependsOnTime(ModifierData *UNUSED(md))
|
||||
}
|
||||
|
||||
static void updateDepgraph(ModifierData *md, DagForest *forest,
|
||||
struct Scene *scene,
|
||||
Object *UNUSED(ob),
|
||||
struct Scene *scene, struct Object *ob,
|
||||
DagNode *obNode)
|
||||
{
|
||||
SmokeModifierData *smd = (SmokeModifierData *) md;
|
||||
Base *base;
|
||||
|
||||
if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
|
||||
if (smd->domain->fluid_group || smd->domain->coll_group) {
|
||||
@@ -139,8 +151,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base *base = scene->base.first;
|
||||
|
||||
base = scene->base.first;
|
||||
for (; base; base = base->next) {
|
||||
SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(base->object, eModifierType_Smoke);
|
||||
|
||||
@@ -150,6 +161,14 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
|
||||
}
|
||||
}
|
||||
}
|
||||
/* add relation to all "smoke flow" force fields */
|
||||
base = scene->base.first;
|
||||
for (; base; base = base->next) {
|
||||
if (base->object->pd && base->object->pd->forcefield == PFIELD_SMOKEFLOW && base->object->pd->f_source == ob) {
|
||||
DagNode *node2 = dag_get_node(forest, base->object);
|
||||
dag_add_relation(forest, obNode, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Source Object");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,26 +186,30 @@ static void foreachIDLink(ModifierData *md, Object *ob,
|
||||
walk(userData, ob, (ID **)&smd->domain->effector_weights->group);
|
||||
}
|
||||
}
|
||||
|
||||
if (smd->type == MOD_SMOKE_TYPE_FLOW && smd->flow) {
|
||||
walk(userData, ob, (ID **)&smd->flow->noise_texture);
|
||||
}
|
||||
}
|
||||
|
||||
ModifierTypeInfo modifierType_Smoke = {
|
||||
/* name */ "Smoke",
|
||||
/* structName */ "SmokeModifierData",
|
||||
/* structSize */ sizeof(SmokeModifierData),
|
||||
/* type */ eModifierTypeType_OnlyDeform,
|
||||
/* type */ eModifierTypeType_Constructive,
|
||||
/* flags */ eModifierTypeFlag_AcceptsMesh |
|
||||
eModifierTypeFlag_UsesPointCache |
|
||||
eModifierTypeFlag_Single,
|
||||
|
||||
/* copyData */ copyData,
|
||||
/* deformVerts */ deformVerts,
|
||||
/* deformVerts */ NULL,
|
||||
/* deformMatrices */ NULL,
|
||||
/* deformVertsEM */ NULL,
|
||||
/* deformMatricesEM */ NULL,
|
||||
/* applyModifier */ NULL,
|
||||
/* applyModifier */ applyModifier,
|
||||
/* applyModifierEM */ NULL,
|
||||
/* initData */ initData,
|
||||
/* requiredDataMask */ NULL,
|
||||
/* requiredDataMask */ requiredDataMask,
|
||||
/* freeData */ freeData,
|
||||
/* isDisabled */ NULL,
|
||||
/* updateDepgraph */ updateDepgraph,
|
||||
|
||||
@@ -2660,6 +2660,13 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
|
||||
mul_m4_v3(shi->obi->duplitexmat, co);
|
||||
}
|
||||
mul_m4_v3(ob->imat_ren, co);
|
||||
|
||||
if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) {
|
||||
/* use bb vec[0] as min and bb vec[6] as max */
|
||||
co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f;
|
||||
co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f;
|
||||
co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* not really orco, but 'local' */
|
||||
@@ -2672,6 +2679,13 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
|
||||
Object *ob= shi->obi->ob;
|
||||
copy_v3_v3(co, xyz);
|
||||
mul_m4_v3(ob->imat_ren, co);
|
||||
|
||||
if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) {
|
||||
/* use bb vec[0] as min and bb vec[6] as max */
|
||||
co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f;
|
||||
co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f;
|
||||
co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mtex->texco==TEXCO_GLOB) {
|
||||
@@ -2738,6 +2752,12 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
|
||||
if ((rgbnor & TEX_RGB) == 0) {
|
||||
copy_v3_v3(tcol, &mtex->r);
|
||||
}
|
||||
else if (mtex->mapto & MAP_DENSITY) {
|
||||
copy_v3_v3(tcol, &texres.tr);
|
||||
if (texres.talpha) {
|
||||
texres.tin = stencilTin;
|
||||
}
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(tcol, &texres.tr);
|
||||
if (texres.talpha) {
|
||||
|
||||
@@ -227,69 +227,102 @@ static void init_frame_smoke(VoxelData *vd, float cfra)
|
||||
/* draw code for smoke */
|
||||
if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke))) {
|
||||
SmokeModifierData *smd = (SmokeModifierData *)md;
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
|
||||
|
||||
if (smd->domain && smd->domain->fluid) {
|
||||
if (cfra < smd->domain->point_cache[0]->startframe)
|
||||
if (sds && sds->fluid) {
|
||||
if (cfra < sds->point_cache[0]->startframe)
|
||||
; /* don't show smoke before simulation starts, this could be made an option in the future */
|
||||
else if (vd->smoked_type == TEX_VD_SMOKEHEAT) {
|
||||
size_t totRes;
|
||||
size_t i;
|
||||
float *heat;
|
||||
|
||||
copy_v3_v3_int(vd->resol, smd->domain->res);
|
||||
if (!smoke_has_heat(sds->fluid)) return;
|
||||
|
||||
copy_v3_v3_int(vd->resol, sds->res);
|
||||
totRes = vd_resol_size(vd);
|
||||
|
||||
/* scaling heat values from -2.0-2.0 to 0.0-1.0 */
|
||||
vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data");
|
||||
/* get heat data */
|
||||
heat = smoke_get_heat(sds->fluid);
|
||||
|
||||
|
||||
heat = smoke_get_heat(smd->domain->fluid);
|
||||
|
||||
/* scale heat values from -2.0-2.0 to 0.0-1.0 */
|
||||
for (i = 0; i < totRes; i++) {
|
||||
vd->dataset[i] = (heat[i] + 2.0f) / 4.0f;
|
||||
}
|
||||
|
||||
/* vd->dataset = smoke_get_heat(smd->domain->fluid); */
|
||||
}
|
||||
else if (vd->smoked_type == TEX_VD_SMOKEVEL) {
|
||||
size_t totRes;
|
||||
size_t i;
|
||||
float *xvel, *yvel, *zvel;
|
||||
|
||||
copy_v3_v3_int(vd->resol, smd->domain->res);
|
||||
copy_v3_v3_int(vd->resol, sds->res);
|
||||
totRes = vd_resol_size(vd);
|
||||
|
||||
/* scaling heat values from -2.0-2.0 to 0.0-1.0 */
|
||||
vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data");
|
||||
/* get velocity data */
|
||||
xvel = smoke_get_velocity_x(sds->fluid);
|
||||
yvel = smoke_get_velocity_y(sds->fluid);
|
||||
zvel = smoke_get_velocity_z(sds->fluid);
|
||||
|
||||
xvel = smoke_get_velocity_x(smd->domain->fluid);
|
||||
yvel = smoke_get_velocity_y(smd->domain->fluid);
|
||||
zvel = smoke_get_velocity_z(smd->domain->fluid);
|
||||
|
||||
/* map velocities between 0 and 0.3f */
|
||||
for (i = 0; i < totRes; i++) {
|
||||
vd->dataset[i] = sqrt(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
else if (vd->smoked_type == TEX_VD_SMOKEFLAME) {
|
||||
size_t totRes;
|
||||
float *density;
|
||||
float *flame;
|
||||
|
||||
if (smd->domain->flags & MOD_SMOKE_HIGHRES) {
|
||||
smoke_turbulence_get_res(smd->domain->wt, vd->resol);
|
||||
density = smoke_turbulence_get_density(smd->domain->wt);
|
||||
if (sds->flags & MOD_SMOKE_HIGHRES) {
|
||||
if (!smoke_turbulence_has_fuel(sds->wt)) return;
|
||||
smoke_turbulence_get_res(sds->wt, vd->resol);
|
||||
flame = smoke_turbulence_get_flame(sds->wt);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3_int(vd->resol, smd->domain->res);
|
||||
density = smoke_get_density(smd->domain->fluid);
|
||||
if (!smoke_has_fuel(sds->fluid)) return;
|
||||
copy_v3_v3_int(vd->resol, sds->res);
|
||||
flame = smoke_get_flame(sds->fluid);
|
||||
}
|
||||
|
||||
/* always store copy, as smoke internal data can change */
|
||||
totRes= vd_resol_size(vd);
|
||||
vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data");
|
||||
memcpy(vd->dataset, flame, sizeof(float)*totRes);
|
||||
}
|
||||
else {
|
||||
size_t totCells;
|
||||
int depth = 4;
|
||||
vd->data_type = TEX_VD_RGBA_PREMUL;
|
||||
|
||||
/* data resolution */
|
||||
if (sds->flags & MOD_SMOKE_HIGHRES) {
|
||||
smoke_turbulence_get_res(sds->wt, vd->resol);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3_int(vd->resol, sds->res);
|
||||
}
|
||||
|
||||
/* TODO: is_vd_res_ok(rvd) doesnt check this resolution */
|
||||
totRes = vd_resol_size(vd);
|
||||
totCells = vd_resol_size(vd) * depth;
|
||||
/* always store copy, as smoke internal data can change */
|
||||
vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data");
|
||||
memcpy(vd->dataset, density, sizeof(float) * totRes);
|
||||
vd->dataset = MEM_mapallocN(sizeof(float) * totCells, "smoke data");
|
||||
|
||||
if (sds->flags & MOD_SMOKE_HIGHRES) {
|
||||
if (smoke_turbulence_has_colors(sds->wt)) {
|
||||
smoke_turbulence_get_rgba(sds->wt, vd->dataset, 1);
|
||||
}
|
||||
else {
|
||||
smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, vd->dataset, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (smoke_has_colors(sds->fluid)) {
|
||||
smoke_get_rgba(sds->fluid, vd->dataset, 1);
|
||||
}
|
||||
else {
|
||||
smoke_get_rgba_from_density(sds->fluid, sds->active_color, vd->dataset, 1);
|
||||
}
|
||||
}
|
||||
} /* end of fluid condition */
|
||||
}
|
||||
}
|
||||
@@ -320,6 +353,8 @@ void cache_voxeldata(Tex *tex, int scene_frame)
|
||||
MEM_freeN(vd->dataset);
|
||||
vd->dataset = NULL;
|
||||
}
|
||||
/* reset data_type */
|
||||
vd->data_type = TEX_VD_INTENSITY;
|
||||
|
||||
if (vd->flag & TEX_VD_STILL)
|
||||
curframe = vd->still_frame;
|
||||
@@ -379,9 +414,11 @@ void make_voxeldata(struct Render *re)
|
||||
|
||||
int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texres)
|
||||
{
|
||||
int retval = TEX_INT;
|
||||
VoxelData *vd = tex->vd;
|
||||
float co[3], offset[3] = {0.5, 0.5, 0.5};
|
||||
float co[3], offset[3] = {0.5, 0.5, 0.5}, a;
|
||||
int retval = (vd->data_type == TEX_VD_RGBA_PREMUL) ? TEX_RGB : TEX_INT;
|
||||
int depth = (vd->data_type == TEX_VD_RGBA_PREMUL) ? 4 : 1;
|
||||
int ch;
|
||||
|
||||
if (vd->dataset == NULL) {
|
||||
texres->tin = 0.0f;
|
||||
@@ -421,28 +458,60 @@ int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texre
|
||||
}
|
||||
}
|
||||
|
||||
for (ch = 0; ch < depth; ch++) {
|
||||
float *dataset = vd->dataset + ch*vd->resol[0]*vd->resol[1]*vd->resol[2];
|
||||
float *result = &texres->tin;
|
||||
|
||||
if (vd->data_type == TEX_VD_RGBA_PREMUL) {
|
||||
switch (ch) {
|
||||
case 0:
|
||||
result = &texres->tr;
|
||||
break;
|
||||
case 1:
|
||||
result = &texres->tg;
|
||||
break;
|
||||
case 2:
|
||||
result = &texres->tb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (vd->interp_type) {
|
||||
case TEX_VD_NEARESTNEIGHBOR:
|
||||
texres->tin = BLI_voxel_sample_nearest(vd->dataset, vd->resol, co);
|
||||
*result = BLI_voxel_sample_nearest(dataset, vd->resol, co);
|
||||
break;
|
||||
case TEX_VD_LINEAR:
|
||||
texres->tin = BLI_voxel_sample_trilinear(vd->dataset, vd->resol, co);
|
||||
*result = BLI_voxel_sample_trilinear(dataset, vd->resol, co);
|
||||
break;
|
||||
case TEX_VD_QUADRATIC:
|
||||
texres->tin = BLI_voxel_sample_triquadratic(vd->dataset, vd->resol, co);
|
||||
*result = BLI_voxel_sample_triquadratic(dataset, vd->resol, co);
|
||||
break;
|
||||
case TEX_VD_TRICUBIC_CATROM:
|
||||
case TEX_VD_TRICUBIC_BSPLINE:
|
||||
texres->tin = BLI_voxel_sample_tricubic(vd->dataset, vd->resol, co, (vd->interp_type == TEX_VD_TRICUBIC_BSPLINE));
|
||||
*result = BLI_voxel_sample_tricubic(dataset, vd->resol, co, (vd->interp_type == TEX_VD_TRICUBIC_BSPLINE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
a = texres->tin;
|
||||
texres->tin *= vd->int_multiplier;
|
||||
BRICONT;
|
||||
|
||||
if (vd->data_type == TEX_VD_RGBA_PREMUL) {
|
||||
/* unmultiply */
|
||||
if (a>0.001f) {
|
||||
texres->tr /= a;
|
||||
texres->tg /= a;
|
||||
texres->tb /= a;
|
||||
}
|
||||
texres->talpha = 1;
|
||||
}
|
||||
else {
|
||||
texres->tr = texres->tin;
|
||||
texres->tg = texres->tin;
|
||||
texres->tb = texres->tin;
|
||||
}
|
||||
|
||||
texres->ta = texres->tin;
|
||||
BRICONTRGB;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user