130
150
_domainBcRight = _domainBcLeft;
132
152
_colloPrev = 1; // default value
155
void FLUID_3D::initHeat()
158
_heat = new float[_totalCells];
159
_heatOld = new float[_totalCells];
160
_heatTemp = new float[_totalCells];
162
for (int x = 0; x < _totalCells; x++)
170
void FLUID_3D::initFire()
173
_flame = new float[_totalCells];
174
_fuel = new float[_totalCells];
175
_fuelTemp = new float[_totalCells];
176
_fuelOld = new float[_totalCells];
177
_react = new float[_totalCells];
178
_reactTemp = new float[_totalCells];
179
_reactOld = new float[_totalCells];
181
for (int x = 0; x < _totalCells; x++)
188
_reactTemp[x] = 0.0f;
194
void FLUID_3D::initColors(float init_r, float init_g, float init_b)
197
_color_r = new float[_totalCells];
198
_color_rOld = new float[_totalCells];
199
_color_rTemp = new float[_totalCells];
200
_color_g = new float[_totalCells];
201
_color_gOld = new float[_totalCells];
202
_color_gTemp = new float[_totalCells];
203
_color_b = new float[_totalCells];
204
_color_bOld = new float[_totalCells];
205
_color_bTemp = new float[_totalCells];
207
for (int x = 0; x < _totalCells; x++)
209
_color_r[x] = _density[x] * init_r;
210
_color_rOld[x] = 0.0f;
211
_color_g[x] = _density[x] * init_g;
212
_color_gOld[x] = 0.0f;
213
_color_b[x] = _density[x] * init_b;
214
_color_bOld[x] = 0.0f;
219
void FLUID_3D::setBorderObstacles()
135
222
// set side obstacles
137
224
for (int y = 0; y < _yRes; y++)
138
225
for (int x = 0; x < _xRes; x++)
141
228
index = x + y * _xRes;
142
if(_domainBcBottom==1) _obstacles[index] = 1;
229
if(_domainBcBottom) _obstacles[index] = 1;
145
232
index += _totalCells - _slabSize;
146
if(_domainBcTop==1) _obstacles[index] = 1;
233
if(_domainBcTop) _obstacles[index] = 1;
149
236
for (int z = 0; z < _zRes; z++)
196
284
if (_densityTemp) delete[] _densityTemp;
197
285
if (_heatTemp) delete[] _heatTemp;
287
if (_flame) delete[] _flame;
288
if (_fuel) delete[] _fuel;
289
if (_fuelTemp) delete[] _fuelTemp;
290
if (_fuelOld) delete[] _fuelOld;
291
if (_react) delete[] _react;
292
if (_reactTemp) delete[] _reactTemp;
293
if (_reactOld) delete[] _reactOld;
295
if (_color_r) delete[] _color_r;
296
if (_color_rOld) delete[] _color_rOld;
297
if (_color_rTemp) delete[] _color_rTemp;
298
if (_color_g) delete[] _color_g;
299
if (_color_gOld) delete[] _color_gOld;
300
if (_color_gTemp) delete[] _color_gTemp;
301
if (_color_b) delete[] _color_b;
302
if (_color_bOld) delete[] _color_bOld;
303
if (_color_bTemp) delete[] _color_bTemp;
199
305
// printf("deleted fluid\n");
202
308
// init direct access functions from blender
203
void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision)
309
void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision, float *burning_rate,
310
float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp)
207
314
_dtFactor = dt_factor;
208
315
_vorticityRNA = vorticity;
209
316
_borderColli = borderCollision;
317
_burning_rate = burning_rate;
318
_flame_smoke = flame_smoke;
319
_flame_smoke_color = flame_smoke_color;
320
_flame_vorticity = flame_vorticity;
321
_ignition_temp = flame_ignition_temp;
322
_max_temp = flame_max_temp;
212
325
//////////////////////////////////////////////////////////////////////
213
326
// step simulation once
214
327
//////////////////////////////////////////////////////////////////////
215
void FLUID_3D::step(float dt)
328
void FLUID_3D::step(float dt, float gravity[3])
217
331
// If border rules have been changed
218
332
if (_colloPrev != *_borderColli) {
333
printf("Border collisions changed\n");
335
// DG TODO: Need to check that no animated obstacle flags are overwritten
219
336
setBorderCollisions();
340
// DG: TODO for the moment redo border for every timestep since it's been deleted every time by moving obstacles
341
setBorderCollisions();
223
344
// set delta time by dt_factor
786
934
memset(_pressure, 0, sizeof(float)*_totalCells);
787
935
memset(_divergence, 0, sizeof(float)*_totalCells);
937
// set velocity and pressure inside of obstacles to zero
789
938
setObstacleBoundaries(_pressure, 0, _zRes);
791
940
// copy out the boundaries
792
if(_domainBcLeft == 0) setNeumannX(_xVelocity, _res, 0, _zRes);
941
if(!_domainBcLeft) setNeumannX(_xVelocity, _res, 0, _zRes);
793
942
else setZeroX(_xVelocity, _res, 0, _zRes);
795
if(_domainBcFront == 0) setNeumannY(_yVelocity, _res, 0, _zRes);
944
if(!_domainBcFront) setNeumannY(_yVelocity, _res, 0, _zRes);
796
945
else setZeroY(_yVelocity, _res, 0, _zRes);
798
if(_domainBcTop == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
947
if(!_domainBcTop) setNeumannZ(_zVelocity, _res, 0, _zRes);
799
948
else setZeroZ(_zVelocity, _res, 0, _zRes);
801
950
// calculate divergence
811
968
float ztop = _zVelocity[index + _slabSize];
812
969
float zbottom = _zVelocity[index - _slabSize];
814
if(_obstacles[index+1]) xright = - _xVelocity[index];
971
if(_obstacles[index+1]) xright = - _xVelocity[index]; // DG: +=
815
972
if(_obstacles[index-1]) xleft = - _xVelocity[index];
816
973
if(_obstacles[index+_xRes]) yup = - _yVelocity[index];
817
974
if(_obstacles[index-_xRes]) ydown = - _yVelocity[index];
818
975
if(_obstacles[index+_slabSize]) ztop = - _zVelocity[index];
819
976
if(_obstacles[index-_slabSize]) zbottom = - _zVelocity[index];
978
if(_obstacles[index+1] & 8) xright += _xVelocityOb[index + 1];
979
if(_obstacles[index-1] & 8) xleft += _xVelocityOb[index - 1];
980
if(_obstacles[index+_xRes] & 8) yup += _yVelocityOb[index + _xRes];
981
if(_obstacles[index-_xRes] & 8) ydown += _yVelocityOb[index - _xRes];
982
if(_obstacles[index+_slabSize] & 8) ztop += _zVelocityOb[index + _slabSize];
983
if(_obstacles[index-_slabSize] & 8) zbottom += _zVelocityOb[index - _slabSize];
821
985
_divergence[index] = -_dx * 0.5f * (
824
988
ztop - zbottom );
826
// DG: commenting this helps CG to get a better start, 10-20% speed improvement
827
// _pressure[index] = 0.0f;
990
// Pressure is zero anyway since now a local array is used
991
_pressure[index] = 0.0f;
998
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
1000
if(_divergence[i] > maxvalue)
1001
maxvalue = _divergence[i];
1004
printf("Max divergence: %f\n", maxvalue);
829
1008
copyBorderAll(_pressure, 0, _zRes);
1013
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
1015
if(_pressure[i] > maxvalue)
1016
maxvalue = _pressure[i];
1018
printf("Max pressure BEFORE: %f\n", maxvalue);
831
1022
// solve Poisson equation
832
1023
solvePressurePre(_pressure, _divergence, _obstacles);
1027
for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
1029
if(_pressure[i] > maxvalue)
1030
maxvalue = _pressure[i];
1032
/* HACK: Animated collision object sometimes result in a non converging solvePressurePre() */
1033
if(_pressure[i] > _dx * _dt)
1034
_pressure[i] = _dx * _dt;
1035
else if(_pressure[i] < -_dx * _dt)
1036
_pressure[i] = -_dx * _dt;
1038
// if(_obstacle[i] && _pressure[i] != 0.0)
1039
// printf("BAD PRESSURE i\n");
1041
// if(_pressure[i]>1)
1042
// printf("index: %d\n", i);
1044
// printf("Max pressure: %f, dx: %f\n", maxvalue, _dx);
834
1047
setObstaclePressure(_pressure, 0, _zRes);
836
1049
// project out solution
1050
// New idea for code from NVIDIA graphic gems 3 - DG
837
1051
float invDx = 1.0f / _dx;
838
1052
index = _slabSize + _xRes + 1;
839
1053
for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
840
1054
for (y = 1; y < _yRes - 1; y++, index += 2)
841
1055
for (x = 1; x < _xRes - 1; x++, index++)
1057
float vMask[3] = {1.0f, 1.0f, 1.0f}, vObst[3] = {0, 0, 0};
1058
// float vR = 0.0f, vL = 0.0f, vT = 0.0f, vB = 0.0f, vD = 0.0f, vU = 0.0f; // UNUSED
1060
float pC = _pressure[index]; // center
1061
float pR = _pressure[index + 1]; // right
1062
float pL = _pressure[index - 1]; // left
1063
float pU = _pressure[index + _xRes]; // Up
1064
float pD = _pressure[index - _xRes]; // Down
1065
float pT = _pressure[index + _slabSize]; // top
1066
float pB = _pressure[index - _slabSize]; // bottom
843
1068
if(!_obstacles[index])
845
_xVelocity[index] -= 0.5f * (_pressure[index + 1] - _pressure[index - 1]) * invDx;
846
_yVelocity[index] -= 0.5f * (_pressure[index + _xRes] - _pressure[index - _xRes]) * invDx;
847
_zVelocity[index] -= 0.5f * (_pressure[index + _slabSize] - _pressure[index - _slabSize]) * invDx;
1070
// DG TODO: What if obstacle is left + right and one of them is moving?
1071
if(_obstacles[index+1]) { pR = pC; vObst[0] = _xVelocityOb[index + 1]; vMask[0] = 0; }
1072
if(_obstacles[index-1]) { pL = pC; vObst[0] = _xVelocityOb[index - 1]; vMask[0] = 0; }
1073
if(_obstacles[index+_xRes]) { pU = pC; vObst[1] = _yVelocityOb[index + _xRes]; vMask[1] = 0; }
1074
if(_obstacles[index-_xRes]) { pD = pC; vObst[1] = _yVelocityOb[index - _xRes]; vMask[1] = 0; }
1075
if(_obstacles[index+_slabSize]) { pT = pC; vObst[2] = _zVelocityOb[index + _slabSize]; vMask[2] = 0; }
1076
if(_obstacles[index-_slabSize]) { pB = pC; vObst[2] = _zVelocityOb[index - _slabSize]; vMask[2] = 0; }
1078
_xVelocity[index] -= 0.5f * (pR - pL) * invDx;
1079
_yVelocity[index] -= 0.5f * (pU - pD) * invDx;
1080
_zVelocity[index] -= 0.5f * (pT - pB) * invDx;
1082
_xVelocity[index] = (vMask[0] * _xVelocity[index]) + vObst[0];
1083
_yVelocity[index] = (vMask[1] * _yVelocity[index]) + vObst[1];
1084
_zVelocity[index] = (vMask[2] * _zVelocity[index]) + vObst[2];
1088
_xVelocity[index] = _xVelocityOb[index];
1089
_yVelocity[index] = _yVelocityOb[index];
1090
_zVelocity[index] = _zVelocityOb[index];
1094
// DG: was enabled in original code but now we do this later
1095
// setObstacleVelocity(0, _zRes);
851
1097
if (_pressure) delete[] _pressure;
852
1098
if (_divergence) delete[] _divergence;
1101
//////////////////////////////////////////////////////////////////////
1102
// calculate the obstacle velocity at boundary
1103
//////////////////////////////////////////////////////////////////////
1104
void FLUID_3D::setObstacleVelocity(int zBegin, int zEnd)
1107
// completely TODO <-- who wrote this and what is here TODO? DG
1109
const size_t index_ = _slabSize + _xRes + 1;
1111
//int vIndex=_slabSize + _xRes + 1;
1116
if (zBegin == 0) {bb = 1;}
1117
if (zEnd == _zRes) {bt = 1;}
1119
// tag remaining obstacle blocks
1120
for (int z = zBegin + bb; z < zEnd - bt; z++)
1122
size_t index = index_ +(z-1)*_slabSize;
1124
for (int y = 1; y < _yRes - 1; y++, index += 2)
1126
for (int x = 1; x < _xRes - 1; x++, index++)
1128
if (!_obstacles[index])
1130
// if(_obstacles[index+1]) xright = - _xVelocityOb[index];
1131
if((_obstacles[index - 1] & 8) && abs(_xVelocityOb[index - 1]) > FLT_EPSILON )
1133
// printf("velocity x!\n");
1134
_xVelocity[index] = _xVelocityOb[index - 1];
1135
_xVelocity[index - 1] = _xVelocityOb[index - 1];
1137
// if(_obstacles[index+_xRes]) yup = - _yVelocityOb[index];
1138
if((_obstacles[index - _xRes] & 8) && abs(_yVelocityOb[index - _xRes]) > FLT_EPSILON)
1140
// printf("velocity y!\n");
1141
_yVelocity[index] = _yVelocityOb[index - _xRes];
1142
_yVelocity[index - _xRes] = _yVelocityOb[index - _xRes];
1144
// if(_obstacles[index+_slabSize]) ztop = - _zVelocityOb[index];
1145
if((_obstacles[index - _slabSize] & 8) && abs(_zVelocityOb[index - _slabSize]) > FLT_EPSILON)
1147
// printf("velocity z!\n");
1148
_zVelocity[index] = _zVelocityOb[index - _slabSize];
1149
_zVelocity[index - _slabSize] = _zVelocityOb[index - _slabSize];
1154
_density[index] = 0;
1160
//vIndex += 2 * _xRes;
858
1164
//////////////////////////////////////////////////////////////////////
1098
1423
for (int x = 1; x < _xRes - 1; x++, index++)
1101
int up = _obstacles[index + _xRes] ? index : index + _xRes;
1102
int down = _obstacles[index - _xRes] ? index : index - _xRes;
1103
float dy = (up == index || down == index) ? 1.0f / _dx : gridSize;
1104
int out = _obstacles[index + _slabSize] ? index : index + _slabSize;
1105
int in = _obstacles[index - _slabSize] ? index : index - _slabSize;
1106
float dz = (out == index || in == index) ? 1.0f / _dx : gridSize;
1107
int right = _obstacles[index + 1] ? index : index + 1;
1108
int left = _obstacles[index - 1] ? index : index - 1;
1109
float dx = (right == index || left == index) ? 1.0f / _dx : gridSize;
1111
_xVorticity[vIndex] = (_zVelocity[up] - _zVelocity[down]) * dy + (-_yVelocity[out] + _yVelocity[in]) * dz;
1112
_yVorticity[vIndex] = (_xVelocity[out] - _xVelocity[in]) * dz + (-_zVelocity[right] + _zVelocity[left]) * dx;
1113
_zVorticity[vIndex] = (_yVelocity[right] - _yVelocity[left]) * dx + (-_xVelocity[up] + _xVelocity[down])* dy;
1115
_vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] +
1425
if (!_obstacles[index])
1429
obpos[0] = (_obstacles[index + _xRes] == 1) ? index : index + _xRes; // up
1430
obpos[1] = (_obstacles[index - _xRes] == 1) ? index : index - _xRes; // down
1431
float dy = (obpos[0] == index || obpos[1] == index) ? 1.0f / _dx : gridSize;
1433
obpos[2] = (_obstacles[index + _slabSize] == 1) ? index : index + _slabSize; // out
1434
obpos[3] = (_obstacles[index - _slabSize] == 1) ? index : index - _slabSize; // in
1435
float dz = (obpos[2] == index || obpos[3] == index) ? 1.0f / _dx : gridSize;
1437
obpos[4] = (_obstacles[index + 1] == 1) ? index : index + 1; // right
1438
obpos[5] = (_obstacles[index - 1] == 1) ? index : index - 1; // left
1439
float dx = (obpos[4] == index || obpos[5] == index) ? 1.0f / _dx : gridSize;
1441
float xV[2], yV[2], zV[2];
1443
zV[1] = VORT_VEL(0, 2);
1444
zV[0] = VORT_VEL(1, 2);
1445
yV[1] = VORT_VEL(2, 1);
1446
yV[0] = VORT_VEL(3, 1);
1447
_xVorticity[vIndex] = (zV[1] - zV[0]) * dy + (-yV[1] + yV[0]) * dz;
1449
xV[1] = VORT_VEL(2, 0);
1450
xV[0] = VORT_VEL(3, 0);
1451
zV[1] = VORT_VEL(4, 2);
1452
zV[0] = VORT_VEL(5, 2);
1453
_yVorticity[vIndex] = (xV[1] - xV[0]) * dz + (-zV[1] + zV[0]) * dx;
1455
yV[1] = VORT_VEL(4, 1);
1456
yV[0] = VORT_VEL(5, 1);
1457
xV[1] = VORT_VEL(0, 0);
1458
xV[0] = VORT_VEL(1, 0);
1459
_zVorticity[vIndex] = (yV[1] - yV[0]) * dx + (-xV[1] + xV[0])* dy;
1461
_vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] +
1116
1462
_yVorticity[vIndex] * _yVorticity[vIndex] +
1117
1463
_zVorticity[vIndex] * _zVorticity[vIndex]);
1147
int up = _obstacles[index + _xRes] ? vIndex : vIndex + _xRes;
1148
int down = _obstacles[index - _xRes] ? vIndex : vIndex - _xRes;
1494
int up = (_obstacles[index + _xRes] == 1) ? vIndex : vIndex + _xRes;
1495
int down = (_obstacles[index - _xRes] == 1) ? vIndex : vIndex - _xRes;
1149
1496
float dy = (up == vIndex || down == vIndex) ? 1.0f / _dx : gridSize;
1150
int out = _obstacles[index + _slabSize] ? vIndex : vIndex + _slabSize;
1151
int in = _obstacles[index - _slabSize] ? vIndex : vIndex - _slabSize;
1498
int out = (_obstacles[index + _slabSize] == 1) ? vIndex : vIndex + _slabSize;
1499
int in = (_obstacles[index - _slabSize] == 1) ? vIndex : vIndex - _slabSize;
1152
1500
float dz = (out == vIndex || in == vIndex) ? 1.0f / _dx : gridSize;
1153
int right = _obstacles[index + 1] ? vIndex : vIndex + 1;
1154
int left = _obstacles[index - 1] ? vIndex : vIndex - 1;
1502
int right = (_obstacles[index + 1] == 1) ? vIndex : vIndex + 1;
1503
int left = (_obstacles[index - 1] == 1) ? vIndex : vIndex - 1;
1155
1504
float dx = (right == vIndex || left == vIndex) ? 1.0f / _dx : gridSize;
1156
1506
N[0] = (_vorticity[right] - _vorticity[left]) * dx;
1157
1507
N[1] = (_vorticity[up] - _vorticity[down]) * dy;
1158
1508
N[2] = (_vorticity[out] - _vorticity[in]) * dz;
1160
1510
float magnitude = sqrtf(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]);
1161
if (magnitude > 0.0f)
1511
if (magnitude > FLT_EPSILON)
1513
float flame_vort = (_fuel) ? _fuel[index]*flame_vorticity : 0.0f;
1163
1514
magnitude = 1.0f / magnitude;
1164
1515
N[0] *= magnitude;
1165
1516
N[1] *= magnitude;
1166
1517
N[2] *= magnitude;
1168
_xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * eps;
1169
_yForce[index] -= (N[0] * _zVorticity[vIndex] - N[2] * _xVorticity[vIndex]) * _dx * eps;
1170
_zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * eps;
1519
_xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * (eps + flame_vort);
1520
_yForce[index] += (N[2] * _xVorticity[vIndex] - N[0] * _zVorticity[vIndex]) * _dx * (eps + flame_vort);
1521
_zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * (eps + flame_vort);
1215
1561
// advectFieldMacCormack1(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res)
1217
1563
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _densityTemp, res, zBegin, zEnd);
1218
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd);
1565
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd);
1568
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _fuelOld, _fuelTemp, res, zBegin, zEnd);
1569
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _reactOld, _reactTemp, res, zBegin, zEnd);
1572
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_rOld, _color_rTemp, res, zBegin, zEnd);
1573
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_gOld, _color_gTemp, res, zBegin, zEnd);
1574
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_bOld, _color_bTemp, res, zBegin, zEnd);
1219
1576
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, res, zBegin, zEnd);
1220
1577
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, res, zBegin, zEnd);
1221
1578
advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, res, zBegin, zEnd);
1231
1588
const float dt0 = _dt / _dx;
1232
1589
Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
1234
// use force array as temp arrays
1591
// use force array as temp array
1235
1592
float* t1 = _xForce;
1237
1594
// advectFieldMacCormack2(dt, xVelocity, yVelocity, zVelocity, oldField, newField, tempfield, temp, res, obstacles)
1596
/* finish advection */
1239
1597
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, _densityTemp, t1, res, _obstacles, zBegin, zEnd);
1240
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd);
1599
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd);
1602
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _fuelOld, _fuel, _fuelTemp, t1, res, _obstacles, zBegin, zEnd);
1603
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _reactOld, _react, _reactTemp, t1, res, _obstacles, zBegin, zEnd);
1606
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_rOld, _color_r, _color_rTemp, t1, res, _obstacles, zBegin, zEnd);
1607
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_gOld, _color_g, _color_gTemp, t1, res, _obstacles, zBegin, zEnd);
1608
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_bOld, _color_b, _color_bTemp, t1, res, _obstacles, zBegin, zEnd);
1241
1610
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocityTemp, _xVelocity, t1, res, _obstacles, zBegin, zEnd);
1242
1611
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd);
1243
1612
advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd);
1245
if(_domainBcLeft == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
1614
/* set boundary conditions for velocity */
1615
if(!_domainBcLeft) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
1246
1616
else setZeroX(_xVelocityTemp, res, zBegin, zEnd);
1248
if(_domainBcFront == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
1618
if(!_domainBcFront) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
1249
1619
else setZeroY(_yVelocityTemp, res, zBegin, zEnd);
1251
if(_domainBcTop == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
1621
if(!_domainBcTop) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
1252
1622
else setZeroZ(_zVelocityTemp, res, zBegin, zEnd);
1624
/* clear data boundaries */
1254
1625
setZeroBorder(_density, res, zBegin, zEnd);
1255
setZeroBorder(_heat, res, zBegin, zEnd);
1258
/*int begin=zBegin * _slabSize;
1259
int end=begin + (zEnd - zBegin) * _slabSize;
1260
for (int x = begin; x < end; x++)
1261
_xForce[x] = _yForce[x] = 0.0f;*/
1627
setZeroBorder(_fuel, res, zBegin, zEnd);
1628
setZeroBorder(_react, res, zBegin, zEnd);
1631
setZeroBorder(_color_r, res, zBegin, zEnd);
1632
setZeroBorder(_color_g, res, zBegin, zEnd);
1633
setZeroBorder(_color_b, res, zBegin, zEnd);
1638
void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat,
1639
float *r, float *g, float *b, int total_cells, float dt)
1641
float burning_rate = *_burning_rate;
1642
float flame_smoke = *_flame_smoke;
1643
float ignition_point = *_ignition_temp;
1644
float temp_max = *_max_temp;
1646
for (int index = 0; index < total_cells; index++)
1648
float orig_fuel = fuel[index];
1649
float orig_smoke = smoke[index];
1650
float smoke_emit = 0.0f;
1651
float react_coord = 0.0f;
1654
fuel[index] -= burning_rate * dt;
1655
if (fuel[index] < 0.0f) fuel[index] = 0.0f;
1656
/* process reaction coordinate */
1657
if (orig_fuel > FLT_EPSILON) {
1658
react[index] *= fuel[index]/orig_fuel;
1659
react_coord = react[index];
1662
react[index] = 0.0f;
1665
/* emit smoke based on fuel burn rate and "flame_smoke" factor */
1666
smoke_emit = (orig_fuel < 1.0f) ? (1.0f - orig_fuel)*0.5f : 0.0f;
1667
smoke_emit = (smoke_emit + 0.5f) * (orig_fuel-fuel[index]) * 0.1f * flame_smoke;
1668
smoke[index] += smoke_emit;
1669
CLAMP(smoke[index], 0.0f, 1.0f);
1671
/* model flame temperature curve from the reaction coordinate (fuel) */
1672
if (react_coord>0.0f) {
1673
/* do a smooth falloff for rest of the values */
1674
flame[index] = pow(react_coord, 0.5f);
1677
flame[index] = 0.0f;
1679
/* set fluid temperature from the flame temperature profile */
1680
if (heat && flame[index])
1681
heat[index] = (1.0f-flame[index])*ignition_point + flame[index]*temp_max;
1684
if (r && smoke_emit > FLT_EPSILON) {
1685
float smoke_factor = smoke[index]/(orig_smoke+smoke_emit);
1686
r[index] = (r[index] + _flame_smoke_color[0] * smoke_emit) * smoke_factor;
1687
g[index] = (g[index] + _flame_smoke_color[1] * smoke_emit) * smoke_factor;
1688
b[index] = (b[index] + _flame_smoke_color[2] * smoke_emit) * smoke_factor;