Merging r46043 through r46061 from trunk into soc-2011-tomato
This commit is contained in:
7
intern/smoke/extern/smoke_API.h
vendored
7
intern/smoke/extern/smoke_API.h
vendored
@@ -41,11 +41,11 @@ struct FLUID_3D;
|
||||
void smoke_export(struct FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles);
|
||||
|
||||
// low res
|
||||
struct FLUID_3D *smoke_init(int *res, float *p0);
|
||||
struct FLUID_3D *smoke_init(int *res, float *p0, float dtdef);
|
||||
void smoke_free(struct FLUID_3D *fluid);
|
||||
|
||||
void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli);
|
||||
void smoke_step(struct FLUID_3D *fluid, size_t framenr, float fps);
|
||||
void smoke_step(struct FLUID_3D *fluid, float dtSubdiv);
|
||||
|
||||
float *smoke_get_density(struct FLUID_3D *fluid);
|
||||
float *smoke_get_heat(struct FLUID_3D *fluid);
|
||||
@@ -53,6 +53,9 @@ float *smoke_get_velocity_x(struct FLUID_3D *fluid);
|
||||
float *smoke_get_velocity_y(struct FLUID_3D *fluid);
|
||||
float *smoke_get_velocity_z(struct FLUID_3D *fluid);
|
||||
|
||||
/* Moving obstacle velocity provided by blender */
|
||||
void smoke_get_ob_velocity(struct FLUID_3D *fluid, float **x, float **y, float **z);
|
||||
|
||||
float *smoke_get_force_x(struct FLUID_3D *fluid);
|
||||
float *smoke_get_force_y(struct FLUID_3D *fluid);
|
||||
float *smoke_get_force_z(struct FLUID_3D *fluid);
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "SPHERE.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#include "float.h"
|
||||
|
||||
#if PARALLEL==1
|
||||
#include <omp.h>
|
||||
#endif // PARALLEL
|
||||
@@ -42,11 +44,11 @@
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
FLUID_3D::FLUID_3D(int *res, float *p0) :
|
||||
FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
|
||||
_xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f)
|
||||
{
|
||||
// set simulation consts
|
||||
_dt = DT_DEFAULT; // just in case. set in step from a RNA factor
|
||||
_dt = dtdef; // just in case. set in step from a RNA factor
|
||||
|
||||
// start point of array
|
||||
_p0[0] = p0[0];
|
||||
@@ -81,6 +83,9 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
|
||||
_xVelocity = new float[_totalCells];
|
||||
_yVelocity = new float[_totalCells];
|
||||
_zVelocity = new float[_totalCells];
|
||||
_xVelocityOb = new float[_totalCells];
|
||||
_yVelocityOb = new float[_totalCells];
|
||||
_zVelocityOb = new float[_totalCells];
|
||||
_xVelocityOld = new float[_totalCells];
|
||||
_yVelocityOld = new float[_totalCells];
|
||||
_zVelocityOld = new float[_totalCells];
|
||||
@@ -111,6 +116,9 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
|
||||
_xVelocity[x] = 0.0f;
|
||||
_yVelocity[x] = 0.0f;
|
||||
_zVelocity[x] = 0.0f;
|
||||
_xVelocityOb[x] = 0.0f;
|
||||
_yVelocityOb[x] = 0.0f;
|
||||
_zVelocityOb[x] = 0.0f;
|
||||
_xVelocityOld[x] = 0.0f;
|
||||
_yVelocityOld[x] = 0.0f;
|
||||
_zVelocityOld[x] = 0.0f;
|
||||
@@ -131,9 +139,15 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
|
||||
|
||||
_colloPrev = 1; // default value
|
||||
|
||||
setBorderObstacles(); // walls
|
||||
|
||||
}
|
||||
|
||||
void FLUID_3D::setBorderObstacles()
|
||||
{
|
||||
|
||||
// set side obstacles
|
||||
int index;
|
||||
unsigned int index;
|
||||
for (int y = 0; y < _yRes; y++)
|
||||
for (int x = 0; x < _xRes; x++)
|
||||
{
|
||||
@@ -169,7 +183,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0) :
|
||||
index += _xRes - 1;
|
||||
if(_domainBcRight==1) _obstacles[index] = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FLUID_3D::~FLUID_3D()
|
||||
@@ -177,6 +190,9 @@ FLUID_3D::~FLUID_3D()
|
||||
if (_xVelocity) delete[] _xVelocity;
|
||||
if (_yVelocity) delete[] _yVelocity;
|
||||
if (_zVelocity) delete[] _zVelocity;
|
||||
if (_xVelocityOb) delete[] _xVelocityOb;
|
||||
if (_yVelocityOb) delete[] _yVelocityOb;
|
||||
if (_zVelocityOb) delete[] _zVelocityOb;
|
||||
if (_xVelocityOld) delete[] _xVelocityOld;
|
||||
if (_yVelocityOld) delete[] _yVelocityOld;
|
||||
if (_zVelocityOld) delete[] _zVelocityOld;
|
||||
@@ -214,10 +230,18 @@ void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void FLUID_3D::step(float dt)
|
||||
{
|
||||
#if 0
|
||||
// If border rules have been changed
|
||||
if (_colloPrev != *_borderColli) {
|
||||
printf("Border collisions changed\n");
|
||||
|
||||
// DG TODO: Need to check that no animated obstacle flags are overwritten
|
||||
setBorderCollisions();
|
||||
}
|
||||
#endif
|
||||
|
||||
// DG: TODO for the moment redo border for every timestep since it's been deleted every time by moving obstacles
|
||||
setBorderCollisions();
|
||||
|
||||
|
||||
// set delta time by dt_factor
|
||||
@@ -786,6 +810,7 @@ void FLUID_3D::project()
|
||||
memset(_pressure, 0, sizeof(float)*_totalCells);
|
||||
memset(_divergence, 0, sizeof(float)*_totalCells);
|
||||
|
||||
// set velocity and pressure inside of obstacles to zero
|
||||
setObstacleBoundaries(_pressure, 0, _zRes);
|
||||
|
||||
// copy out the boundaries
|
||||
@@ -798,12 +823,49 @@ void FLUID_3D::project()
|
||||
if(_domainBcTop == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
|
||||
else setZeroZ(_zVelocity, _res, 0, _zRes);
|
||||
|
||||
/*
|
||||
{
|
||||
float maxx = 0, maxy = 0, maxz = 0;
|
||||
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
|
||||
{
|
||||
if(_xVelocity[i] > maxx)
|
||||
maxx = _xVelocity[i];
|
||||
if(_yVelocity[i] > maxy)
|
||||
maxy = _yVelocity[i];
|
||||
if(_zVelocity[i] > maxz)
|
||||
maxz = _zVelocity[i];
|
||||
}
|
||||
printf("Max velx: %f, vely: %f, velz: %f\n", maxx, maxy, maxz);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
{
|
||||
float maxvalue = 0;
|
||||
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
|
||||
{
|
||||
if(_heat[i] > maxvalue)
|
||||
maxvalue = _heat[i];
|
||||
|
||||
}
|
||||
printf("Max heat: %f\n", maxvalue);
|
||||
}
|
||||
*/
|
||||
|
||||
// calculate divergence
|
||||
index = _slabSize + _xRes + 1;
|
||||
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
|
||||
for (y = 1; y < _yRes - 1; y++, index += 2)
|
||||
for (x = 1; x < _xRes - 1; x++, index++)
|
||||
{
|
||||
|
||||
if(_obstacles[index])
|
||||
{
|
||||
_divergence[index] = 0.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
float xright = _xVelocity[index + 1];
|
||||
float xleft = _xVelocity[index - 1];
|
||||
float yup = _yVelocity[index + _xRes];
|
||||
@@ -811,26 +873,82 @@ void FLUID_3D::project()
|
||||
float ztop = _zVelocity[index + _slabSize];
|
||||
float zbottom = _zVelocity[index - _slabSize];
|
||||
|
||||
if(_obstacles[index+1]) xright = - _xVelocity[index];
|
||||
if(_obstacles[index+1]) xright = - _xVelocity[index]; // DG: +=
|
||||
if(_obstacles[index-1]) xleft = - _xVelocity[index];
|
||||
if(_obstacles[index+_xRes]) yup = - _yVelocity[index];
|
||||
if(_obstacles[index-_xRes]) ydown = - _yVelocity[index];
|
||||
if(_obstacles[index+_slabSize]) ztop = - _zVelocity[index];
|
||||
if(_obstacles[index-_slabSize]) zbottom = - _zVelocity[index];
|
||||
|
||||
if(_obstacles[index+1] & 8) xright += _xVelocityOb[index + 1];
|
||||
if(_obstacles[index-1] & 8) xleft += _xVelocityOb[index - 1];
|
||||
if(_obstacles[index+_xRes] & 8) yup += _yVelocityOb[index + _xRes];
|
||||
if(_obstacles[index-_xRes] & 8) ydown += _yVelocityOb[index - _xRes];
|
||||
if(_obstacles[index+_slabSize] & 8) ztop += _zVelocityOb[index + _slabSize];
|
||||
if(_obstacles[index-_slabSize] & 8) zbottom += _zVelocityOb[index - _slabSize];
|
||||
|
||||
_divergence[index] = -_dx * 0.5f * (
|
||||
xright - xleft +
|
||||
yup - ydown +
|
||||
ztop - zbottom );
|
||||
|
||||
// DG: commenting this helps CG to get a better start, 10-20% speed improvement
|
||||
// _pressure[index] = 0.0f;
|
||||
// Pressure is zero anyway since now a local array is used
|
||||
_pressure[index] = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
{
|
||||
float maxvalue = 0;
|
||||
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
|
||||
{
|
||||
if(_divergence[i] > maxvalue)
|
||||
maxvalue = _divergence[i];
|
||||
|
||||
}
|
||||
printf("Max divergence: %f\n", maxvalue);
|
||||
}
|
||||
*/
|
||||
|
||||
copyBorderAll(_pressure, 0, _zRes);
|
||||
|
||||
/*
|
||||
{
|
||||
float maxvalue = 0;
|
||||
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
|
||||
{
|
||||
if(_pressure[i] > maxvalue)
|
||||
maxvalue = _pressure[i];
|
||||
}
|
||||
printf("Max pressure BEFORE: %f\n", maxvalue);
|
||||
}
|
||||
*/
|
||||
|
||||
// solve Poisson equation
|
||||
solvePressurePre(_pressure, _divergence, _obstacles);
|
||||
|
||||
{
|
||||
float maxvalue = 0;
|
||||
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
|
||||
{
|
||||
if(_pressure[i] > maxvalue)
|
||||
maxvalue = _pressure[i];
|
||||
|
||||
/* HACK: Animated collision object sometimes result in a non converging solvePressurePre() */
|
||||
if(_pressure[i] > _dx * _dt)
|
||||
_pressure[i] = _dx * _dt;
|
||||
else if(_pressure[i] < -_dx * _dt)
|
||||
_pressure[i] = -_dx * _dt;
|
||||
|
||||
// if(_obstacle[i] && _pressure[i] != 0.0)
|
||||
// printf("BAD PRESSURE i\n");
|
||||
|
||||
// if(_pressure[i]>1)
|
||||
// printf("index: %d\n", i);
|
||||
}
|
||||
// printf("Max pressure: %f, dx: %f\n", maxvalue, _dx);
|
||||
}
|
||||
|
||||
setObstaclePressure(_pressure, 0, _zRes);
|
||||
|
||||
// project out solution
|
||||
@@ -848,12 +966,74 @@ void FLUID_3D::project()
|
||||
}
|
||||
}
|
||||
|
||||
setObstacleVelocity(0, _zRes);
|
||||
|
||||
if (_pressure) delete[] _pressure;
|
||||
if (_divergence) delete[] _divergence;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// calculate the obstacle velocity at boundary
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void FLUID_3D::setObstacleVelocity(int zBegin, int zEnd)
|
||||
{
|
||||
|
||||
// completely TODO <-- who wrote this and what is here TODO? DG
|
||||
|
||||
const size_t index_ = _slabSize + _xRes + 1;
|
||||
|
||||
//int vIndex=_slabSize + _xRes + 1;
|
||||
|
||||
int bb=0;
|
||||
int bt=0;
|
||||
|
||||
if (zBegin == 0) {bb = 1;}
|
||||
if (zEnd == _zRes) {bt = 1;}
|
||||
|
||||
// tag remaining obstacle blocks
|
||||
for (int z = zBegin + bb; z < zEnd - bt; z++)
|
||||
{
|
||||
size_t index = index_ +(z-1)*_slabSize;
|
||||
|
||||
for (int y = 1; y < _yRes - 1; y++, index += 2)
|
||||
{
|
||||
for (int x = 1; x < _xRes - 1; x++, index++)
|
||||
{
|
||||
if (!_obstacles[index])
|
||||
{
|
||||
// if(_obstacles[index+1]) xright = - _xVelocityOb[index];
|
||||
if((_obstacles[index - 1] & 8) && abs(_xVelocityOb[index - 1]) > FLT_EPSILON )
|
||||
{
|
||||
// printf("velocity x!\n");
|
||||
_xVelocity[index] = _xVelocityOb[index - 1];
|
||||
_xVelocity[index - 1] = _xVelocityOb[index - 1];
|
||||
}
|
||||
// if(_obstacles[index+_xRes]) yup = - _yVelocityOb[index];
|
||||
if((_obstacles[index - _xRes] & 8) && abs(_yVelocityOb[index - _xRes]) > FLT_EPSILON)
|
||||
{
|
||||
// printf("velocity y!\n");
|
||||
_yVelocity[index] = _yVelocityOb[index - _xRes];
|
||||
_yVelocity[index - _xRes] = _yVelocityOb[index - _xRes];
|
||||
}
|
||||
// if(_obstacles[index+_slabSize]) ztop = - _zVelocityOb[index];
|
||||
if((_obstacles[index - _slabSize] & 8) && abs(_zVelocityOb[index - _slabSize]) > FLT_EPSILON)
|
||||
{
|
||||
// printf("velocity z!\n");
|
||||
_zVelocity[index] = _zVelocityOb[index - _slabSize];
|
||||
_zVelocity[index - _slabSize] = _zVelocityOb[index - _slabSize];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_density[index] = 0;
|
||||
}
|
||||
//vIndex++;
|
||||
} // x loop
|
||||
//vIndex += 2;
|
||||
} // y loop
|
||||
//vIndex += 2 * _xRes;
|
||||
} // z loop
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// diffuse heat
|
||||
@@ -892,7 +1072,7 @@ void FLUID_3D::addObstacle(OBSTACLE* obstacle)
|
||||
void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
|
||||
{
|
||||
|
||||
// compleately TODO
|
||||
// completely TODO <-- who wrote this and what is here TODO? DG
|
||||
|
||||
const size_t index_ = _slabSize + _xRes + 1;
|
||||
|
||||
@@ -914,7 +1094,7 @@ void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
|
||||
for (int x = 1; x < _xRes - 1; x++, index++)
|
||||
{
|
||||
// could do cascade of ifs, but they are a pain
|
||||
if (_obstacles[index])
|
||||
if (_obstacles[index] /* && !(_obstacles[index] & 8) DG TODO TEST THIS CONDITION */)
|
||||
{
|
||||
const int top = _obstacles[index + _slabSize];
|
||||
const int bottom= _obstacles[index - _slabSize];
|
||||
@@ -928,9 +1108,11 @@ void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
|
||||
// const bool fully = (up && down);
|
||||
//const bool fullx = (left && right);
|
||||
|
||||
/*
|
||||
_xVelocity[index] =
|
||||
_yVelocity[index] =
|
||||
_zVelocity[index] = 0.0f;
|
||||
*/
|
||||
_pressure[index] = 0.0f;
|
||||
|
||||
// average pressure neighbors
|
||||
@@ -1253,7 +1435,35 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
|
||||
|
||||
setZeroBorder(_density, res, zBegin, zEnd);
|
||||
setZeroBorder(_heat, res, zBegin, zEnd);
|
||||
#if 0
|
||||
{
|
||||
const size_t index_ = _slabSize + _xRes + 1;
|
||||
int bb=0;
|
||||
int bt=0;
|
||||
|
||||
if (zBegin == 0) {bb = 1;}
|
||||
if (zEnd == _zRes) {bt = 1;}
|
||||
|
||||
for (int z = zBegin + bb; z < zEnd - bt; z++)
|
||||
{
|
||||
size_t index = index_ +(z-1)*_slabSize;
|
||||
|
||||
for (int y = 1; y < _yRes - 1; y++, index += 2)
|
||||
{
|
||||
for (int x = 1; x < _xRes - 1; x++, index++)
|
||||
{
|
||||
// clean custom velocities from moving obstacles again
|
||||
if (_obstacles[index])
|
||||
{
|
||||
_xVelocity[index] =
|
||||
_yVelocity[index] =
|
||||
_zVelocity[index] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*int begin=zBegin * _slabSize;
|
||||
int end=begin + (zEnd - zBegin) * _slabSize;
|
||||
|
||||
@@ -39,9 +39,6 @@
|
||||
// #include "WTURBULENCE.h"
|
||||
#include "VEC3.h"
|
||||
|
||||
// timestep default value for nice appearance
|
||||
#define DT_DEFAULT 0.1f;
|
||||
|
||||
using namespace std;
|
||||
using namespace BasicVector;
|
||||
class WTURBULENCE;
|
||||
@@ -49,7 +46,7 @@ class WTURBULENCE;
|
||||
class FLUID_3D
|
||||
{
|
||||
public:
|
||||
FLUID_3D(int *res, /* int amplify, */ float *p0);
|
||||
FLUID_3D(int *res, /* int amplify, */ float *p0, float dtdef);
|
||||
FLUID_3D() {};
|
||||
virtual ~FLUID_3D();
|
||||
|
||||
@@ -72,7 +69,7 @@ class FLUID_3D
|
||||
int yRes() const { return _yRes; };
|
||||
int zRes() const { return _zRes; };
|
||||
|
||||
public:
|
||||
public:
|
||||
// dimensions
|
||||
int _xRes, _yRes, _zRes, _maxRes;
|
||||
Vec3Int _res;
|
||||
@@ -89,6 +86,8 @@ class FLUID_3D
|
||||
void artificialDampingSL(int zBegin, int zEnd);
|
||||
void artificialDampingExactSL(int pos);
|
||||
|
||||
void setBorderObstacles();
|
||||
|
||||
// fields
|
||||
float* _density;
|
||||
float* _densityOld;
|
||||
@@ -97,13 +96,17 @@ class FLUID_3D
|
||||
float* _xVelocity;
|
||||
float* _yVelocity;
|
||||
float* _zVelocity;
|
||||
float* _xVelocityOb;
|
||||
float* _yVelocityOb;
|
||||
float* _zVelocityOb;
|
||||
float* _xVelocityOld;
|
||||
float* _yVelocityOld;
|
||||
float* _zVelocityOld;
|
||||
float* _xForce;
|
||||
float* _yForce;
|
||||
float* _zForce;
|
||||
unsigned char* _obstacles;
|
||||
unsigned char* _obstacles; /* only used (usefull) for static obstacles like domain boundaries */
|
||||
unsigned char* _obstaclesAnim;
|
||||
|
||||
// Required for proper threading:
|
||||
float* _xVelocityTemp;
|
||||
@@ -137,6 +140,8 @@ class FLUID_3D
|
||||
// have to recalibrate borders if nothing has changed
|
||||
void setBorderCollisions();
|
||||
|
||||
void setObstacleVelocity(int zBegin, int zEnd);
|
||||
|
||||
// WTURBULENCE object, if active
|
||||
// WTURBULENCE* _wTurbulence;
|
||||
|
||||
|
||||
@@ -27,9 +27,11 @@
|
||||
#define OBSTACLE_H
|
||||
|
||||
enum OBSTACLE_FLAGS {
|
||||
EMPTY = 0,
|
||||
EMPTY = 0,
|
||||
/* 1 is used to flag an object cell */
|
||||
MARCHED = 2,
|
||||
RETIRED = 4
|
||||
RETIRED = 4,
|
||||
ANIMATED = 8,
|
||||
};
|
||||
|
||||
class OBSTACLE
|
||||
|
||||
@@ -431,8 +431,11 @@ void WTURBULENCE::decomposeEnergy(float *_energy, float *_highFreqEnergy)
|
||||
// compute velocity from energies and march into obstacles
|
||||
// for wavelet decomposition
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float* zvel, unsigned char *obstacles)
|
||||
void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float* zvel, unsigned char *origObstacles)
|
||||
{
|
||||
unsigned char *obstacles = new unsigned char[_totalCellsSm];
|
||||
memcpy(obstacles, origObstacles, sizeof(unsigned char) * _totalCellsSm);
|
||||
|
||||
// compute everywhere
|
||||
for (int x = 0; x < _totalCellsSm; x++)
|
||||
_energy[x] = 0.5f * (xvel[x] * xvel[x] + yvel[x] * yvel[x] + zvel[x] * zvel[x]);
|
||||
@@ -506,7 +509,9 @@ void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float*
|
||||
for (int y = 1; y < _yResSm - 1; y++, index += 2)
|
||||
for (int x = 1; x < _xResSm - 1; x++, index++)
|
||||
if (obstacles[index])
|
||||
obstacles[index] = 1;
|
||||
obstacles[index] = 1; // DG TODO ? animated obstacle flag?
|
||||
|
||||
free(obstacles);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Daniel Genrich
|
||||
* Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
@@ -36,10 +37,10 @@
|
||||
#include <math.h>
|
||||
|
||||
// y in smoke is z in blender
|
||||
extern "C" FLUID_3D *smoke_init(int *res, float *p0)
|
||||
extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef)
|
||||
{
|
||||
// smoke lib uses y as top-bottom/vertical axis where blender uses z
|
||||
FLUID_3D *fluid = new FLUID_3D(res, p0);
|
||||
FLUID_3D *fluid = new FLUID_3D(res, p0, dtdef);
|
||||
|
||||
// printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
|
||||
|
||||
@@ -78,41 +79,9 @@ extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z
|
||||
return x + y * max_x;
|
||||
}
|
||||
|
||||
extern "C" void smoke_step(FLUID_3D *fluid, size_t framenr, float fps)
|
||||
extern "C" void smoke_step(FLUID_3D *fluid, float dtSubdiv)
|
||||
{
|
||||
/* stability values copied from wturbulence.cpp */
|
||||
const int maxSubSteps = 25;
|
||||
const float maxVel = 0.5f; /* TODO: maybe 0.5 is still too high, please confirm! -dg */
|
||||
|
||||
float dt = DT_DEFAULT;
|
||||
float maxVelMag = 0.0f;
|
||||
int totalSubsteps;
|
||||
int substep = 0;
|
||||
float dtSubdiv;
|
||||
|
||||
/* get max velocity and lower the dt value if it is too high */
|
||||
size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
|
||||
|
||||
for(size_t i = 0; i < size; i++)
|
||||
{
|
||||
float vtemp = (fluid->_xVelocity[i]*fluid->_xVelocity[i]+fluid->_yVelocity[i]*fluid->_yVelocity[i]+fluid->_zVelocity[i]*fluid->_zVelocity[i]);
|
||||
if(vtemp > maxVelMag)
|
||||
maxVelMag = vtemp;
|
||||
}
|
||||
|
||||
/* adapt timestep for different framerates, dt = 0.1 is at 25fps */
|
||||
dt *= (25.0f / fps);
|
||||
|
||||
maxVelMag = sqrt(maxVelMag) * dt * (*(fluid->_dtFactor));
|
||||
totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */
|
||||
totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
|
||||
totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
|
||||
dtSubdiv = (float)dt / (float)totalSubsteps;
|
||||
|
||||
// printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
|
||||
|
||||
for(substep = 0; substep < totalSubsteps; substep++)
|
||||
fluid->step(dtSubdiv);
|
||||
fluid->step(dtSubdiv);
|
||||
}
|
||||
|
||||
extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
|
||||
@@ -307,6 +276,18 @@ extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
|
||||
return fluid->_obstacles;
|
||||
}
|
||||
|
||||
extern "C" void smoke_get_ob_velocity(struct FLUID_3D *fluid, float **x, float **y, float **z)
|
||||
{
|
||||
*x = fluid->_xVelocityOb;
|
||||
*y = fluid->_yVelocityOb;
|
||||
*z = fluid->_zVelocityOb;
|
||||
}
|
||||
|
||||
extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid)
|
||||
{
|
||||
return fluid->_obstaclesAnim;
|
||||
}
|
||||
|
||||
extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
|
||||
{
|
||||
wt->setNoise(type);
|
||||
|
||||
@@ -100,6 +100,15 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
|
||||
sub.prop(flow, "use_absolute")
|
||||
sub.prop(flow, "density")
|
||||
sub.prop(flow, "temperature")
|
||||
|
||||
elif md.smoke_type == 'COLLISION':
|
||||
coll = md.coll_settings
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(coll, "collision_type")
|
||||
|
||||
|
||||
|
||||
class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
|
||||
|
||||
@@ -637,10 +637,6 @@ class USERPREF_PT_theme(Panel):
|
||||
col.label(text="Tooltip:")
|
||||
ui_items_general(col, ui)
|
||||
|
||||
ui = theme.user_interface.wcol_tooltip
|
||||
col.label(text="Tooltip:")
|
||||
ui_items_general(col, ui)
|
||||
|
||||
ui = theme.user_interface.wcol_menu_item
|
||||
col.label(text="Menu Item:")
|
||||
ui_items_general(col, ui)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Daniel Genrich
|
||||
* Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
@@ -53,6 +54,7 @@
|
||||
|
||||
#include "BKE_bvhutils.h"
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_collision.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_effect.h"
|
||||
@@ -118,8 +120,7 @@ static void tend ( void )
|
||||
gettimeofday ( &_tend,&tz );
|
||||
}
|
||||
|
||||
#if 0 // unused
|
||||
static double tval()
|
||||
static double tval( void )
|
||||
{
|
||||
double t1, t2;
|
||||
t1 = ( double ) _tstart.tv_sec*1000 + ( double ) _tstart.tv_usec/ ( 1000 );
|
||||
@@ -127,14 +128,16 @@ static double tval()
|
||||
return t2-t1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct DerivedMesh;
|
||||
struct SmokeModifierData;
|
||||
|
||||
#define TRI_UVOFFSET (1.0 / 4.0)
|
||||
#define TRI_UVOFFSET (1./4.)
|
||||
|
||||
// timestep default value for nice appearance 0.1f
|
||||
#define DT_DEFAULT 0.1f
|
||||
|
||||
/* forward declerations */
|
||||
static void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *tris, int numfaces, int numtris, int **tridivs, float cell_len);
|
||||
@@ -159,7 +162,7 @@ void smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Obje
|
||||
|
||||
static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm)
|
||||
{
|
||||
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
|
||||
if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
|
||||
{
|
||||
size_t i;
|
||||
float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||
@@ -171,7 +174,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
|
||||
res = smd->domain->maxres;
|
||||
|
||||
// get BB of domain
|
||||
for (i = 0; i < dm->getNumVerts(dm); i++)
|
||||
for(i = 0; i < dm->getNumVerts(dm); i++)
|
||||
{
|
||||
float tmp[3];
|
||||
|
||||
@@ -198,32 +201,32 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
|
||||
// printf("size: %f, %f, %f\n", size[0], size[1], size[2]);
|
||||
|
||||
// prevent crash when initializing a plane as domain
|
||||
if ((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
|
||||
if((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
|
||||
return 0;
|
||||
|
||||
if (size[0] > size[1])
|
||||
if(size[0] > size[1])
|
||||
{
|
||||
if (size[0] > size[2])
|
||||
if(size[0] > size[2])
|
||||
{
|
||||
scale = res / size[0];
|
||||
smd->domain->dx = size[0] / res;
|
||||
smd->domain->dx = size[0] / res; // dx is in global coords
|
||||
smd->domain->res[0] = res;
|
||||
smd->domain->res[1] = (int)(size[1] * scale + 0.5);
|
||||
smd->domain->res[2] = (int)(size[2] * scale + 0.5);
|
||||
}
|
||||
else {
|
||||
scale = res / size[2];
|
||||
smd->domain->dx = size[2] / res;
|
||||
smd->domain->dx = size[2] / res; // dx is in global coords
|
||||
smd->domain->res[2] = res;
|
||||
smd->domain->res[0] = (int)(size[0] * scale + 0.5);
|
||||
smd->domain->res[1] = (int)(size[1] * scale + 0.5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (size[1] > size[2])
|
||||
if(size[1] > size[2])
|
||||
{
|
||||
scale = res / size[1];
|
||||
smd->domain->dx = size[1] / res;
|
||||
smd->domain->dx = size[1] / res; // dx is in global coords
|
||||
smd->domain->res[1] = res;
|
||||
smd->domain->res[0] = (int)(size[0] * scale + 0.5);
|
||||
smd->domain->res[2] = (int)(size[2] * scale + 0.5);
|
||||
@@ -243,10 +246,10 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
|
||||
|
||||
// printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
|
||||
// dt max is 0.1
|
||||
smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0);
|
||||
smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, DT_DEFAULT);
|
||||
smd->time = scene->r.cfra;
|
||||
|
||||
if (smd->domain->flags & MOD_SMOKE_HIGHRES)
|
||||
if(smd->domain->flags & MOD_SMOKE_HIGHRES)
|
||||
{
|
||||
smd->domain->wt = smoke_turbulence_init(smd->domain->res, smd->domain->amplify + 1, smd->domain->noise);
|
||||
smd->domain->res_wt[0] = smd->domain->res[0] * (smd->domain->amplify + 1);
|
||||
@@ -257,19 +260,19 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
|
||||
// printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n");
|
||||
}
|
||||
|
||||
if (!smd->domain->shadow)
|
||||
if(!smd->domain->shadow)
|
||||
smd->domain->shadow = MEM_callocN(sizeof(float) * smd->domain->res[0] * smd->domain->res[1] * smd->domain->res[2], "SmokeDomainShadow");
|
||||
|
||||
smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta), &(smd->domain->time_scale), &(smd->domain->vorticity), &(smd->domain->border_collisions));
|
||||
|
||||
if (smd->domain->wt)
|
||||
if(smd->domain->wt)
|
||||
{
|
||||
smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength));
|
||||
// printf("smoke_initWaveletBlenderRNA\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
|
||||
else if((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
|
||||
{
|
||||
// handle flow object here
|
||||
// XXX TODO
|
||||
@@ -288,7 +291,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
|
||||
}
|
||||
|
||||
/*
|
||||
if (!smd->flow->bvh)
|
||||
if(!smd->flow->bvh)
|
||||
{
|
||||
// smd->flow->bvh = MEM_callocN(sizeof(BVHTreeFromMesh), "smoke_bvhfromfaces");
|
||||
// bvhtree_from_mesh_faces(smd->flow->bvh, dm, 0.0, 2, 6);
|
||||
@@ -301,28 +304,33 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if ((smd->type & MOD_SMOKE_TYPE_COLL))
|
||||
else if((smd->type & MOD_SMOKE_TYPE_COLL))
|
||||
{
|
||||
smd->time = scene->r.cfra;
|
||||
|
||||
// todo: delete this when loading colls work -dg
|
||||
if (!smd->coll)
|
||||
smokeModifier_createType(smd);
|
||||
|
||||
if (!smd->coll->points)
|
||||
if(!smd->coll)
|
||||
{
|
||||
smokeModifier_createType(smd);
|
||||
}
|
||||
|
||||
if(!smd->coll->points)
|
||||
{
|
||||
// init collision points
|
||||
SmokeCollSettings *scs = smd->coll;
|
||||
|
||||
smd->time = scene->r.cfra;
|
||||
|
||||
// copy obmat
|
||||
copy_m4_m4(scs->mat, ob->obmat);
|
||||
copy_m4_m4(scs->mat_old, ob->obmat);
|
||||
|
||||
DM_ensure_tessface(dm);
|
||||
fill_scs_points(ob, dm, scs);
|
||||
|
||||
// DEBUG printf("scs->dx: %f\n", scs->dx);
|
||||
}
|
||||
|
||||
if (!smd->coll->bvhtree)
|
||||
if(!smd->coll->bvhtree)
|
||||
{
|
||||
smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
|
||||
}
|
||||
@@ -337,50 +345,52 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
|
||||
MVert *mvert = dm->getVertArray(dm);
|
||||
MFace *mface = dm->getTessFaceArray(dm);
|
||||
int i = 0, divs = 0;
|
||||
int *tridivs = NULL;
|
||||
float cell_len = 1.0 / 50.0; // for res = 50
|
||||
|
||||
// DG TODO: need to do this dynamically according to the domain object!
|
||||
float cell_len = scs->dx;
|
||||
int newdivs = 0;
|
||||
int quads = 0, facecounter = 0;
|
||||
|
||||
// count quads
|
||||
for (i = 0; i < dm->getNumTessFaces(dm); i++)
|
||||
for(i = 0; i < dm->getNumTessFaces(dm); i++)
|
||||
{
|
||||
if (mface[i].v4)
|
||||
if(mface[i].v4)
|
||||
quads++;
|
||||
}
|
||||
|
||||
calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumTessFaces(dm), dm->getNumTessFaces(dm) + quads, &tridivs, cell_len);
|
||||
scs->numtris = dm->getNumTessFaces(dm) + quads;
|
||||
scs->tridivs = NULL;
|
||||
calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumTessFaces(dm), scs->numtris, &(scs->tridivs), cell_len);
|
||||
|
||||
// count triangle divisions
|
||||
for (i = 0; i < dm->getNumTessFaces(dm) + quads; i++)
|
||||
for(i = 0; i < dm->getNumTessFaces(dm) + quads; i++)
|
||||
{
|
||||
divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1);
|
||||
divs += (scs->tridivs[3 * i] + 1) * (scs->tridivs[3 * i + 1] + 1) * (scs->tridivs[3 * i + 2] + 1);
|
||||
}
|
||||
|
||||
// printf("divs: %d\n", divs);
|
||||
|
||||
scs->points = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPoints");
|
||||
scs->points_old = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPointsOld");
|
||||
|
||||
for (i = 0; i < dm->getNumVerts(dm); i++)
|
||||
for(i = 0; i < dm->getNumVerts(dm); i++)
|
||||
{
|
||||
float tmpvec[3];
|
||||
copy_v3_v3(tmpvec, mvert[i].co);
|
||||
mul_m4_v3(ob->obmat, tmpvec);
|
||||
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
|
||||
copy_v3_v3(&scs->points[i * 3], tmpvec);
|
||||
}
|
||||
|
||||
for (i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
|
||||
for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
|
||||
{
|
||||
int again = 0;
|
||||
do
|
||||
{
|
||||
int j, k;
|
||||
int divs1 = tridivs[3 * facecounter + 0];
|
||||
int divs2 = tridivs[3 * facecounter + 1];
|
||||
//int divs3 = tridivs[3 * facecounter + 2];
|
||||
int divs1 = scs->tridivs[3 * facecounter + 0];
|
||||
int divs2 = scs->tridivs[3 * facecounter + 1];
|
||||
//int divs3 = scs->tridivs[3 * facecounter + 2];
|
||||
float side1[3], side2[3], trinormorg[3], trinorm[3];
|
||||
|
||||
if (again == 1 && mface[i].v4)
|
||||
if(again == 1 && mface[i].v4)
|
||||
{
|
||||
sub_v3_v3v3(side1, mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co);
|
||||
sub_v3_v3v3(side2, mvert[ mface[i].v4 ].co, mvert[ mface[i].v1 ].co);
|
||||
@@ -395,23 +405,23 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
|
||||
copy_v3_v3(trinorm, trinormorg);
|
||||
mul_v3_fl(trinorm, 0.25 * cell_len);
|
||||
|
||||
for (j = 0; j <= divs1; j++)
|
||||
for(j = 0; j <= divs1; j++)
|
||||
{
|
||||
for (k = 0; k <= divs2; k++)
|
||||
for(k = 0; k <= divs2; k++)
|
||||
{
|
||||
float p1[3], p2[3], p3[3], p[3]={0,0,0};
|
||||
const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0);
|
||||
const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0);
|
||||
float tmpvec[3];
|
||||
|
||||
if (uf+vf > 1.0)
|
||||
if(uf+vf > 1.0)
|
||||
{
|
||||
// printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
|
||||
continue;
|
||||
}
|
||||
|
||||
copy_v3_v3(p1, mvert[ mface[i].v1 ].co);
|
||||
if (again == 1 && mface[i].v4)
|
||||
if(again == 1 && mface[i].v4)
|
||||
{
|
||||
copy_v3_v3(p2, mvert[ mface[i].v3 ].co);
|
||||
copy_v3_v3(p3, mvert[ mface[i].v4 ].co);
|
||||
@@ -428,40 +438,211 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
|
||||
add_v3_v3v3(p, p1, p2);
|
||||
add_v3_v3(p, p3);
|
||||
|
||||
if (newdivs > divs)
|
||||
if(newdivs > divs)
|
||||
printf("mem problem\n");
|
||||
|
||||
// mMovPoints.push_back(p + trinorm);
|
||||
add_v3_v3v3(tmpvec, p, trinorm);
|
||||
mul_m4_v3(ob->obmat, tmpvec);
|
||||
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
|
||||
copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
|
||||
newdivs++;
|
||||
|
||||
if (newdivs > divs)
|
||||
if(newdivs > divs)
|
||||
printf("mem problem\n");
|
||||
|
||||
// mMovPoints.push_back(p - trinorm);
|
||||
copy_v3_v3(tmpvec, p);
|
||||
sub_v3_v3(tmpvec, trinorm);
|
||||
mul_m4_v3(ob->obmat, tmpvec);
|
||||
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
|
||||
copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
|
||||
newdivs++;
|
||||
}
|
||||
}
|
||||
|
||||
if (again == 0 && mface[i].v4)
|
||||
if(again == 0 && mface[i].v4)
|
||||
again++;
|
||||
else
|
||||
again = 0;
|
||||
|
||||
facecounter++;
|
||||
|
||||
} while (again!=0);
|
||||
} while(again!=0);
|
||||
}
|
||||
|
||||
scs->numverts = dm->getNumVerts(dm);
|
||||
// DG TODO: also save triangle count?
|
||||
|
||||
scs->numpoints = dm->getNumVerts(dm) + newdivs;
|
||||
|
||||
MEM_freeN(tridivs);
|
||||
for(i = 0; i < scs->numpoints * 3; i++)
|
||||
{
|
||||
scs->points_old[i] = scs->points[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void fill_scs_points_anim(Object *UNUSED(ob), DerivedMesh *dm, SmokeCollSettings *scs)
|
||||
{
|
||||
MVert *mvert = dm->getVertArray(dm);
|
||||
MFace *mface = dm->getTessFaceArray(dm);
|
||||
int quads = 0, numtris = 0, facecounter = 0;
|
||||
unsigned int i = 0;
|
||||
int divs = 0, newdivs = 0;
|
||||
|
||||
// DG TODO: need to do this dynamically according to the domain object!
|
||||
float cell_len = scs->dx;
|
||||
|
||||
// count quads
|
||||
for(i = 0; i < dm->getNumTessFaces(dm); i++)
|
||||
{
|
||||
if(mface[i].v4)
|
||||
quads++;
|
||||
}
|
||||
|
||||
numtris = dm->getNumTessFaces(dm) + quads;
|
||||
|
||||
// check if mesh changed topology
|
||||
if(scs->numtris != numtris)
|
||||
return;
|
||||
if(scs->numverts != dm->getNumVerts(dm))
|
||||
return;
|
||||
|
||||
// update new positions
|
||||
for(i = 0; i < dm->getNumVerts(dm); i++)
|
||||
{
|
||||
float tmpvec[3];
|
||||
copy_v3_v3(tmpvec, mvert[i].co);
|
||||
copy_v3_v3(&scs->points[i * 3], tmpvec);
|
||||
}
|
||||
|
||||
// for every triangle // update div points
|
||||
for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
|
||||
{
|
||||
int again = 0;
|
||||
do
|
||||
{
|
||||
int j, k;
|
||||
int divs1 = scs->tridivs[3 * facecounter + 0];
|
||||
int divs2 = scs->tridivs[3 * facecounter + 1];
|
||||
float srcside1[3], srcside2[3], destside1[3], destside2[3], src_trinormorg[3], dest_trinormorg[3], src_trinorm[3], dest_trinorm[3];
|
||||
|
||||
if(again == 1 && mface[i].v4)
|
||||
{
|
||||
sub_v3_v3v3(srcside1, &scs->points_old[mface[i].v3 * 3], &scs->points_old[mface[i].v1 * 3]);
|
||||
sub_v3_v3v3(destside1, &scs->points[mface[i].v3 * 3], &scs->points[mface[i].v1 * 3]);
|
||||
|
||||
sub_v3_v3v3(srcside2, &scs->points_old[mface[i].v4 * 3], &scs->points_old[mface[i].v1 * 3]);
|
||||
sub_v3_v3v3(destside2, &scs->points[mface[i].v4 * 3], &scs->points[mface[i].v1 * 3]);
|
||||
}
|
||||
else {
|
||||
sub_v3_v3v3(srcside1, &scs->points_old[mface[i].v2 * 3], &scs->points_old[mface[i].v1 * 3]);
|
||||
sub_v3_v3v3(destside1, &scs->points[mface[i].v2 * 3], &scs->points[mface[i].v1 * 3]);
|
||||
|
||||
sub_v3_v3v3(srcside2, &scs->points_old[mface[i].v3 * 3], &scs->points_old[mface[i].v1 * 3]);
|
||||
sub_v3_v3v3(destside2, &scs->points[mface[i].v3 * 3], &scs->points[mface[i].v1 * 3]);
|
||||
}
|
||||
|
||||
cross_v3_v3v3(src_trinormorg, srcside1, srcside2);
|
||||
cross_v3_v3v3(dest_trinormorg, destside1, destside2);
|
||||
|
||||
normalize_v3(src_trinormorg);
|
||||
normalize_v3(dest_trinormorg);
|
||||
|
||||
copy_v3_v3(src_trinorm, src_trinormorg);
|
||||
copy_v3_v3(dest_trinorm, dest_trinormorg);
|
||||
|
||||
mul_v3_fl(src_trinorm, 0.25 * cell_len);
|
||||
mul_v3_fl(dest_trinorm, 0.25 * cell_len);
|
||||
|
||||
for(j = 0; j <= divs1; j++)
|
||||
{
|
||||
for(k = 0; k <= divs2; k++)
|
||||
{
|
||||
float src_p1[3], src_p2[3], src_p3[3], src_p[3]={0,0,0};
|
||||
float dest_p1[3], dest_p2[3], dest_p3[3], dest_p[3]={0,0,0};
|
||||
const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0);
|
||||
const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0);
|
||||
float src_tmpvec[3], dest_tmpvec[3];
|
||||
|
||||
if(uf+vf > 1.0)
|
||||
{
|
||||
// printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
|
||||
continue;
|
||||
}
|
||||
|
||||
copy_v3_v3(src_p1, &scs->points_old[mface[i].v1 * 3]);
|
||||
copy_v3_v3(dest_p1, &scs->points[mface[i].v1 * 3]);
|
||||
if(again == 1 && mface[i].v4)
|
||||
{
|
||||
copy_v3_v3(src_p2, &scs->points_old[mface[i].v3 * 3]);
|
||||
copy_v3_v3(dest_p2, &scs->points[mface[i].v3 * 3]);
|
||||
|
||||
copy_v3_v3(src_p3,&scs->points_old[mface[i].v4 * 3]);
|
||||
copy_v3_v3(dest_p3, &scs->points[mface[i].v4 * 3]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(src_p2, &scs->points_old[mface[i].v2 * 3]);
|
||||
copy_v3_v3(dest_p2, &scs->points[mface[i].v2 * 3]);
|
||||
copy_v3_v3(src_p3, &scs->points_old[mface[i].v3 * 3]);
|
||||
copy_v3_v3(dest_p3, &scs->points[mface[i].v3 * 3]);
|
||||
}
|
||||
|
||||
mul_v3_fl(src_p1, (1.0-uf-vf));
|
||||
mul_v3_fl(dest_p1, (1.0-uf-vf));
|
||||
|
||||
mul_v3_fl(src_p2, uf);
|
||||
mul_v3_fl(dest_p2, uf);
|
||||
|
||||
mul_v3_fl(src_p3, vf);
|
||||
mul_v3_fl(dest_p3, vf);
|
||||
|
||||
add_v3_v3v3(src_p, src_p1, src_p2);
|
||||
add_v3_v3v3(dest_p, dest_p1, dest_p2);
|
||||
|
||||
add_v3_v3(src_p, src_p3);
|
||||
add_v3_v3(dest_p, dest_p3);
|
||||
|
||||
if(newdivs > divs)
|
||||
printf("mem problem\n");
|
||||
|
||||
// mMovPoints.push_back(p + trinorm);
|
||||
add_v3_v3v3(src_tmpvec, src_p, src_trinorm);
|
||||
add_v3_v3v3(dest_tmpvec, dest_p, dest_trinorm);
|
||||
|
||||
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
|
||||
copy_v3_v3(&scs->points_old[3 * (dm->getNumVerts(dm) + newdivs)], src_tmpvec);
|
||||
copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], dest_tmpvec);
|
||||
newdivs++;
|
||||
|
||||
if(newdivs > divs)
|
||||
printf("mem problem\n");
|
||||
|
||||
// mMovPoints.push_back(p - trinorm);
|
||||
copy_v3_v3(src_tmpvec, src_p);
|
||||
copy_v3_v3(dest_tmpvec, dest_p);
|
||||
|
||||
sub_v3_v3(src_tmpvec, src_trinorm);
|
||||
sub_v3_v3(dest_tmpvec, dest_trinorm);
|
||||
|
||||
// mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway
|
||||
copy_v3_v3(&scs->points_old[3 * (dm->getNumVerts(dm) + newdivs)], src_tmpvec);
|
||||
copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], dest_tmpvec);
|
||||
newdivs++;
|
||||
}
|
||||
}
|
||||
|
||||
if(again == 0 && mface[i].v4)
|
||||
again++;
|
||||
else
|
||||
again = 0;
|
||||
|
||||
facecounter++;
|
||||
|
||||
} while(again!=0);
|
||||
}
|
||||
|
||||
// scs->numpoints = dm->getNumVerts(dm) + newdivs;
|
||||
|
||||
}
|
||||
|
||||
/*! init triangle divisions */
|
||||
@@ -472,22 +653,22 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
|
||||
// mTriangleDivs3.resize( faces.size() );
|
||||
|
||||
size_t i = 0, facecounter = 0;
|
||||
float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale);
|
||||
float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale); get max scale value
|
||||
float maxpart = ABS(maxscale[0]);
|
||||
float scaleFac = 0;
|
||||
float fsTri = 0;
|
||||
if (ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
|
||||
if (ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
|
||||
if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
|
||||
if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
|
||||
scaleFac = 1.0 / maxpart;
|
||||
// featureSize = mLevel[mMaxRefine].nodeSize
|
||||
fsTri = cell_len * 0.5 * scaleFac;
|
||||
fsTri = cell_len * 0.75 * scaleFac; // fsTri = cell_len * 0.9;
|
||||
|
||||
if (*tridivs)
|
||||
if(*tridivs)
|
||||
MEM_freeN(*tridivs);
|
||||
|
||||
*tridivs = MEM_callocN(sizeof(int) * numtris * 3, "Smoke_Tridivs");
|
||||
|
||||
for (i = 0, facecounter = 0; i < numfaces; i++)
|
||||
for(i = 0, facecounter = 0; i < numfaces; i++)
|
||||
{
|
||||
float p0[3], p1[3], p2[3];
|
||||
float side1[3];
|
||||
@@ -506,21 +687,22 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
|
||||
sub_v3_v3v3(side2, p2, p0);
|
||||
sub_v3_v3v3(side3, p1, p2);
|
||||
|
||||
if (dot_v3v3(side1, side1) > fsTri*fsTri)
|
||||
if(dot_v3v3(side1, side1) > fsTri*fsTri)
|
||||
{
|
||||
float tmp = normalize_v3(side1);
|
||||
divs1 = (int)ceil(tmp/fsTri);
|
||||
}
|
||||
if (dot_v3v3(side2, side2) > fsTri*fsTri)
|
||||
if(dot_v3v3(side2, side2) > fsTri*fsTri)
|
||||
{
|
||||
float tmp = normalize_v3(side2);
|
||||
divs2 = (int)ceil(tmp/fsTri);
|
||||
|
||||
/*
|
||||
/*
|
||||
// debug
|
||||
if (i==0)
|
||||
if(i==0)
|
||||
printf("b tmp: %f, fsTri: %f, divs2: %d\n", tmp, fsTri, divs2);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
(*tridivs)[3 * facecounter + 0] = divs1;
|
||||
@@ -528,7 +710,7 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
|
||||
(*tridivs)[3 * facecounter + 2] = divs3;
|
||||
|
||||
// TODO quad case
|
||||
if (faces[i].v4)
|
||||
if(faces[i].v4)
|
||||
{
|
||||
divs1=0, divs2=0, divs3=0;
|
||||
|
||||
@@ -545,12 +727,12 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
|
||||
sub_v3_v3v3(side2, p2, p0);
|
||||
sub_v3_v3v3(side3, p1, p2);
|
||||
|
||||
if (dot_v3v3(side1, side1) > fsTri*fsTri)
|
||||
if(dot_v3v3(side1, side1) > fsTri*fsTri)
|
||||
{
|
||||
float tmp = normalize_v3(side1);
|
||||
divs1 = (int)ceil(tmp/fsTri);
|
||||
}
|
||||
if (dot_v3v3(side2, side2) > fsTri*fsTri)
|
||||
if(dot_v3v3(side2, side2) > fsTri*fsTri)
|
||||
{
|
||||
float tmp = normalize_v3(side2);
|
||||
divs2 = (int)ceil(tmp/fsTri);
|
||||
@@ -568,19 +750,19 @@ static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFa
|
||||
|
||||
static void smokeModifier_freeDomain(SmokeModifierData *smd)
|
||||
{
|
||||
if (smd->domain)
|
||||
if(smd->domain)
|
||||
{
|
||||
if (smd->domain->shadow)
|
||||
if(smd->domain->shadow)
|
||||
MEM_freeN(smd->domain->shadow);
|
||||
smd->domain->shadow = NULL;
|
||||
|
||||
if (smd->domain->fluid)
|
||||
if(smd->domain->fluid)
|
||||
smoke_free(smd->domain->fluid);
|
||||
|
||||
if (smd->domain->wt)
|
||||
if(smd->domain->wt)
|
||||
smoke_turbulence_free(smd->domain->wt);
|
||||
|
||||
if (smd->domain->effector_weights)
|
||||
if(smd->domain->effector_weights)
|
||||
MEM_freeN(smd->domain->effector_weights);
|
||||
smd->domain->effector_weights = NULL;
|
||||
|
||||
@@ -594,10 +776,10 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd)
|
||||
|
||||
static void smokeModifier_freeFlow(SmokeModifierData *smd)
|
||||
{
|
||||
if (smd->flow)
|
||||
if(smd->flow)
|
||||
{
|
||||
/*
|
||||
if (smd->flow->bvh)
|
||||
if(smd->flow->bvh)
|
||||
{
|
||||
free_bvhtree_from_mesh(smd->flow->bvh);
|
||||
MEM_freeN(smd->flow->bvh);
|
||||
@@ -611,22 +793,37 @@ static void smokeModifier_freeFlow(SmokeModifierData *smd)
|
||||
|
||||
static void smokeModifier_freeCollision(SmokeModifierData *smd)
|
||||
{
|
||||
if (smd->coll)
|
||||
if(smd->coll)
|
||||
{
|
||||
if (smd->coll->points)
|
||||
SmokeCollSettings *scs = smd->coll;
|
||||
|
||||
if(scs->numpoints)
|
||||
{
|
||||
MEM_freeN(smd->coll->points);
|
||||
smd->coll->points = NULL;
|
||||
if(scs->points)
|
||||
{
|
||||
MEM_freeN(scs->points);
|
||||
scs->points = NULL;
|
||||
}
|
||||
if(scs->points_old)
|
||||
{
|
||||
MEM_freeN(scs->points_old);
|
||||
scs->points_old = NULL;
|
||||
}
|
||||
if(scs->tridivs)
|
||||
{
|
||||
MEM_freeN(scs->tridivs);
|
||||
scs->tridivs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (smd->coll->bvhtree)
|
||||
if(scs->bvhtree)
|
||||
{
|
||||
BLI_bvhtree_free(smd->coll->bvhtree);
|
||||
smd->coll->bvhtree = NULL;
|
||||
BLI_bvhtree_free(scs->bvhtree);
|
||||
scs->bvhtree = NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_SMOKE_COLLISION_DM
|
||||
if (smd->coll->dm)
|
||||
if(smd->coll->dm)
|
||||
smd->coll->dm->release(smd->coll->dm);
|
||||
smd->coll->dm = NULL;
|
||||
#endif
|
||||
@@ -638,7 +835,7 @@ static void smokeModifier_freeCollision(SmokeModifierData *smd)
|
||||
|
||||
void smokeModifier_reset_turbulence(struct SmokeModifierData *smd)
|
||||
{
|
||||
if (smd && smd->domain && smd->domain->wt)
|
||||
if(smd && smd->domain && smd->domain->wt)
|
||||
{
|
||||
smoke_turbulence_free(smd->domain->wt);
|
||||
smd->domain->wt = NULL;
|
||||
@@ -647,15 +844,15 @@ void smokeModifier_reset_turbulence(struct SmokeModifierData *smd)
|
||||
|
||||
void smokeModifier_reset(struct SmokeModifierData *smd)
|
||||
{
|
||||
if (smd)
|
||||
if(smd)
|
||||
{
|
||||
if (smd->domain)
|
||||
if(smd->domain)
|
||||
{
|
||||
if (smd->domain->shadow)
|
||||
if(smd->domain->shadow)
|
||||
MEM_freeN(smd->domain->shadow);
|
||||
smd->domain->shadow = NULL;
|
||||
|
||||
if (smd->domain->fluid)
|
||||
if(smd->domain->fluid)
|
||||
{
|
||||
smoke_free(smd->domain->fluid);
|
||||
smd->domain->fluid = NULL;
|
||||
@@ -667,10 +864,10 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
|
||||
|
||||
// printf("reset domain end\n");
|
||||
}
|
||||
else if (smd->flow)
|
||||
else if(smd->flow)
|
||||
{
|
||||
/*
|
||||
if (smd->flow->bvh)
|
||||
if(smd->flow->bvh)
|
||||
{
|
||||
free_bvhtree_from_mesh(smd->flow->bvh);
|
||||
MEM_freeN(smd->flow->bvh);
|
||||
@@ -678,33 +875,33 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
|
||||
smd->flow->bvh = NULL;
|
||||
*/
|
||||
}
|
||||
else if (smd->coll)
|
||||
else if(smd->coll)
|
||||
{
|
||||
if (smd->coll->points)
|
||||
SmokeCollSettings *scs = smd->coll;
|
||||
|
||||
if(scs->numpoints && scs->points)
|
||||
{
|
||||
MEM_freeN(smd->coll->points);
|
||||
smd->coll->points = NULL;
|
||||
MEM_freeN(scs->points);
|
||||
scs->points = NULL;
|
||||
|
||||
if(scs->points_old)
|
||||
{
|
||||
MEM_freeN(scs->points_old);
|
||||
scs->points_old = NULL;
|
||||
}
|
||||
if(scs->tridivs)
|
||||
{
|
||||
MEM_freeN(scs->tridivs);
|
||||
scs->tridivs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (smd->coll->bvhtree)
|
||||
{
|
||||
BLI_bvhtree_free(smd->coll->bvhtree);
|
||||
smd->coll->bvhtree = NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_SMOKE_COLLISION_DM
|
||||
if (smd->coll->dm)
|
||||
smd->coll->dm->release(smd->coll->dm);
|
||||
smd->coll->dm = NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void smokeModifier_free (SmokeModifierData *smd)
|
||||
{
|
||||
if (smd)
|
||||
if(smd)
|
||||
{
|
||||
smokeModifier_freeDomain(smd);
|
||||
smokeModifier_freeFlow(smd);
|
||||
@@ -714,11 +911,11 @@ void smokeModifier_free (SmokeModifierData *smd)
|
||||
|
||||
void smokeModifier_createType(struct SmokeModifierData *smd)
|
||||
{
|
||||
if (smd)
|
||||
if(smd)
|
||||
{
|
||||
if (smd->type & MOD_SMOKE_TYPE_DOMAIN)
|
||||
if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
|
||||
{
|
||||
if (smd->domain)
|
||||
if(smd->domain)
|
||||
smokeModifier_freeDomain(smd);
|
||||
|
||||
smd->domain = MEM_callocN(sizeof(SmokeDomainSettings), "SmokeDomain");
|
||||
@@ -745,7 +942,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
|
||||
smd->domain->beta = 0.1;
|
||||
smd->domain->time_scale = 1.0;
|
||||
smd->domain->vorticity = 2.0;
|
||||
smd->domain->border_collisions = 1; // vertically non-colliding
|
||||
smd->domain->border_collisions = SM_BORDER_OPEN; // open domain
|
||||
smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG | MOD_SMOKE_HIGH_SMOOTH;
|
||||
smd->domain->strength = 2.0;
|
||||
smd->domain->noise = MOD_SMOKE_NOISEWAVE;
|
||||
@@ -755,9 +952,9 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
|
||||
smd->domain->viewsettings = MOD_SMOKE_VIEW_SHOWBIG;
|
||||
smd->domain->effector_weights = BKE_add_effector_weights(NULL);
|
||||
}
|
||||
else if (smd->type & MOD_SMOKE_TYPE_FLOW)
|
||||
else if(smd->type & MOD_SMOKE_TYPE_FLOW)
|
||||
{
|
||||
if (smd->flow)
|
||||
if(smd->flow)
|
||||
smokeModifier_freeFlow(smd);
|
||||
|
||||
smd->flow = MEM_callocN(sizeof(SmokeFlowSettings), "SmokeFlow");
|
||||
@@ -773,17 +970,23 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
|
||||
smd->flow->psys = NULL;
|
||||
|
||||
}
|
||||
else if (smd->type & MOD_SMOKE_TYPE_COLL)
|
||||
else if(smd->type & MOD_SMOKE_TYPE_COLL)
|
||||
{
|
||||
if (smd->coll)
|
||||
if(smd->coll)
|
||||
smokeModifier_freeCollision(smd);
|
||||
|
||||
smd->coll = MEM_callocN(sizeof(SmokeCollSettings), "SmokeColl");
|
||||
|
||||
smd->coll->smd = smd;
|
||||
smd->coll->points = NULL;
|
||||
smd->coll->points_old = NULL;
|
||||
smd->coll->tridivs = NULL;
|
||||
smd->coll->vel = NULL;
|
||||
smd->coll->numpoints = 0;
|
||||
smd->coll->numtris = 0;
|
||||
smd->coll->bvhtree = NULL;
|
||||
smd->coll->type = 0; // static obstacle
|
||||
smd->coll->dx = 1.0f / 50.0f;
|
||||
|
||||
#ifdef USE_SMOKE_COLLISION_DM
|
||||
smd->coll->dm = NULL;
|
||||
@@ -818,7 +1021,7 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
|
||||
|
||||
MEM_freeN(tsmd->domain->effector_weights);
|
||||
tsmd->domain->effector_weights = MEM_dupallocN(smd->domain->effector_weights);
|
||||
}
|
||||
}
|
||||
else if (tsmd->flow) {
|
||||
tsmd->flow->density = smd->flow->density;
|
||||
tsmd->flow->temp = smd->flow->temp;
|
||||
@@ -845,15 +1048,15 @@ static int get_lamp(Scene *scene, float *light)
|
||||
int found_lamp = 0;
|
||||
|
||||
// try to find a lamp, preferably local
|
||||
for (base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) {
|
||||
if (base_tmp->object->type == OB_LAMP) {
|
||||
for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) {
|
||||
if(base_tmp->object->type == OB_LAMP) {
|
||||
Lamp *la = base_tmp->object->data;
|
||||
|
||||
if (la->type == LA_LOCAL) {
|
||||
if(la->type == LA_LOCAL) {
|
||||
copy_v3_v3(light, base_tmp->object->obmat[3]);
|
||||
return 1;
|
||||
}
|
||||
else if (!found_lamp) {
|
||||
else if(!found_lamp) {
|
||||
copy_v3_v3(light, base_tmp->object->obmat[3]);
|
||||
found_lamp = 1;
|
||||
}
|
||||
@@ -863,499 +1066,605 @@ static int get_lamp(Scene *scene, float *light)
|
||||
return found_lamp;
|
||||
}
|
||||
|
||||
static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
|
||||
static void smoke_calc_domain(Scene *UNUSED(scene), Object *UNUSED(ob), SmokeModifierData *UNUSED(smd))
|
||||
{
|
||||
#if 0
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
GroupObject *go = NULL;
|
||||
Base *base = NULL;
|
||||
Base *base = NULL;
|
||||
|
||||
// do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells
|
||||
if (1)
|
||||
/* do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells */
|
||||
if(1)
|
||||
{
|
||||
Object *otherobj = NULL;
|
||||
ModifierData *md = NULL;
|
||||
unsigned int i;
|
||||
Object **collobjs = NULL;
|
||||
unsigned int numcollobj = 0;
|
||||
collobjs = get_collisionobjects(scene, ob, sds->coll_group, &numcollobj);
|
||||
|
||||
if (sds->coll_group) // we use groups since we have 2 domains
|
||||
go = sds->coll_group->gobject.first;
|
||||
else
|
||||
base = scene->base.first;
|
||||
|
||||
while (base || go)
|
||||
for(i = 0; i < numcollobj; i++)
|
||||
{
|
||||
otherobj = NULL;
|
||||
if (sds->coll_group)
|
||||
{
|
||||
if (go->ob)
|
||||
otherobj = go->ob;
|
||||
}
|
||||
else
|
||||
otherobj = base->object;
|
||||
if (!otherobj)
|
||||
{
|
||||
if (sds->coll_group)
|
||||
go = go->next;
|
||||
else
|
||||
base= base->next;
|
||||
continue;
|
||||
}
|
||||
md = modifiers_findByType(otherobj, eModifierType_Smoke);
|
||||
Object *collob= collobjs[i];
|
||||
SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke);
|
||||
|
||||
// check for active smoke modifier
|
||||
if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
|
||||
// if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
|
||||
// SmokeModifierData *smd2 = (SmokeModifierData *)md;
|
||||
|
||||
if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points && smd2->coll->points_old)
|
||||
{
|
||||
SmokeModifierData *smd2 = (SmokeModifierData *)md;
|
||||
// ??? anything to do here?
|
||||
|
||||
if ((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points)
|
||||
// TODO: only something to do for ANIMATED obstacles: need to update positions
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(collobjs)
|
||||
MEM_freeN(collobjs);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Animated obstacles: dx_step = ((x_new - x_old) / totalsteps) * substep */
|
||||
static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt, int substep, int totalsteps)
|
||||
{
|
||||
Object **collobjs = NULL;
|
||||
unsigned int numcollobj = 0;
|
||||
|
||||
unsigned int collIndex;
|
||||
unsigned char *obstacles = smoke_get_obstacle(sds->fluid);
|
||||
float *velx = NULL;
|
||||
float *vely = NULL;
|
||||
float *velz = NULL;
|
||||
float *velxOrig = smoke_get_velocity_x(sds->fluid);
|
||||
float *velyOrig = smoke_get_velocity_y(sds->fluid);
|
||||
float *velzOrig = smoke_get_velocity_z(sds->fluid);
|
||||
// float *density = smoke_get_density(sds->fluid);
|
||||
unsigned int z;
|
||||
|
||||
smoke_get_ob_velocity(sds->fluid, &velx, &vely, &velz);
|
||||
|
||||
// TODO: delete old obstacle flags
|
||||
for(z = 0; z < sds->res[0] * sds->res[1] * sds->res[2]; z++)
|
||||
{
|
||||
if(obstacles[z])
|
||||
{
|
||||
// density[z] = 0;
|
||||
|
||||
velxOrig[z] = 0;
|
||||
velyOrig[z] = 0;
|
||||
velzOrig[z] = 0;
|
||||
}
|
||||
|
||||
if(obstacles[z] & 8) // Do not delete static obstacles
|
||||
{
|
||||
obstacles[z] = 0;
|
||||
}
|
||||
|
||||
velx[z] = 0;
|
||||
vely[z] = 0;
|
||||
velz[z] = 0;
|
||||
}
|
||||
|
||||
collobjs = get_collisionobjects(scene, ob, sds->coll_group, &numcollobj, eModifierType_Smoke);
|
||||
|
||||
// update obstacle tags in cells
|
||||
for(collIndex = 0; collIndex < numcollobj; collIndex++)
|
||||
{
|
||||
Object *collob= collobjs[collIndex];
|
||||
SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke);
|
||||
|
||||
// DG TODO: check if modifier is active?
|
||||
|
||||
if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points && smd2->coll->points_old)
|
||||
{
|
||||
SmokeCollSettings *scs = smd2->coll;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
// DG TODO: support static cobstacles, but basicly we could even support static + rigid with one set of code
|
||||
if(scs->type > SM_COLL_STATIC)
|
||||
*/
|
||||
|
||||
/* Handle collisions */
|
||||
for(i = 0; i < scs->numpoints; i++)
|
||||
{
|
||||
// 1. get corresponding cell
|
||||
int cell[3];
|
||||
float pos[3], oldpos[3], vel[3];
|
||||
float cPos[3], cOldpos[3]; /* current position in substeps */
|
||||
int badcell = 0;
|
||||
size_t index;
|
||||
int j;
|
||||
|
||||
// translate local points into global positions
|
||||
copy_v3_v3(cPos, &scs->points[3 * i]);
|
||||
mul_m4_v3(scs->mat, cPos);
|
||||
copy_v3_v3(pos, cPos);
|
||||
|
||||
copy_v3_v3(cOldpos, &scs->points_old[3 * i]);
|
||||
mul_m4_v3(scs->mat_old, cOldpos);
|
||||
copy_v3_v3(oldpos, cOldpos);
|
||||
|
||||
/* support for rigid bodies, armatures etc */
|
||||
{
|
||||
// we got nice collision object
|
||||
SmokeCollSettings *scs = smd2->coll;
|
||||
size_t i, j;
|
||||
unsigned char *obstacles = smoke_get_obstacle(smd->domain->fluid);
|
||||
float tmp[3];
|
||||
|
||||
for (i = 0; i < scs->numpoints; i++)
|
||||
/* x_current = x_old + (x_new - x_old) * step_current / steps_total */
|
||||
float mulStep = (float)(((float)substep) / ((float)totalsteps));
|
||||
|
||||
sub_v3_v3v3(tmp, cPos, cOldpos);
|
||||
mul_v3_fl(tmp, mulStep);
|
||||
add_v3_v3(cOldpos, tmp);
|
||||
}
|
||||
|
||||
sub_v3_v3v3(vel, pos, oldpos);
|
||||
/* Scale velocity to incorperate the object movement during this step */
|
||||
mul_v3_fl(vel, 1.0 / (totalsteps * dt));
|
||||
// mul_v3_fl(vel, 1.0 / dt);
|
||||
|
||||
// DG TODO: cap velocity to maxVelMag (or maxvel)
|
||||
|
||||
// oldpos + velocity * dt = newpos
|
||||
get_cell(sds->p0, sds->res, sds->dx, cOldpos /* use current position here instead of "pos" */, cell, 0);
|
||||
|
||||
// check if cell is valid (in the domain boundary)
|
||||
for(j = 0; j < 3; j++)
|
||||
if((cell[j] > sds->res[j] - 1) || (cell[j] < 0))
|
||||
{
|
||||
int badcell = 0;
|
||||
size_t index = 0;
|
||||
int cell[3];
|
||||
|
||||
// 1. get corresponding cell
|
||||
get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, &scs->points[3 * i], cell, 0);
|
||||
|
||||
// check if cell is valid (in the domain boundary)
|
||||
for (j = 0; j < 3; j++)
|
||||
if ((cell[j] > sds->res[j] - 1) || (cell[j] < 0))
|
||||
{
|
||||
badcell = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (badcell)
|
||||
continue;
|
||||
// 2. set cell values (heat, density and velocity)
|
||||
index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
|
||||
|
||||
// printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]);
|
||||
// printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index);
|
||||
obstacles[index] = 1;
|
||||
// for moving gobstacles
|
||||
/*
|
||||
const LbmFloat maxVelVal = 0.1666;
|
||||
const LbmFloat maxusqr = maxVelVal*maxVelVal*3. *1.5;
|
||||
|
||||
LbmVec objvel = vec2L((mMOIVertices[n]-mMOIVerticesOld[n]) /dvec);
|
||||
{
|
||||
const LbmFloat usqr = (objvel[0]*objvel[0]+objvel[1]*objvel[1]+objvel[2]*objvel[2])*1.5;
|
||||
USQRMAXCHECK(usqr, objvel[0],objvel[1],objvel[2], mMaxVlen, mMxvx,mMxvy,mMxvz);
|
||||
if (usqr>maxusqr) {
|
||||
// cutoff at maxVelVal
|
||||
for (int jj=0; jj<3; jj++) {
|
||||
if (objvel[jj] > 0.0) objvel[jj] = maxVelVal;
|
||||
if (objvel[jj] < 0.0) objvel[jj] = -maxVelVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
const LbmFloat dp=dot(objvel, vec2L((*pNormals)[n]) );
|
||||
const LbmVec oldov=objvel; // debug
|
||||
objvel = vec2L((*pNormals)[n]) *dp;
|
||||
*/
|
||||
badcell = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(badcell)
|
||||
continue;
|
||||
|
||||
// 2. set cell values (heat, density and velocity)
|
||||
index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
|
||||
|
||||
// Don't overwrite existing obstacles
|
||||
if(obstacles[index])
|
||||
continue;
|
||||
|
||||
// printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]);
|
||||
// printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index);
|
||||
obstacles[index] = 1 | 8 /* ANIMATED */;
|
||||
|
||||
if(len_v3(vel) > FLT_EPSILON)
|
||||
{
|
||||
// Collision object is moving
|
||||
|
||||
velx[index] = vel[0]; // use "+="?
|
||||
vely[index] = vel[1];
|
||||
velz[index] = vel[2];
|
||||
}
|
||||
}
|
||||
|
||||
if (sds->coll_group)
|
||||
go = go->next;
|
||||
else
|
||||
base= base->next;
|
||||
}
|
||||
}
|
||||
|
||||
// do flows and fluids
|
||||
if (1)
|
||||
if(collobjs)
|
||||
MEM_freeN(collobjs);
|
||||
}
|
||||
|
||||
static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float time)
|
||||
{
|
||||
Object **flowobjs = NULL;
|
||||
unsigned int numflowobj = 0;
|
||||
unsigned int flowIndex;
|
||||
|
||||
flowobjs = get_collisionobjects(scene, ob, sds->fluid_group, &numflowobj, eModifierType_Smoke);
|
||||
|
||||
// update obstacle tags in cells
|
||||
for(flowIndex = 0; flowIndex < numflowobj; flowIndex++)
|
||||
{
|
||||
Object *otherobj = NULL;
|
||||
ModifierData *md = NULL;
|
||||
if (sds->fluid_group) // we use groups since we have 2 domains
|
||||
go = sds->fluid_group->gobject.first;
|
||||
else
|
||||
base = scene->base.first;
|
||||
while (base || go)
|
||||
{
|
||||
otherobj = NULL;
|
||||
if (sds->fluid_group)
|
||||
{
|
||||
if (go->ob)
|
||||
otherobj = go->ob;
|
||||
}
|
||||
else
|
||||
otherobj = base->object;
|
||||
if (!otherobj)
|
||||
{
|
||||
if (sds->fluid_group)
|
||||
go = go->next;
|
||||
else
|
||||
base= base->next;
|
||||
Object *collob= flowobjs[flowIndex];
|
||||
SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke);
|
||||
|
||||
continue;
|
||||
}
|
||||
// check for initialized smoke object
|
||||
if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
|
||||
{
|
||||
// we got nice flow object
|
||||
SmokeFlowSettings *sfs = smd2->flow;
|
||||
|
||||
md = modifiers_findByType(otherobj, eModifierType_Smoke);
|
||||
|
||||
// check for active smoke modifier
|
||||
if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render))
|
||||
if(sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected
|
||||
{
|
||||
SmokeModifierData *smd2 = (SmokeModifierData *)md;
|
||||
|
||||
// check for initialized smoke object
|
||||
if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow)
|
||||
ParticleSimulationData sim;
|
||||
ParticleSystem *psys = sfs->psys;
|
||||
int totpart=psys->totpart, totchild;
|
||||
int p = 0;
|
||||
float *density = smoke_get_density(sds->fluid);
|
||||
float *bigdensity = smoke_turbulence_get_density(sds->wt);
|
||||
float *heat = smoke_get_heat(sds->fluid);
|
||||
float *velocity_x = smoke_get_velocity_x(sds->fluid);
|
||||
float *velocity_y = smoke_get_velocity_y(sds->fluid);
|
||||
float *velocity_z = smoke_get_velocity_z(sds->fluid);
|
||||
unsigned char *obstacle = smoke_get_obstacle(sds->fluid);
|
||||
// DG TODO UNUSED unsigned char *obstacleAnim = smoke_get_obstacle_anim(sds->fluid);
|
||||
int bigres[3];
|
||||
short absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE);
|
||||
short high_emission_smoothing = bigdensity ? (sds->flags & MOD_SMOKE_HIGH_SMOOTH) : 0;
|
||||
|
||||
/*
|
||||
* A temporary volume map used to store whole emissive
|
||||
* area to be added to smoke density and interpolated
|
||||
* for high resolution smoke.
|
||||
*/
|
||||
float *temp_emission_map = NULL;
|
||||
|
||||
sim.scene = scene;
|
||||
sim.ob = collob;
|
||||
sim.psys = psys;
|
||||
|
||||
// initialize temp emission map
|
||||
if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
|
||||
{
|
||||
// we got nice flow object
|
||||
SmokeFlowSettings *sfs = smd2->flow;
|
||||
|
||||
if (sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected
|
||||
int i;
|
||||
temp_emission_map = MEM_callocN(sizeof(float) * sds->res[0]*sds->res[1]*sds->res[2], "SmokeTempEmission");
|
||||
// set whole volume to 0.0f
|
||||
for (i=0; i<sds->res[0]*sds->res[1]*sds->res[2]; i++) {
|
||||
temp_emission_map[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// mostly copied from particle code
|
||||
if(psys->part->type==PART_HAIR)
|
||||
{
|
||||
/*
|
||||
if(psys->childcache)
|
||||
{
|
||||
ParticleSimulationData sim;
|
||||
ParticleSystem *psys = sfs->psys;
|
||||
int totpart=psys->totpart, totchild;
|
||||
int p = 0;
|
||||
float *density = smoke_get_density(sds->fluid);
|
||||
float *bigdensity = smoke_turbulence_get_density(sds->wt);
|
||||
float *heat = smoke_get_heat(sds->fluid);
|
||||
float *velocity_x = smoke_get_velocity_x(sds->fluid);
|
||||
float *velocity_y = smoke_get_velocity_y(sds->fluid);
|
||||
float *velocity_z = smoke_get_velocity_z(sds->fluid);
|
||||
unsigned char *obstacle = smoke_get_obstacle(sds->fluid);
|
||||
int bigres[3];
|
||||
short absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE);
|
||||
short high_emission_smoothing = bigdensity ? (smd->domain->flags & MOD_SMOKE_HIGH_SMOOTH) : 0;
|
||||
totchild = psys->totchildcache;
|
||||
}
|
||||
else
|
||||
*/
|
||||
|
||||
/*
|
||||
* A temporary volume map used to store whole emissive
|
||||
* area to be added to smoke density and interpolated
|
||||
* for high resolution smoke.
|
||||
*/
|
||||
float *temp_emission_map = NULL;
|
||||
// TODO: PART_HAIR not supported whatsoever
|
||||
totchild=0;
|
||||
}
|
||||
else
|
||||
totchild=psys->totchild*psys->part->disp/100;
|
||||
|
||||
sim.scene = scene;
|
||||
sim.ob = otherobj;
|
||||
sim.psys = psys;
|
||||
for(p=0; p<totpart+totchild; p++)
|
||||
{
|
||||
int cell[3];
|
||||
size_t i = 0;
|
||||
size_t index = 0;
|
||||
int badcell = 0;
|
||||
ParticleKey state;
|
||||
|
||||
// initialize temp emission map
|
||||
if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
|
||||
if(p < totpart)
|
||||
{
|
||||
if(psys->particles[p].flag & (PARS_NO_DISP|PARS_UNEXIST))
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
/* handle child particle */
|
||||
ChildParticle *cpa = &psys->child[p - totpart];
|
||||
|
||||
if(psys->particles[cpa->parent].flag & (PARS_NO_DISP|PARS_UNEXIST))
|
||||
continue;
|
||||
}
|
||||
|
||||
state.time = time;
|
||||
if(psys_get_particle_state(&sim, p, &state, 0) == 0)
|
||||
continue;
|
||||
|
||||
// copy_v3_v3(pos, pa->state.co);
|
||||
// mul_m4_v3(ob->imat, pos);
|
||||
// 1. get corresponding cell
|
||||
get_cell(sds->p0, sds->res, sds->dx, state.co, cell, 0);
|
||||
// check if cell is valid (in the domain boundary)
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
if((cell[i] > sds->res[i] - 1) || (cell[i] < 0))
|
||||
{
|
||||
badcell = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(badcell)
|
||||
continue;
|
||||
// 2. set cell values (heat, density and velocity)
|
||||
index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
|
||||
if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // this is inflow
|
||||
{
|
||||
// heat[index] += sfs->temp * 0.1;
|
||||
// density[index] += sfs->density * 0.1;
|
||||
heat[index] = sfs->temp;
|
||||
|
||||
// Add emitter density to temp emission map
|
||||
temp_emission_map[index] = sfs->density;
|
||||
|
||||
// Uses particle velocity as initial velocity for smoke
|
||||
if(sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO))
|
||||
{
|
||||
int i;
|
||||
temp_emission_map = MEM_callocN(sizeof(float) * sds->res[0]*sds->res[1]*sds->res[2], "SmokeTempEmission");
|
||||
// set whole volume to 0.0f
|
||||
for (i=0; i<sds->res[0]*sds->res[1]*sds->res[2]; i++) {
|
||||
temp_emission_map[i] = 0.0f;
|
||||
}
|
||||
velocity_x[index] = state.vel[0]*sfs->vel_multi;
|
||||
velocity_y[index] = state.vel[1]*sfs->vel_multi;
|
||||
velocity_z[index] = state.vel[2]*sfs->vel_multi;
|
||||
}
|
||||
}
|
||||
else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow
|
||||
{
|
||||
heat[index] = 0.f;
|
||||
density[index] = 0.f;
|
||||
velocity_x[index] = 0.f;
|
||||
velocity_y[index] = 0.f;
|
||||
velocity_z[index] = 0.f;
|
||||
// we need different handling for the high-res feature
|
||||
if(bigdensity)
|
||||
{
|
||||
// init all surrounding cells according to amplification, too
|
||||
int i, j, k;
|
||||
smoke_turbulence_get_res(sds->wt, bigres);
|
||||
|
||||
for(i = 0; i < sds->amplify + 1; i++)
|
||||
for(j = 0; j < sds->amplify + 1; j++)
|
||||
for(k = 0; k < sds->amplify + 1; k++)
|
||||
{
|
||||
index = smoke_get_index((sds->amplify + 1)* cell[0] + i, bigres[0], (sds->amplify + 1)* cell[1] + j, bigres[1], (sds->amplify + 1)* cell[2] + k);
|
||||
bigdensity[index] = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
// mostly copied from particle code
|
||||
if (psys->part->type==PART_HAIR)
|
||||
{
|
||||
/*
|
||||
if (psys->childcache)
|
||||
}
|
||||
} // particles loop
|
||||
|
||||
// apply emission values
|
||||
if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW))
|
||||
{
|
||||
// initialize variables
|
||||
int ii, jj, kk, x, y, z, block_size;
|
||||
size_t index, index_big;
|
||||
|
||||
smoke_turbulence_get_res(sds->wt, bigres);
|
||||
block_size = sds->amplify + 1; // high res block size
|
||||
|
||||
// loop through every low res cell
|
||||
for(x = 0; x < sds->res[0]; x++)
|
||||
for(y = 0; y < sds->res[1]; y++)
|
||||
for(z = 0; z < sds->res[2]; z++)
|
||||
{
|
||||
totchild = psys->totchildcache;
|
||||
}
|
||||
else
|
||||
*/
|
||||
// neighbor cell emission densities (for high resolution smoke smooth interpolation)
|
||||
float c000, c001, c010, c011, c100, c101, c110, c111;
|
||||
|
||||
// TODO: PART_HAIR not supported whatsoever
|
||||
totchild=0;
|
||||
}
|
||||
else
|
||||
totchild=psys->totchild*psys->part->disp/100;
|
||||
|
||||
for (p=0; p<totpart+totchild; p++)
|
||||
{
|
||||
int cell[3];
|
||||
size_t i = 0;
|
||||
size_t index = 0;
|
||||
int badcell = 0;
|
||||
ParticleKey state;
|
||||
c000 = (x>0 && y>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z-1)] : 0;
|
||||
c001 = (x>0 && y>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z)] : 0;
|
||||
c010 = (x>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z-1)] : 0;
|
||||
c011 = (x>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z)] : 0;
|
||||
|
||||
if (p < totpart)
|
||||
{
|
||||
if (psys->particles[p].flag & (PARS_NO_DISP|PARS_UNEXIST))
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
/* handle child particle */
|
||||
ChildParticle *cpa = &psys->child[p - totpart];
|
||||
|
||||
if (psys->particles[cpa->parent].flag & (PARS_NO_DISP|PARS_UNEXIST))
|
||||
continue;
|
||||
}
|
||||
c100 = (y>0 && z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z-1)] : 0;
|
||||
c101 = (y>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z)] : 0;
|
||||
c110 = (z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z-1)] : 0;
|
||||
c111 = temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z)]; // this cell
|
||||
|
||||
state.time = smd->time;
|
||||
if (psys_get_particle_state(&sim, p, &state, 0) == 0)
|
||||
continue;
|
||||
|
||||
// copy_v3_v3(pos, pa->state.co);
|
||||
// mul_m4_v3(ob->imat, pos);
|
||||
// 1. get corresponding cell
|
||||
get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, state.co, cell, 0);
|
||||
// check if cell is valid (in the domain boundary)
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if ((cell[i] > sds->res[i] - 1) || (cell[i] < 0))
|
||||
{
|
||||
badcell = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (badcell)
|
||||
continue;
|
||||
// 2. set cell values (heat, density and velocity)
|
||||
index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]);
|
||||
if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // this is inflow
|
||||
{
|
||||
// heat[index] += sfs->temp * 0.1;
|
||||
// density[index] += sfs->density * 0.1;
|
||||
heat[index] = sfs->temp;
|
||||
|
||||
// Add emitter density to temp emission map
|
||||
temp_emission_map[index] = sfs->density;
|
||||
// get cell index
|
||||
index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
|
||||
|
||||
// Uses particle velocity as initial velocity for smoke
|
||||
if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO))
|
||||
// add emission to low resolution density
|
||||
if (absolute_flow)
|
||||
{
|
||||
velocity_x[index] = state.vel[0]*sfs->vel_multi;
|
||||
velocity_y[index] = state.vel[1]*sfs->vel_multi;
|
||||
velocity_z[index] = state.vel[2]*sfs->vel_multi;
|
||||
}
|
||||
}
|
||||
else if (sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow
|
||||
{
|
||||
heat[index] = 0.f;
|
||||
density[index] = 0.f;
|
||||
velocity_x[index] = 0.f;
|
||||
velocity_y[index] = 0.f;
|
||||
velocity_z[index] = 0.f;
|
||||
// we need different handling for the high-res feature
|
||||
if (bigdensity)
|
||||
{
|
||||
// init all surrounding cells according to amplification, too
|
||||
int i, j, k;
|
||||
smoke_turbulence_get_res(smd->domain->wt, bigres);
|
||||
|
||||
for (i = 0; i < smd->domain->amplify + 1; i++)
|
||||
for (j = 0; j < smd->domain->amplify + 1; j++)
|
||||
for (k = 0; k < smd->domain->amplify + 1; k++)
|
||||
{
|
||||
index = smoke_get_index((smd->domain->amplify + 1)* cell[0] + i, bigres[0], (smd->domain->amplify + 1)* cell[1] + j, bigres[1], (smd->domain->amplify + 1)* cell[2] + k);
|
||||
bigdensity[index] = 0.f;
|
||||
}
|
||||
if (temp_emission_map[index]>0)
|
||||
density[index] = temp_emission_map[index];
|
||||
}
|
||||
}
|
||||
} // particles loop
|
||||
else
|
||||
{
|
||||
density[index] += temp_emission_map[index];
|
||||
|
||||
if (density[index]>1)
|
||||
density[index]=1.0f;
|
||||
}
|
||||
|
||||
// apply emission values
|
||||
if (!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) {
|
||||
smoke_turbulence_get_res(sds->wt, bigres);
|
||||
|
||||
// initialize variables
|
||||
int ii, jj, kk, x, y, z, block_size;
|
||||
size_t index, index_big;
|
||||
|
||||
smoke_turbulence_get_res(smd->domain->wt, bigres);
|
||||
block_size = smd->domain->amplify + 1; // high res block size
|
||||
|
||||
|
||||
// loop through every low res cell
|
||||
for (x = 0; x < sds->res[0]; x++)
|
||||
for (y = 0; y < sds->res[1]; y++)
|
||||
for (z = 0; z < sds->res[2]; z++)
|
||||
/* loop through high res blocks if high res enabled */
|
||||
if (bigdensity)
|
||||
for(ii = 0; ii < block_size; ii++)
|
||||
for(jj = 0; jj < block_size; jj++)
|
||||
for(kk = 0; kk < block_size; kk++)
|
||||
{
|
||||
|
||||
// neighbor cell emission densities (for high resolution smoke smooth interpolation)
|
||||
float c000, c001, c010, c011, c100, c101, c110, c111;
|
||||
|
||||
c000 = (x>0 && y>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z-1)] : 0;
|
||||
c001 = (x>0 && y>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z)] : 0;
|
||||
c010 = (x>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z-1)] : 0;
|
||||
c011 = (x>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z)] : 0;
|
||||
|
||||
c100 = (y>0 && z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z-1)] : 0;
|
||||
c101 = (y>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z)] : 0;
|
||||
c110 = (z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z-1)] : 0;
|
||||
c111 = temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z)]; // this cell
|
||||
|
||||
|
||||
|
||||
// get cell index
|
||||
index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
|
||||
|
||||
// add emission to low resolution density
|
||||
if (absolute_flow) {if (temp_emission_map[index]>0) density[index] = temp_emission_map[index];}
|
||||
else {
|
||||
density[index] += temp_emission_map[index];
|
||||
if (density[index]>1) density[index]=1.0f;
|
||||
}
|
||||
|
||||
smoke_turbulence_get_res(smd->domain->wt, bigres);
|
||||
|
||||
float fx,fy,fz, interpolated_value;
|
||||
int shift_x, shift_y, shift_z;
|
||||
|
||||
|
||||
/*
|
||||
loop through high res blocks if high res enabled
|
||||
* Do volume interpolation if emitter smoothing
|
||||
* is enabled
|
||||
*/
|
||||
if (bigdensity)
|
||||
for (ii = 0; ii < block_size; ii++)
|
||||
for (jj = 0; jj < block_size; jj++)
|
||||
for (kk = 0; kk < block_size; kk++)
|
||||
{
|
||||
if (high_emission_smoothing)
|
||||
{
|
||||
// convert block position to relative
|
||||
// for interpolation smoothing
|
||||
fx = (float)ii/block_size + 0.5f/block_size;
|
||||
fy = (float)jj/block_size + 0.5f/block_size;
|
||||
fz = (float)kk/block_size + 0.5f/block_size;
|
||||
|
||||
float fx,fy,fz, interpolated_value;
|
||||
int shift_x, shift_y, shift_z;
|
||||
// calculate trilinear interpolation
|
||||
interpolated_value = c000 * (1-fx) * (1-fy) * (1-fz) +
|
||||
c100 * fx * (1-fy) * (1-fz) +
|
||||
c010 * (1-fx) * fy * (1-fz) +
|
||||
c001 * (1-fx) * (1-fy) * fz +
|
||||
c101 * fx * (1-fy) * fz +
|
||||
c011 * (1-fx) * fy * fz +
|
||||
c110 * fx * fy * (1-fz) +
|
||||
c111 * fx * fy * fz;
|
||||
|
||||
|
||||
/*
|
||||
* Do volume interpolation if emitter smoothing
|
||||
* is enabled
|
||||
*/
|
||||
if (high_emission_smoothing) {
|
||||
// convert block position to relative
|
||||
// for interpolation smoothing
|
||||
fx = (float)ii/block_size + 0.5f/block_size;
|
||||
fy = (float)jj/block_size + 0.5f/block_size;
|
||||
fz = (float)kk/block_size + 0.5f/block_size;
|
||||
// add some contrast / sharpness
|
||||
// depending on hi-res block size
|
||||
|
||||
// calculate trilinear interpolation
|
||||
interpolated_value = c000 * (1-fx) * (1-fy) * (1-fz) +
|
||||
c100 * fx * (1-fy) * (1-fz) +
|
||||
c010 * (1-fx) * fy * (1-fz) +
|
||||
c001 * (1-fx) * (1-fy) * fz +
|
||||
c101 * fx * (1-fy) * fz +
|
||||
c011 * (1-fx) * fy * fz +
|
||||
c110 * fx * fy * (1-fz) +
|
||||
c111 * fx * fy * fz;
|
||||
interpolated_value = (interpolated_value-0.4f*sfs->density)*(block_size/2) + 0.4f*sfs->density;
|
||||
if (interpolated_value<0.0f) interpolated_value = 0.0f;
|
||||
if (interpolated_value>1.0f) interpolated_value = 1.0f;
|
||||
|
||||
// shift smoke block index
|
||||
// (because pixel center is actually
|
||||
// in halfway of the low res block)
|
||||
shift_x = (x < 1) ? 0 : block_size/2;
|
||||
shift_y = (y < 1) ? 0 : block_size/2;
|
||||
shift_z = (z < 1) ? 0 : block_size/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// without interpolation use same low resolution
|
||||
// block value for all hi-res blocks
|
||||
interpolated_value = c111;
|
||||
shift_x = 0;
|
||||
shift_y = 0;
|
||||
shift_z = 0;
|
||||
}
|
||||
|
||||
// add some contrast / sharpness
|
||||
// depending on hi-res block size
|
||||
// get shifted index for current high resolution block
|
||||
index_big = smoke_get_index(block_size * x + ii - shift_x, bigres[0], block_size * y + jj - shift_y, bigres[1], block_size * z + kk - shift_z);
|
||||
|
||||
interpolated_value = (interpolated_value-0.4f*sfs->density)*(block_size/2) + 0.4f*sfs->density;
|
||||
if (interpolated_value<0.0f) interpolated_value = 0.0f;
|
||||
if (interpolated_value>1.0f) interpolated_value = 1.0f;
|
||||
// add emission data to high resolution density
|
||||
if (absolute_flow)
|
||||
{
|
||||
if (interpolated_value > 0)
|
||||
bigdensity[index_big] = interpolated_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
bigdensity[index_big] += interpolated_value;
|
||||
|
||||
// shift smoke block index
|
||||
// (because pixel center is actually
|
||||
// in halfway of the low res block)
|
||||
shift_x = (x < 1) ? 0 : block_size/2;
|
||||
shift_y = (y < 1) ? 0 : block_size/2;
|
||||
shift_z = (z < 1) ? 0 : block_size/2;
|
||||
}
|
||||
else {
|
||||
// without interpolation use same low resolution
|
||||
// block value for all hi-res blocks
|
||||
interpolated_value = c111;
|
||||
shift_x = 0;
|
||||
shift_y = 0;
|
||||
shift_z = 0;
|
||||
}
|
||||
if (bigdensity[index_big]>1)
|
||||
bigdensity[index_big]=1.0f;
|
||||
}
|
||||
} // end of hires loop
|
||||
|
||||
// get shifted index for current high resolution block
|
||||
index_big = smoke_get_index(block_size * x + ii - shift_x, bigres[0], block_size * y + jj - shift_y, bigres[1], block_size * z + kk - shift_z);
|
||||
|
||||
// add emission data to high resolution density
|
||||
if (absolute_flow) {if (interpolated_value > 0) bigdensity[index_big] = interpolated_value;}
|
||||
else {
|
||||
bigdensity[index_big] += interpolated_value;
|
||||
if (bigdensity[index_big]>1) bigdensity[index_big]=1.0f;
|
||||
}
|
||||
} // end of low res loop
|
||||
|
||||
} // end of hires loop
|
||||
// free temporary emission map
|
||||
if (temp_emission_map)
|
||||
MEM_freeN(temp_emission_map);
|
||||
|
||||
} // end of low res loop
|
||||
|
||||
// free temporary emission map
|
||||
if (temp_emission_map) MEM_freeN(temp_emission_map);
|
||||
|
||||
} // end emission
|
||||
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
/*
|
||||
for ()
|
||||
{
|
||||
// no psys
|
||||
BVHTreeNearest nearest;
|
||||
nearest.index = -1;
|
||||
nearest.dist = FLT_MAX;
|
||||
|
||||
BLI_bvhtree_find_nearest(sfs->bvh->tree, pco, &nearest, sfs->bvh->nearest_callback, sfs->bvh);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sds->fluid_group)
|
||||
go = go->next;
|
||||
else
|
||||
base= base->next;
|
||||
}
|
||||
}
|
||||
|
||||
// do effectors
|
||||
{
|
||||
ListBase *effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights);
|
||||
|
||||
if (effectors)
|
||||
{
|
||||
float *density = smoke_get_density(sds->fluid);
|
||||
float *force_x = smoke_get_force_x(sds->fluid);
|
||||
float *force_y = smoke_get_force_y(sds->fluid);
|
||||
float *force_z = smoke_get_force_z(sds->fluid);
|
||||
float *velocity_x = smoke_get_velocity_x(sds->fluid);
|
||||
float *velocity_y = smoke_get_velocity_y(sds->fluid);
|
||||
float *velocity_z = smoke_get_velocity_z(sds->fluid);
|
||||
int x, y, z;
|
||||
|
||||
// precalculate wind forces
|
||||
for (x = 0; x < sds->res[0]; x++)
|
||||
for (y = 0; y < sds->res[1]; y++)
|
||||
for (z = 0; z < sds->res[2]; z++)
|
||||
{
|
||||
EffectedPoint epoint;
|
||||
float voxelCenter[3] = {0,0,0} , vel[3] = {0,0,0} , retvel[3] = {0,0,0};
|
||||
unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
|
||||
|
||||
if (density[index] < FLT_EPSILON)
|
||||
continue;
|
||||
|
||||
vel[0] = velocity_x[index];
|
||||
vel[1] = velocity_y[index];
|
||||
vel[2] = velocity_z[index];
|
||||
|
||||
voxelCenter[0] = sds->p0[0] + sds->dx * x + sds->dx * 0.5;
|
||||
voxelCenter[1] = sds->p0[1] + sds->dx * y + sds->dx * 0.5;
|
||||
voxelCenter[2] = sds->p0[2] + sds->dx * z + sds->dx * 0.5;
|
||||
|
||||
pd_point_from_loc(scene, voxelCenter, vel, index, &epoint);
|
||||
pdDoEffectors(effectors, NULL, sds->effector_weights, &epoint, retvel, NULL);
|
||||
|
||||
// TODO dg - do in force!
|
||||
force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0);
|
||||
force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0);
|
||||
force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0);
|
||||
} // end emission
|
||||
}
|
||||
}
|
||||
|
||||
pdEndEffectors(&effectors);
|
||||
}
|
||||
|
||||
if(flowobjs)
|
||||
MEM_freeN(flowobjs);
|
||||
}
|
||||
|
||||
static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt))
|
||||
{
|
||||
ListBase *effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights);
|
||||
|
||||
if(effectors)
|
||||
{
|
||||
float *density = smoke_get_density(sds->fluid);
|
||||
float *force_x = smoke_get_force_x(sds->fluid);
|
||||
float *force_y = smoke_get_force_y(sds->fluid);
|
||||
float *force_z = smoke_get_force_z(sds->fluid);
|
||||
float *velocity_x = smoke_get_velocity_x(sds->fluid);
|
||||
float *velocity_y = smoke_get_velocity_y(sds->fluid);
|
||||
float *velocity_z = smoke_get_velocity_z(sds->fluid);
|
||||
unsigned char *obstacle = smoke_get_obstacle(sds->fluid);
|
||||
int x, y, z;
|
||||
|
||||
// precalculate wind forces
|
||||
for(x = 0; x < sds->res[0]; x++)
|
||||
for(y = 0; y < sds->res[1]; y++)
|
||||
for(z = 0; z < sds->res[2]; z++)
|
||||
{
|
||||
EffectedPoint epoint;
|
||||
float voxelCenter[3] = {0,0,0} , vel[3] = {0,0,0} , retvel[3] = {0,0,0};
|
||||
unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
|
||||
|
||||
if((density[index] < FLT_EPSILON) || obstacle[index])
|
||||
continue;
|
||||
|
||||
vel[0] = velocity_x[index];
|
||||
vel[1] = velocity_y[index];
|
||||
vel[2] = velocity_z[index];
|
||||
|
||||
voxelCenter[0] = sds->p0[0] + sds->dx * x + sds->dx * 0.5;
|
||||
voxelCenter[1] = sds->p0[1] + sds->dx * y + sds->dx * 0.5;
|
||||
voxelCenter[2] = sds->p0[2] + sds->dx * z + sds->dx * 0.5;
|
||||
|
||||
pd_point_from_loc(scene, voxelCenter, vel, index, &epoint);
|
||||
pdDoEffectors(effectors, NULL, sds->effector_weights, &epoint, retvel, NULL);
|
||||
|
||||
// TODO dg - do in force!
|
||||
force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0);
|
||||
force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0);
|
||||
force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
pdEndEffectors(&effectors);
|
||||
}
|
||||
|
||||
static void step(Scene *scene, Object *ob, SmokeModifierData *smd, float fps)
|
||||
{
|
||||
/* stability values copied from wturbulence.cpp */
|
||||
const int maxSubSteps = 25;
|
||||
float maxVel;
|
||||
// maxVel should be 1.5 (1.5 cell max movement) * dx (cell size)
|
||||
|
||||
float dt = DT_DEFAULT;
|
||||
float maxVelMag = 0.0f;
|
||||
int totalSubsteps;
|
||||
int substep = 0;
|
||||
float dtSubdiv;
|
||||
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
|
||||
/* get max velocity and lower the dt value if it is too high */
|
||||
size_t size= sds->res[0] * sds->res[1] * sds->res[2];
|
||||
|
||||
float *velX = smoke_get_velocity_x(sds->fluid);
|
||||
float *velY = smoke_get_velocity_y(sds->fluid);
|
||||
float *velZ = smoke_get_velocity_z(sds->fluid);
|
||||
size_t i;
|
||||
|
||||
/* adapt timestep for different framerates, dt = 0.1 is at 25fps */
|
||||
dt *= (25.0f / fps);
|
||||
|
||||
// printf("test maxVel: %f\n", (sds->dx * 1.5) / dt); // gives 0.9
|
||||
maxVel = (sds->dx * 1.5);
|
||||
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
float vtemp = (velX[i]*velX[i]+velY[i]*velY[i]+velZ[i]*velZ[i]);
|
||||
if(vtemp > maxVelMag)
|
||||
maxVelMag = vtemp;
|
||||
}
|
||||
|
||||
maxVelMag = sqrt(maxVelMag) * dt * sds->time_scale;
|
||||
totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */
|
||||
totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
|
||||
totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
|
||||
|
||||
// totalSubsteps = 2.0f; // DEBUG
|
||||
|
||||
dtSubdiv = (float)dt / (float)totalSubsteps;
|
||||
|
||||
// printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
|
||||
|
||||
for(substep = 0; substep < totalSubsteps; substep++)
|
||||
{
|
||||
// calc animated obstacle velocities
|
||||
update_obstacles(scene, ob, sds, dtSubdiv, substep, totalSubsteps);
|
||||
update_flowsfluids(scene, ob, sds, smd->time);
|
||||
update_effectors(scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt
|
||||
|
||||
smoke_step(sds->fluid, dtSubdiv);
|
||||
|
||||
// move animated obstacle: Done in update_obstacles() */
|
||||
|
||||
// where to delete old obstacles from array? Done in update_obstacles() */
|
||||
}
|
||||
}
|
||||
|
||||
void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
|
||||
{
|
||||
if ((smd->type & MOD_SMOKE_TYPE_FLOW))
|
||||
if((smd->type & MOD_SMOKE_TYPE_FLOW))
|
||||
{
|
||||
if (scene->r.cfra >= smd->time)
|
||||
if(scene->r.cfra >= smd->time)
|
||||
smokeModifier_init(smd, ob, scene, dm);
|
||||
|
||||
if (scene->r.cfra > smd->time)
|
||||
if(scene->r.cfra > smd->time)
|
||||
{
|
||||
// XXX TODO
|
||||
smd->time = scene->r.cfra;
|
||||
@@ -1366,40 +1675,102 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
|
||||
copy_m4_m4(smd->flow->mat, ob->obmat);
|
||||
*/
|
||||
}
|
||||
else if (scene->r.cfra < smd->time)
|
||||
else if(scene->r.cfra < smd->time)
|
||||
{
|
||||
smd->time = scene->r.cfra;
|
||||
smokeModifier_reset(smd);
|
||||
}
|
||||
}
|
||||
else if (smd->type & MOD_SMOKE_TYPE_COLL)
|
||||
else if(smd->type & MOD_SMOKE_TYPE_COLL)
|
||||
{
|
||||
if (scene->r.cfra >= smd->time)
|
||||
/* Check if domain resolution changed */
|
||||
/* DG TODO: can this be solved more elegant using dependancy graph? */
|
||||
{
|
||||
SmokeCollSettings *scs = smd->coll;
|
||||
Base *base = scene->base.first;
|
||||
int changed = 0;
|
||||
float dx = FLT_MAX;
|
||||
int haveDomain = 0;
|
||||
|
||||
for ( ; base; base = base->next)
|
||||
{
|
||||
SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(base->object, eModifierType_Smoke);
|
||||
|
||||
if (smd2 && (smd2->type & MOD_SMOKE_TYPE_DOMAIN) && smd2->domain)
|
||||
{
|
||||
SmokeDomainSettings *sds = smd2->domain;
|
||||
|
||||
if(sds->dx < dx)
|
||||
{
|
||||
dx = sds->dx;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
haveDomain = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!haveDomain)
|
||||
return;
|
||||
|
||||
if(changed)
|
||||
{
|
||||
if(dx != scs->dx)
|
||||
{
|
||||
scs->dx = dx;
|
||||
smokeModifier_reset(smd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(scene->r.cfra >= smd->time)
|
||||
smokeModifier_init(smd, ob, scene, dm);
|
||||
|
||||
if (scene->r.cfra > smd->time)
|
||||
if(scene->r.cfra > smd->time)
|
||||
{
|
||||
// XXX TODO
|
||||
unsigned int i;
|
||||
SmokeCollSettings *scs = smd->coll;
|
||||
float *points_old = scs->points_old;
|
||||
float *points = scs->points;
|
||||
unsigned int numpoints = scs->numpoints;
|
||||
|
||||
// XXX TODO <-- DG: what is TODO here?
|
||||
smd->time = scene->r.cfra;
|
||||
|
||||
#ifdef USE_SMOKE_COLLISION_DM
|
||||
if (smd->coll->dm)
|
||||
smd->coll->dm->release(smd->coll->dm);
|
||||
|
||||
smd->coll->dm = CDDM_copy_from_tessface(dm);
|
||||
#endif
|
||||
|
||||
// rigid movement support
|
||||
copy_m4_m4(smd->coll->mat_old, smd->coll->mat);
|
||||
copy_m4_m4(smd->coll->mat, ob->obmat);
|
||||
copy_m4_m4(scs->mat_old, scs->mat);
|
||||
copy_m4_m4(scs->mat, ob->obmat);
|
||||
|
||||
if(scs->type != SM_COLL_ANIMATED) // if(not_animated)
|
||||
{
|
||||
// nothing to do, "mat" is already up to date
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX TODO: need to update positions + divs
|
||||
|
||||
if(scs->numverts != dm->getNumVerts(dm))
|
||||
{
|
||||
// DG TODO: reset modifier?
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < numpoints * 3; i++)
|
||||
{
|
||||
points_old[i] = points[i];
|
||||
}
|
||||
|
||||
DM_ensure_tessface(dm);
|
||||
fill_scs_points_anim(ob, dm, scs);
|
||||
}
|
||||
}
|
||||
else if (scene->r.cfra < smd->time)
|
||||
else if(scene->r.cfra < smd->time)
|
||||
{
|
||||
smd->time = scene->r.cfra;
|
||||
smokeModifier_reset(smd);
|
||||
}
|
||||
}
|
||||
else if (smd->type & MOD_SMOKE_TYPE_DOMAIN)
|
||||
else if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
|
||||
{
|
||||
SmokeDomainSettings *sds = smd->domain;
|
||||
float light[3];
|
||||
@@ -1416,14 +1787,14 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
|
||||
BKE_ptcache_id_from_smoke(&pid, ob, smd);
|
||||
BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale);
|
||||
|
||||
if (!smd->domain->fluid || framenr == startframe)
|
||||
if(!smd->domain->fluid || framenr == startframe)
|
||||
{
|
||||
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
|
||||
BKE_ptcache_validate(cache, framenr);
|
||||
cache->flag &= ~PTCACHE_REDO_NEEDED;
|
||||
}
|
||||
|
||||
if (!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0)
|
||||
if(!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0)
|
||||
return;
|
||||
|
||||
smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD;
|
||||
@@ -1436,21 +1807,21 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
|
||||
|
||||
// printf("startframe: %d, framenr: %d\n", startframe, framenr);
|
||||
|
||||
if (smokeModifier_init(smd, ob, scene, dm)==0)
|
||||
if(smokeModifier_init(smd, ob, scene, dm)==0)
|
||||
{
|
||||
printf("bad smokeModifier_init\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to read from cache */
|
||||
if (BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) {
|
||||
if(BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) {
|
||||
BKE_ptcache_validate(cache, framenr);
|
||||
smd->time = framenr;
|
||||
return;
|
||||
}
|
||||
|
||||
/* only calculate something when we advanced a single frame */
|
||||
if (framenr != (int)smd->time+1)
|
||||
if(framenr != (int)smd->time+1)
|
||||
return;
|
||||
|
||||
/* don't simulate if viewing start frame, but scene frame is not real start frame */
|
||||
@@ -1462,14 +1833,14 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
|
||||
smoke_calc_domain(scene, ob, smd);
|
||||
|
||||
/* if on second frame, write cache for first frame */
|
||||
if ((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) {
|
||||
if((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) {
|
||||
// create shadows straight after domain initialization so we get nice shadows for startframe, too
|
||||
if (get_lamp(scene, light))
|
||||
if(get_lamp(scene, light))
|
||||
smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx);
|
||||
|
||||
if (sds->wt)
|
||||
if(sds->wt)
|
||||
{
|
||||
if (sds->flags & MOD_SMOKE_DISSOLVE)
|
||||
if(sds->flags & MOD_SMOKE_DISSOLVE)
|
||||
smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
|
||||
smoke_turbulence_step(sds->wt, sds->fluid);
|
||||
}
|
||||
@@ -1486,30 +1857,31 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
|
||||
|
||||
// simulate the actual smoke (c++ code in intern/smoke)
|
||||
// DG: interesting commenting this line + deactivating loading of noise files
|
||||
if (framenr!=startframe)
|
||||
if(framenr!=startframe)
|
||||
{
|
||||
if (sds->flags & MOD_SMOKE_DISSOLVE)
|
||||
if(sds->flags & MOD_SMOKE_DISSOLVE)
|
||||
smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
|
||||
smoke_step(sds->fluid, smd->time, scene->r.frs_sec / scene->r.frs_sec_base);
|
||||
|
||||
step(scene, ob, smd, scene->r.frs_sec / scene->r.frs_sec_base);
|
||||
}
|
||||
|
||||
// create shadows before writing cache so they get stored
|
||||
if (get_lamp(scene, light))
|
||||
if(get_lamp(scene, light))
|
||||
smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx);
|
||||
|
||||
if (sds->wt)
|
||||
if(sds->wt)
|
||||
{
|
||||
if (sds->flags & MOD_SMOKE_DISSOLVE)
|
||||
if(sds->flags & MOD_SMOKE_DISSOLVE)
|
||||
smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
|
||||
smoke_turbulence_step(sds->wt, sds->fluid);
|
||||
}
|
||||
|
||||
BKE_ptcache_validate(cache, framenr);
|
||||
if (framenr != startframe)
|
||||
if(framenr != startframe)
|
||||
BKE_ptcache_write(&pid, framenr);
|
||||
|
||||
tend();
|
||||
//printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() );
|
||||
// printf ( "Frame: %d, Time: %f\n\n", (int)smd->time, ( float ) tval() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1520,7 +1892,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix
|
||||
// T_ray *= T_vox
|
||||
*tRay *= exp(input[index]*correct);
|
||||
|
||||
if (result[index] < 0.0f)
|
||||
if(result[index] < 0.0f)
|
||||
{
|
||||
#pragma omp critical
|
||||
result[index] = *tRay;
|
||||
@@ -1574,7 +1946,7 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
|
||||
err_1 = dy2 - l;
|
||||
err_2 = dz2 - l;
|
||||
for (i = 0; i < l; i++) {
|
||||
if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
|
||||
if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
|
||||
break;
|
||||
if (err_1 > 0) {
|
||||
pixel[1] += y_inc;
|
||||
@@ -1588,12 +1960,12 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
|
||||
err_2 += dz2;
|
||||
pixel[0] += x_inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((m >= l) && (m >= n)) {
|
||||
err_1 = dx2 - m;
|
||||
err_2 = dz2 - m;
|
||||
for (i = 0; i < m; i++) {
|
||||
if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
|
||||
if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
|
||||
break;
|
||||
if (err_1 > 0) {
|
||||
pixel[0] += x_inc;
|
||||
@@ -1607,12 +1979,12 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
|
||||
err_2 += dz2;
|
||||
pixel[1] += y_inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
err_1 = dy2 - n;
|
||||
err_2 = dx2 - n;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
|
||||
if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON)
|
||||
break;
|
||||
if (err_1 > 0) {
|
||||
pixel[1] += y_inc;
|
||||
@@ -1654,7 +2026,7 @@ static void smoke_calc_transparency(float *result, float *input, float *p0, floa
|
||||
float bv[6];
|
||||
int a, z, slabsize=res[0]*res[1], size= res[0]*res[1]*res[2];
|
||||
|
||||
for (a=0; a<size; a++)
|
||||
for(a=0; a<size; a++)
|
||||
result[a]= -1.0f;
|
||||
|
||||
bv[0] = p0[0];
|
||||
@@ -1667,27 +2039,27 @@ static void smoke_calc_transparency(float *result, float *input, float *p0, floa
|
||||
bv[5] = p1[2];
|
||||
|
||||
#pragma omp parallel for schedule(static,1)
|
||||
for (z = 0; z < res[2]; z++)
|
||||
for(z = 0; z < res[2]; z++)
|
||||
{
|
||||
size_t index = z*slabsize;
|
||||
int x,y;
|
||||
|
||||
for (y = 0; y < res[1]; y++)
|
||||
for (x = 0; x < res[0]; x++, index++)
|
||||
for(y = 0; y < res[1]; y++)
|
||||
for(x = 0; x < res[0]; x++, index++)
|
||||
{
|
||||
float voxelCenter[3];
|
||||
float pos[3];
|
||||
int cell[3];
|
||||
float tRay = 1.0;
|
||||
|
||||
if (result[index] >= 0.0f)
|
||||
if(result[index] >= 0.0f)
|
||||
continue;
|
||||
voxelCenter[0] = p0[0] + dx * x + dx * 0.5;
|
||||
voxelCenter[1] = p0[1] + dx * y + dx * 0.5;
|
||||
voxelCenter[2] = p0[2] + dx * z + dx * 0.5;
|
||||
|
||||
// get starting position (in voxel coords)
|
||||
if (BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON)
|
||||
if(BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON)
|
||||
{
|
||||
// we're ouside
|
||||
get_cell(p0, res, dx, pos, cell, 1);
|
||||
|
||||
@@ -104,6 +104,50 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Elem Iter Flag Count
|
||||
*
|
||||
* Counts how many flagged / unflagged items are found in this element.
|
||||
*/
|
||||
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value)
|
||||
{
|
||||
BMIter iter;
|
||||
BMElem *ele;
|
||||
int count = 0;
|
||||
|
||||
BLI_assert(ELEM(value, TRUE, FALSE));
|
||||
|
||||
for (ele = BM_iter_new(&iter, NULL, itype, data); ele; ele = BM_iter_step(&iter)) {
|
||||
if (BM_elem_flag_test_bool(ele, hflag) == value) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mesh Iter Flag Count
|
||||
*
|
||||
* Counts how many flagged / unflagged items are found in this mesh.
|
||||
*/
|
||||
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value)
|
||||
{
|
||||
BMIter iter;
|
||||
BMElem *ele;
|
||||
int count = 0;
|
||||
|
||||
BLI_assert(ELEM(value, TRUE, FALSE));
|
||||
|
||||
for (ele = BM_iter_new(&iter, bm, itype, NULL); ele; ele = BM_iter_step(&iter)) {
|
||||
if (BM_elem_flag_test_bool(ele, hflag) == value) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Init Iterator
|
||||
|
||||
@@ -117,6 +117,8 @@ typedef struct BMIter {
|
||||
|
||||
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index);
|
||||
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
|
||||
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value);
|
||||
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value);
|
||||
|
||||
/* private for bmesh_iterators_inline.c */
|
||||
void bmiter__vert_of_mesh_begin(struct BMIter *iter);
|
||||
|
||||
@@ -56,6 +56,11 @@
|
||||
#define SM_BORDER_VERTICAL 1
|
||||
#define SM_BORDER_CLOSED 2
|
||||
|
||||
/* collision types */
|
||||
#define SM_COLL_STATIC 0
|
||||
#define SM_COLL_RIGID 1
|
||||
#define SM_COLL_ANIMATED 2
|
||||
|
||||
typedef struct SmokeDomainSettings {
|
||||
struct SmokeModifierData *smd; /* for fast RNA access */
|
||||
struct FLUID_3D *fluid;
|
||||
@@ -137,15 +142,16 @@ typedef struct SmokeFlowSettings {
|
||||
typedef struct SmokeCollSettings {
|
||||
struct SmokeModifierData *smd; /* for fast RNA access */
|
||||
struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
|
||||
|
||||
// struct DerivedMesh *dm; // UNUSED, ifdef'd in code for now.
|
||||
float *points;
|
||||
float *points_old;
|
||||
float *vel;
|
||||
float *vel; // UNUSED
|
||||
int *tridivs;
|
||||
float mat[4][4];
|
||||
float mat_old[4][4];
|
||||
int numpoints;
|
||||
int numverts; // check if mesh changed
|
||||
int numtris;
|
||||
float dx; /* global domain cell length taken from (scale / resolution) */
|
||||
short type; // static = 0, rigid = 1, dynamic = 2
|
||||
short pad;
|
||||
int pad2;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): Daniel Genrich
|
||||
* Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
@@ -336,12 +337,25 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
|
||||
static void rna_def_smoke_coll_settings(BlenderRNA *brna)
|
||||
{
|
||||
static EnumPropertyItem smoke_coll_type_items[] = {
|
||||
{SM_COLL_STATIC, "COLLSTATIC", 0, "Static", "Non moving obstacle"},
|
||||
{SM_COLL_RIGID, "COLLRIGID", 0, "Rigid", "Rigid obstacle"},
|
||||
{SM_COLL_ANIMATED, "COLLANIMATED", 0, "Animated", "Animated obstacle"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "SmokeCollSettings", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Collision Settings", "Smoke collision settings");
|
||||
RNA_def_struct_sdna(srna, "SmokeCollSettings");
|
||||
RNA_def_struct_path_func(srna, "rna_SmokeCollSettings_path");
|
||||
|
||||
prop = RNA_def_property(srna, "collision_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "type");
|
||||
RNA_def_property_enum_items(prop, smoke_coll_type_items);
|
||||
RNA_def_property_ui_text(prop, "Collision type", "Collision type");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
|
||||
}
|
||||
|
||||
void RNA_def_smoke(BlenderRNA *brna)
|
||||
|
||||
@@ -32,7 +32,7 @@ set(INC
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
||||
${PTHREADS_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(SRC
|
||||
|
||||
@@ -35,4 +35,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']:
|
||||
incs += ' ' + env['BF_BULLET_INC']
|
||||
incs += ' ' + env['BF_OPENGL_INC']
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
|
||||
incs += ' ' + env['BF_PTHREADS_INC']
|
||||
|
||||
env.BlenderLib ( 'ge_blen_routines', sources, Split(incs), defs, libtype=['core','player'], priority=[300,35] , cxx_compileflags=env['BGE_CXXFLAGS'])
|
||||
|
||||
@@ -59,6 +59,7 @@ set(INC
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
${PTHREADS_INCLUDE_DIRS}
|
||||
|
||||
)
|
||||
|
||||
|
||||
@@ -39,4 +39,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']:
|
||||
if env['WITH_BF_BULLET']:
|
||||
defs.append('USE_BULLET')
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
|
||||
incs += ' ' + env['BF_PTHREADS_INC']
|
||||
|
||||
env.BlenderLib ( 'ge_converter', sources, Split(incs), defs, libtype=['core','player'], priority=[305,40], cxx_compileflags=env['BGE_CXXFLAGS'])
|
||||
|
||||
@@ -55,6 +55,7 @@ set(INC
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
${PTHREADS_INCLUDE_DIRS}
|
||||
${GLEW_INCLUDE_PATH}
|
||||
../../../extern/recastnavigation/Recast/Include
|
||||
../../../extern/recastnavigation/Detour/Include
|
||||
|
||||
@@ -52,12 +52,9 @@
|
||||
#include "RAS_IRasterizer.h"
|
||||
#include "RAS_IRenderTools.h"
|
||||
#include "RAS_ICanvas.h"
|
||||
#include "STR_String.h"
|
||||
#include "MT_Vector3.h"
|
||||
#include "MT_Transform.h"
|
||||
#include "SCA_IInputDevice.h"
|
||||
#include "KX_Scene.h"
|
||||
#include "MT_CmMatrix4x4.h"
|
||||
#include "KX_Camera.h"
|
||||
#include "KX_FontObject.h"
|
||||
#include "KX_Dome.h"
|
||||
@@ -90,6 +87,12 @@
|
||||
#define DEFAULT_LOGIC_TIC_RATE 60.0
|
||||
#define DEFAULT_PHYSICS_TIC_RATE 60.0
|
||||
|
||||
#ifdef FREE_WINDOWS /* XXX mingw64 (gcc 4.7.0) defines a macro for DrawText that translates to DrawTextA. Not good */
|
||||
#ifdef DrawText
|
||||
#undef DrawText
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
|
||||
"Physics:", // tc_physics
|
||||
"Logic:", // tc_logic
|
||||
@@ -1063,37 +1066,30 @@ void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
|
||||
m_overrideSceneName = forscene;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_KetsjiEngine::SetCameraZoom(float camzoom)
|
||||
{
|
||||
m_cameraZoom = camzoom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_KetsjiEngine::SetCameraOverrideUseOrtho(bool useOrtho)
|
||||
{
|
||||
m_overrideCamUseOrtho = useOrtho;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_KetsjiEngine::SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat)
|
||||
{
|
||||
m_overrideCamProjMat = mat;
|
||||
}
|
||||
|
||||
|
||||
void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
|
||||
{
|
||||
m_overrideCamViewMat = mat;
|
||||
}
|
||||
|
||||
void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far)
|
||||
void KX_KetsjiEngine::SetCameraOverrideClipping(float nearfrust, float farfrust)
|
||||
{
|
||||
m_overrideCamNear = near;
|
||||
m_overrideCamFar = far;
|
||||
m_overrideCamNear = nearfrust;
|
||||
m_overrideCamFar = farfrust;
|
||||
}
|
||||
|
||||
void KX_KetsjiEngine::SetCameraOverrideLens(float lens)
|
||||
|
||||
@@ -47,4 +47,7 @@ if env['WITH_BF_BULLET']:
|
||||
defs.append('USE_BULLET')
|
||||
incs += ' #source/gameengine/Physics/Bullet'
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
|
||||
incs += ' ' + env['BF_PTHREADS_INC']
|
||||
|
||||
env.BlenderLib ( 'ge_logic_ketsji', sources, Split(incs), defs, libtype=['core','player'], priority=[320,45], cxx_compileflags=env['BGE_CXXFLAGS'])
|
||||
|
||||
Reference in New Issue
Block a user