5 #include "../confparser/ConfParser.h"
7 #include "../lbm/LBM_def.h"
23 std::cout <<
"Parsed configuration file " << configFileName << std::endl;
30 }
catch ( std::exception& e ) {
31 std::cerr << e.what() << std::endl;
33 }
catch (
const char* e ) {
34 std::cerr << e << std::endl;
44 std::cout <<
"Setting up ParticleSystem..." << std::endl;
48 if ( paramBlock == NULL )
throw "No domain size given.";
52 std::cout <<
"Read domain specification:" << std::endl;
53 std::cout <<
"sizeX : " <<
sizeX_ << std::endl;
54 std::cout <<
"sizeY : " << sizeY_ << std::endl;
55 std::cout <<
"sizeZ : " << sizeZ_ << std::endl;
58 paramBlock = base.
find(
"parameters" );
59 if ( paramBlock == NULL )
throw "No parameter specification given.";
63 float g_x = paramBlock->
getParam<
float>(
"g_x" );
64 float g_y = paramBlock->
getParam<
float>(
"g_y" );
65 float g_z = paramBlock->
getParam<
float>(
"g_z" );
66 gravity_ = core::vector3df( g_x, g_y, g_z );
70 std::cout <<
"Read parameter specification:" << std::endl;
71 std::cout <<
"alpha (conservation coefficient) : " <<
alpha_ << std::endl;
72 std::cout <<
"beta (transferability coefficient) : " << beta_ << std::endl;
73 std::cout <<
"k (thermal expansion coefficient) : " << k_ << std::endl;
74 std::cout <<
"Gravity unit vector : <" << g_x <<
"," << g_y <<
"," << g_z <<
">" << std::endl;
75 std::cout <<
"Temperature threshold for smoke (K): " <<
smokeTemp_ << std::endl;
76 std::cout <<
"Ambient temperature (K) : " << ambTemp_ << std::endl;
77 std::cout <<
"Number of steps : " << maxSteps_ << std::endl;
80 int maxElem = sqrt(
sizeX_ *
sizeX_ + sizeY_ * sizeY_ + sizeZ_ * sizeZ_ );
82 float a = 1. / sqrt( 2. * M_PI );
83 for (
int i = 0; i < maxElem; ++i ) {
88 paramBlock = base.
find(
"particles" );
89 if ( paramBlock == NULL )
throw "No particle emitters specified.";
90 std::cout <<
"Set up the particle system..." << std::endl;
102 float xStart = b.
getParam<
float>(
"xStart" );
103 float xEnd = b.
getParam<
float>(
"xEnd" );
104 float yStart = b.
getParam<
float>(
"yStart" );
105 float yEnd = b.
getParam<
float>(
"yEnd" );
106 float zStart = b.
getParam<
float>(
"zStart" );
107 float zEnd = b.
getParam<
float>(
"zEnd" );
108 float temp = b.
getParam<
float>(
"temp" );
109 if ( temp > maxTemp ) maxTemp = temp;
110 int fuel = b.
getParam<
int>(
"fuel" );
111 int emitThreshold = b.
getParam<
int>(
"emitThreshold" );
112 float fuelConsumption = b.
getParam<
float>(
"fuelConsumption" );
113 float lifetimeCoeff = b.
getParam<
float>(
"lifetimeCoeff" );
114 std::cout <<
"Read emitter specification:" << std::endl;
115 std::cout <<
"xStart : " << xStart << std::endl;
116 std::cout <<
"xEnd : " << xEnd << std::endl;
117 std::cout <<
"yStart : " << yStart << std::endl;
118 std::cout <<
"yEnd : " << yEnd << std::endl;
119 std::cout <<
"zStart : " << zStart << std::endl;
120 std::cout <<
"zEnd : " << zEnd << std::endl;
121 std::cout <<
"temp : " << temp << std::endl;
122 std::cout <<
"fuel : " << fuel << std::endl;
123 std::cout <<
"emitThreshold : " << emitThreshold << std::endl;
124 std::cout <<
"fuelConsumption : " << fuelConsumption << std::endl;
125 std::cout <<
"lifetimeCoeff : " << lifetimeCoeff << std::endl;
128 core::vector3df( xEnd - xStart,
140 paramBlock = base.
find(
"irrlicht" );
141 if ( paramBlock == NULL ) {
142 std::cout <<
"No irrlicht configuration specified in configuration file. No real-time visualization will be done." << std::endl;
144 std::cout <<
"Set up irrlicht configuration..." << std::endl;
150 int xRes = paramBlock->
getParam<
int>(
"xRes" );
151 int yRes = paramBlock->
getParam<
int>(
"yRes" );
153 std::string camera = paramBlock->
getParam<std::string>(
"camera" );
160 device_ = createDevice( video::EDT_OPENGL, core::dimension2du(xRes,yRes), 24 );
161 if (!device_)
throw "Could not create OpenGL device.";
162 smgr_ = device_->getSceneManager();
163 drvr_ = device_->getVideoDriver();
168 if ( paramBlock->
getParam<
int>(
"ambLight", ambLight ) )
169 smgr_->setAmbientLight( video::SColor(255,ambLight,ambLight,ambLight) );
172 if ( camera ==
"animated" ) {
173 scene::ICameraSceneNode* cam =
174 smgr_->addCameraSceneNode( 0,
175 core::vector3df(
sizeX_/2, sizeY_/2, -sizeZ_/2 ),
176 core::vector3df(
sizeX_/2, sizeY_/2, 0 ) );
177 cam->addAnimator(
smgr_->createFlyCircleAnimator(
178 core::vector3df(
sizeX_/2, sizeY_/2, sizeZ_/2 ),
181 core::vector3df(0.f, 1.f, 0.f)
183 }
else if ( camera ==
"fps" ) {
184 scene::ICameraSceneNode* cam =
185 smgr_->addCameraSceneNodeFPS( 0, 100.0f, .1f );
186 cam->setPosition(core::vector3df(
sizeX_/2, sizeY_/2, -sizeZ_/2 ));
188 smgr_->addCameraSceneNode( 0,
189 core::vector3df(
sizeX_/2, sizeY_/2, -sizeZ_/2 ),
190 core::vector3df(
sizeX_/2, sizeY_/2, 0 ) );
193 cip = paramBlock->
findAll(
"texture" );
199 std::string file = b.
getParam<std::string>(
"file" );
203 cip = paramBlock->
findAll(
"plane" );
209 std::string name = b.
getParam<std::string>(
"name" );
211 b.
getParam<std::string>(
"texture", texture );
213 b.
getParam<
bool>(
"lighting", lighting );
214 float sizeTile = b.
getParam<
float>(
"sizeTile" );
215 int numTile = b.
getParam<
int>(
"numTile" );
216 float xCenter = b.
getParam<
float>(
"xCenter" );
217 float yCenter = b.
getParam<
float>(
"yCenter" );
218 float zCenter = b.
getParam<
float>(
"zCenter" );
219 float xRot = 0., yRot = 0., zRot = 0.;
225 scene::IAnimatedMesh *terrain_model =
226 smgr_->addHillPlaneMesh( name.c_str(),
227 core::dimension2d<f32>( sizeTile, sizeTile ),
228 core::dimension2d<u32>(numTile, numTile),
231 core::dimension2d<f32>(0.0f, 0.0f),
232 core::dimension2d<f32>(numTile, numTile));
234 scene::IAnimatedMeshSceneNode* terrain_node =
235 smgr_->addAnimatedMeshSceneNode( terrain_model,
238 core::vector3df(xCenter,yCenter,zCenter),
239 core::vector3df(xRot,yRot,zRot));
240 if ( texture.length() ) terrain_node->setMaterialTexture(0,
drvr_->getTexture( texture.c_str() ));
241 terrain_node->setMaterialFlag(video::EMF_LIGHTING, lighting);
244 cip = paramBlock->
findAll(
"mesh" );
250 std::string file = b.
getParam<std::string>(
"file" );
251 std::string texture0, texture1;
252 b.
getParam<std::string>(
"texture0", texture0 );
253 b.
getParam<std::string>(
"texture1", texture1 );
255 b.
getParam<
bool>(
"lighting", lighting );
256 float xCenter = b.
getParam<
float>(
"xCenter" );
257 float yCenter = b.
getParam<
float>(
"yCenter" );
258 float zCenter = b.
getParam<
float>(
"zCenter" );
259 float scale = b.
getParam<
float>(
"scale" );
261 scene::IAnimatedMesh* mesh =
smgr_->getMesh( file.c_str() );
264 scene::ISceneNode* node =
smgr_->addMeshSceneNode(mesh->getMesh(0));
266 node->setPosition(core::vector3df(xCenter,yCenter,zCenter));
267 if ( texture0.length() ) node->setMaterialTexture(0,
drvr_->getTexture( texture0.c_str() ));
268 if ( texture1.length() ) node->setMaterialTexture(1,
drvr_->getTexture( texture1.c_str() ));
269 node->setMaterialFlag(video::EMF_LIGHTING, lighting);
270 node->setScale( core::vector3df( scale, scale, scale ) );
276 std::cout <<
"Generate black body color table..." << std::endl;
282 paramBlock = base.
find(
"obstacles" );
283 if ( paramBlock == NULL ) {
284 std::cout <<
"No obstacles defined." << std::endl;
287 std::cout <<
"Set up the obstacles..." << std::endl;
294 bool visible = b.
getParam<
bool>(
"visible" );
295 int xStart = b.
getParam<
int>(
"xStart" );
296 int xEnd = b.
getParam<
int>(
"xEnd" ) + 1;
297 int yStart = b.
getParam<
int>(
"yStart" );
298 int yEnd = b.
getParam<
int>(
"yEnd" ) + 1;
299 int zStart = b.
getParam<
int>(
"zStart" );
300 int zEnd = b.
getParam<
int>(
"zEnd" ) + 1;
301 int dx = xEnd - xStart;
302 int dy = yEnd - yStart;
303 int dz = zEnd - zStart;
305 std::cout <<
"Stationary cuboid ranging from <" << xStart <<
",";
306 std::cout << yStart <<
"," << zStart <<
"> to <" << xEnd <<
"," << yEnd;
307 std::cout <<
"," << zEnd <<
">" << std::endl;
311 b.
getParam<std::string>(
"texture", texture );
313 b.
getParam<
bool>(
"lighting", lighting );
314 scene::IMeshSceneNode* mesh =
smgr_->addCubeSceneNode ( 1.0f,
317 core::vector3df( xStart + 0.5 * dx,
320 core::vector3df( 0, 0, 0 ),
321 core::vector3df( dx, dy, dz )
323 mesh->setMaterialFlag( video::EMF_LIGHTING, lighting );
324 if ( texture.length() ) mesh->setMaterialTexture( 0,
drvr_->getTexture( texture.c_str() ) );
327 core::aabbox3df( xStart, yStart, zStart, xEnd, yEnd, zEnd ) );
330 bit = paramBlock->
findAll(
"sphere_stationary" );
335 bool visible = bl.
getParam<
bool>(
"visible" );
336 float xCenter = bl.
getParam<
float>(
"xCenter" );
337 float yCenter = bl.
getParam<
float>(
"yCenter" );
338 float zCenter = bl.
getParam<
float>(
"zCenter" );
339 float radius = bl.
getParam<
float>(
"radius" );
341 std::cout <<
"Stationary sphere centered at <" << xCenter <<
",";
342 std::cout << yCenter <<
"," << zCenter <<
"> with radius " << radius;
343 std::cout << std::endl;
348 bl.
getParam<std::string>(
"texture", texture );
350 bl.
getParam<
bool>(
"lighting", lighting );
351 scene::IMeshSceneNode* mesh =
smgr_->addSphereSceneNode( radius,
355 core::vector3df( xCenter, yCenter, zCenter ) );
356 mesh->setMaterialFlag( video::EMF_LIGHTING, lighting );
357 if ( texture.length() ) mesh->setMaterialTexture( 0,
drvr_->getTexture( texture.c_str() ) );
358 spheres_.push_back(
Sphere( xCenter, yCenter, zCenter, radius, 0.0, 0.0, 0.0, mesh ) );
360 spheres_.push_back(
Sphere( xCenter, yCenter, zCenter, radius ) );
364 bit = paramBlock->
findAll(
"sphere_moving" );
369 bool visible = bl.
getParam<
bool>(
"visible" );
370 float xCenter = bl.
getParam<
float>(
"xCenter" );
371 float yCenter = bl.
getParam<
float>(
"yCenter" );
372 float zCenter = bl.
getParam<
float>(
"zCenter" );
373 float radius = bl.
getParam<
float>(
"radius" );
374 float u_x = bl.
getParam<
float>(
"u_x" );
375 float u_y = bl.
getParam<
float>(
"u_y" );
376 float u_z = bl.
getParam<
float>(
"u_z" );
378 std::cout <<
"Moving sphere centered at <" << xCenter <<
",";
379 std::cout << yCenter <<
"," << zCenter <<
"> with radius " << radius;
380 std::cout <<
" and u=<" << u_x <<
"," << u_y <<
"," << u_z <<
">";
381 std::cout << std::endl;
386 bl.
getParam<std::string>(
"texture", texture );
388 bl.
getParam<
bool>(
"lighting", lighting );
389 scene::IMeshSceneNode* mesh =
smgr_->addSphereSceneNode( radius,
393 core::vector3df( xCenter, yCenter, zCenter ) );
394 mesh->setMaterialFlag( video::EMF_LIGHTING, lighting );
395 if ( texture.length() ) mesh->setMaterialTexture( 0,
drvr_->getTexture( texture.c_str() ) );
396 spheres_.push_back(
Sphere( xCenter, yCenter, zCenter, radius, u_x, u_y, u_z, mesh ) );
398 spheres_.push_back(
Sphere( xCenter, yCenter, zCenter, radius, u_x, u_y, u_z ) );
403 }
catch ( std::exception& e ) {
404 std::cerr << e.what() << std::endl;
406 }
catch (
const char* e ) {
407 std::cerr << e << std::endl;
411 std::cout <<
"ParticleSystem setup finished!" << std::endl;
423 float totTime = 0., eTimeTot = 0., iTimeTot = 0., sTimeTot = 0., uTimeTot = 0.;
424 std::ofstream updFile, irrFile;
427 updFile <<
"\"Number of Particles\" \"Step time\" \"Emission time\" \"LBM step time\" \"Update time\"\n";
431 irrFile <<
"\"Number of Particles\" \"Sprites per particle\" \"Step time\" \"Emission time\" \"Rendering time\" \"LBM step time\" \"Update time\" \"FPS\"\n";
437 struct timeval start, end;
440 gettimeofday(&start, NULL);
445 gettimeofday(&end, NULL);
446 float eTime =
getTime( start, end );
449 drvr_->beginScene(
true,
true, video::SColor(255,0,0,0));
453 gettimeofday(&start, NULL);
454 float iTime =
getTime( end, start );
457 core::stringw str = L
"LBM fire simulation [";
458 str +=
drvr_->getName();
460 str += (s32)
drvr_->getFPS();
461 str += L
", Particles: ";
463 str += L
", Time step: ";
467 device_->setWindowCaption( str.c_str() );
470 std::ostringstream oss;
471 oss <<
screenshots_ <<
"." << std::setw(4) << std::setfill(
'0') << step <<
".jpg";
472 drvr_->writeImageToFile(
drvr_->createScreenShot(), oss.str().c_str(), 85 );
478 gettimeofday(&start, NULL);
483 gettimeofday(&end, NULL);
484 float uTime =
getTime( start, end );
486 stepTime = eTime + iTime + sTime + uTime;
493 std::cout << step <<
" / " <<
maxSteps_ <<
": ";
494 std::cout << eTime <<
" + " << iTime <<
" + " << sTime <<
" + " << uTime;
495 std::cout <<
" = " << stepTime <<
"s, particles: " <<
numParticles_;
496 std::cout << std::endl;
499 updFile << numParticles_ <<
" " << stepTime <<
" " << eTime <<
" " << sTime <<
" " << uTime <<
"\n";
501 irrFile << numParticles_ <<
" " <<
numSprites_ <<
" " << stepTime <<
" " << eTime <<
" " << iTime <<
" " << sTime <<
" " << uTime <<
" " <<
drvr_->getFPS() <<
"\n";
504 if ( ++step >= maxSteps_ )
break;
513 std::ofstream updFile;
516 updFile <<
"\"Number of Particles\" \"Step time\" \"Emission time\" \"LBM step time\" \"Update time\"\n";
519 for (
int step = 20; step <
maxSteps_; ++step ) {
521 struct timeval start, end;
524 gettimeofday(&start, NULL);
529 gettimeofday(&end, NULL);
530 float eTime =
getTime( start, end );
535 gettimeofday(&start, NULL);
540 gettimeofday(&end, NULL);
541 float uTime =
getTime( start, end );
543 stepTime = eTime + sTime + uTime;
545 std::cout <<
"Time step " << step <<
" of " << maxSteps_ <<
" took ";
546 std::cout << eTime <<
" + " << sTime <<
" + " << uTime <<
" = ";
547 std::cout << stepTime <<
"secs with " <<
numParticles_ <<
" particles";
548 std::cout << std::endl;
551 updFile << numParticles_ <<
" " << stepTime <<
" " << eTime <<
" " << sTime <<
" " << uTime <<
"\n";
561 std::vector< Emitter >::iterator ite, ite2;
562 std::list< Particle >::iterator itp, itp2;
565 float szCoeff = 1. / ( (*ite).fuel_ * (*ite).lifetimeCoeff_ );
566 for ( itp = (*ite).particles_.begin(); itp != (*ite).particles_.end(); ++itp) {
569 while ( itp != (*ite).particles_.end() && ( (*itp).lifetime_ < 1 ||
570 (*itp).getPos().X < 1 || (*itp).getPos().X >
sizeX_ - 1 ||
571 (*itp).getPos().Y < 1 || (*itp).getPos().Y >
sizeY_ - 1 ||
572 (*itp).getPos().Z < 1 || (*itp).getPos().Z >
sizeZ_ -1 ||
576 itp = (*ite).particles_.erase( itp );
581 if ( itp == (*ite).particles_.end() )
break;
585 core::vector3df v = core::vector3df( vel[0], vel[1], vel[2] );
590 bool inObstacle =
false;
591 core::vector3df u = (*itp).pos_ + g + v;
592 for ( uint i = 0; i <
obstacles_.size(); ++i )
598 for ( uint i = 0; i <
spheres_.size(); ++i )
599 if(
spheres_[i].isPointInside( u ) ) {
605 if ( !inObstacle ) (*itp).updatePos( v + g );
607 else (*itp).updatePos( v );
611 (*itp).setSize( sz );
617 for ( itp2 = (*ite2).particles_.begin(); itp2 != (*ite2).particles_.end(); ++itp2) {
618 tempExt +=
gaussTable_[ (int) (*itp).dist( *itp2 ) ] * (*itp2).temp_;
621 (*itp).temp_ =
alpha_ * (*itp).temp_ +
beta_ * tempExt;
623 if ( (*itp).type_ ==
FIRE ) {
627 (*itp).setSmoke( szCoeff );
634 (*itp).setColor( video::SColor( 255 * (*itp).lifetime_ * szCoeff,
635 255 * (*itp).lifetime_ * szCoeff,
636 255 * (*itp).lifetime_ * szCoeff,
637 255 * (*itp).lifetime_ * szCoeff) );
645 for ( uint i = 0; i <
spheres_.size(); ++i ) {
653 std::vector< Emitter >::iterator ite;
656 for (
int i = 0; i < (*ite).emitThreshold_; ++i ) {
657 core::vector3df pos = (*ite).pos_ + core::vector3df(
658 ( std::rand() * (*ite).size_.X ) / (
float) RAND_MAX,
659 ( std::rand() * (*ite).size_.Y ) / (
float) RAND_MAX,
660 ( std::rand() * (*ite).size_.Z ) / (
float) RAND_MAX
664 (*ite).particles_.push_back(
674 (
int) ((*ite).fuel_ * (*ite).lifetimeCoeff_ ),
679 (*ite).particles_.push_back(
680 Particle( pos, (*ite).temp_, (
int) ((*ite).fuel_ * (*ite).lifetimeCoeff_ ) ) );
682 (*ite).fuel_ *= (*ite).fuelConsumption_;
690 float cie_colour_match[81][3] = {
691 {0.0014,0.0000,0.0065}, {0.0022,0.0001,0.0105}, {0.0042,0.0001,0.0201},
692 {0.0076,0.0002,0.0362}, {0.0143,0.0004,0.0679}, {0.0232,0.0006,0.1102},
693 {0.0435,0.0012,0.2074}, {0.0776,0.0022,0.3713}, {0.1344,0.0040,0.6456},
694 {0.2148,0.0073,1.0391}, {0.2839,0.0116,1.3856}, {0.3285,0.0168,1.6230},
695 {0.3483,0.0230,1.7471}, {0.3481,0.0298,1.7826}, {0.3362,0.0380,1.7721},
696 {0.3187,0.0480,1.7441}, {0.2908,0.0600,1.6692}, {0.2511,0.0739,1.5281},
697 {0.1954,0.0910,1.2876}, {0.1421,0.1126,1.0419}, {0.0956,0.1390,0.8130},
698 {0.0580,0.1693,0.6162}, {0.0320,0.2080,0.4652}, {0.0147,0.2586,0.3533},
699 {0.0049,0.3230,0.2720}, {0.0024,0.4073,0.2123}, {0.0093,0.5030,0.1582},
700 {0.0291,0.6082,0.1117}, {0.0633,0.7100,0.0782}, {0.1096,0.7932,0.0573},
701 {0.1655,0.8620,0.0422}, {0.2257,0.9149,0.0298}, {0.2904,0.9540,0.0203},
702 {0.3597,0.9803,0.0134}, {0.4334,0.9950,0.0087}, {0.5121,1.0000,0.0057},
703 {0.5945,0.9950,0.0039}, {0.6784,0.9786,0.0027}, {0.7621,0.9520,0.0021},
704 {0.8425,0.9154,0.0018}, {0.9163,0.8700,0.0017}, {0.9786,0.8163,0.0014},
705 {1.0263,0.7570,0.0011}, {1.0567,0.6949,0.0010}, {1.0622,0.6310,0.0008},
706 {1.0456,0.5668,0.0006}, {1.0026,0.5030,0.0003}, {0.9384,0.4412,0.0002},
707 {0.8544,0.3810,0.0002}, {0.7514,0.3210,0.0001}, {0.6424,0.2650,0.0000},
708 {0.5419,0.2170,0.0000}, {0.4479,0.1750,0.0000}, {0.3608,0.1382,0.0000},
709 {0.2835,0.1070,0.0000}, {0.2187,0.0816,0.0000}, {0.1649,0.0610,0.0000},
710 {0.1212,0.0446,0.0000}, {0.0874,0.0320,0.0000}, {0.0636,0.0232,0.0000},
711 {0.0468,0.0170,0.0000}, {0.0329,0.0119,0.0000}, {0.0227,0.0082,0.0000},
712 {0.0158,0.0057,0.0000}, {0.0114,0.0041,0.0000}, {0.0081,0.0029,0.0000},
713 {0.0058,0.0021,0.0000}, {0.0041,0.0015,0.0000}, {0.0029,0.0010,0.0000},
714 {0.0020,0.0007,0.0000}, {0.0014,0.0005,0.0000}, {0.0010,0.0004,0.0000},
715 {0.0007,0.0002,0.0000}, {0.0005,0.0002,0.0000}, {0.0003,0.0001,0.0000},
716 {0.0002,0.0001,0.0000}, {0.0002,0.0001,0.0000}, {0.0001,0.0000,0.0000},
717 {0.0001,0.0000,0.0000}, {0.0001,0.0000,0.0000}, {0.0000,0.0000,0.0000}
720 for (
float t =
smokeTemp_; t < maxTemp; t += 50. ) {
725 float lambda, x = 0, y = 0, z = 0, xyz;
726 for (i = 0, lambda = 380; lambda < 780.1; i++, lambda += 5) {
730 float wlm = lambda * 1e-9;
731 Me = (3.74183e-16 * pow(wlm, -5.0)) / (exp(1.4388e-2 / (wlm * t)) - 1.0);
732 x += Me * cie_colour_match[i][0];
733 y += Me * cie_colour_match[i][1];
734 z += Me * cie_colour_match[i][2];
743 float xr, yr, zr, xg, yg, zg, xb, yb, zb;
745 float rx, ry, rz, gx, gy, gz, bx, by, bz;
748 xr = 0.630; yr = 0.340; zr = 1 - (xr + yr);
749 xg = 0.310; yg = 0.595; zg = 1 - (xg + yg);
750 xb = 0.155; yb = 0.070; zb = 1 - (xb + yb);
752 xw = 0.3127; yw = 0.3291; zw = 1 - (xw + yw);
755 rx = (yg * zb) - (yb * zg); ry = (xb * zg) - (xg * zb); rz = (xg * yb) - (xb * yg);
756 gx = (yb * zr) - (yr * zb); gy = (xr * zb) - (xb * zr); gz = (xb * yr) - (xr * yb);
757 bx = (yr * zg) - (yg * zr); by = (xg * zr) - (xr * zg); bz = (xr * yg) - (xg * yr);
761 rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw;
762 gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw;
763 bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw;
766 rx = rx / rw; ry = ry / rw; rz = rz / rw;
767 gx = gx / gw; gy = gy / gw; gz = gz / gw;
768 bx = bx / bw; by = by / bw; bz = bz / bw;
771 float r = (rx * x) + (ry * y) + (rz * z);
772 float g = (gx * x) + (gy * y) + (gz * z);
773 float b = (bx * x) + (by * y) + (bz * z);
784 r +=
w; g +=
w; b +=
w;
788 float max = (r > b) ? ( (r > g) ? r : g ) : ( (b > g) ? b : g );
794 std::cout <<
"Temperature " << t <<
"K: RGB <" << r <<
", " << g <<
", " << b <<
">" << std::endl;
796 std::cout <<
"Generated black body color table from " <<
smokeTemp_;
797 std::cout <<
"K to " << maxTemp <<
"K (" <<
bbColorTable_.size() <<
" values)" << std::endl;