diff -Naurw source/Irrlicht/CFireSceneNode.cpp source/Irrlicht/CFireSceneNode.cpp --- source/Irrlicht/CFireSceneNode.cpp 1970-01-01 01:00:00.000000000 +0100 +++ source/Irrlicht/CFireSceneNode.cpp 2005-11-25 12:11:28.000000000 +0100 @@ -0,0 +1,202 @@ +#include "CFireSceneNode.h" +#include "os.h" + +namespace irr +{ +namespace scene +{ + + CFireSceneNode::CFireSceneNode( ISceneNode* parent, ISceneManager* mgr, c8* coolingTextureFilename, + const video::SColor& color, s32 fadeTo, f32 fadeRate, s32 textureX, s32 textureY, + f32 width, f32 height, u32 timeStep, s32 id, const core::vector3df& pos, const core::vector3df& rot ) + : ISceneNode( parent, mgr, id, pos, rot ) + , texX(textureX) + , texY(textureY) + , step(timeStep) + , timer1(0) + , coolOffset(0) + , fadeto(fadeTo) + , faderate(fadeRate) + { + driver = SceneManager->getVideoDriver(); + flameTexture = driver->addTexture(core::dimension2d(texX, texY), "", video::ECF_R8G8B8); + coolingTexture = driver->getTexture(coolingTextureFilename); + eraseTexture(flameTexture); + + f32 minX = - width / 2; + f32 maxX = width / 2; + f32 minZ = minX; + f32 maxZ = maxX; + + AutomaticCullingEnabled = false; + + boundingBox = core::aabbox3d(pos.X - maxX, pos.Y, pos.Z - maxZ, + pos.X + maxX, pos.Y + height, pos.Z + maxZ); + + plane1 = new video::S3DVertex[4]; + plane2 = new video::S3DVertex[4]; + indices = new u16[12]; + + video::SColor white = video::SColor(255, 255, 255, 255); + red = color.getRed(); + blue = color.getBlue(); + green = color.getGreen(); + + material.Lighting = false; + material.Wireframe = false; + material.Texture1 = flameTexture; + material.BackfaceCulling = false; + material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; + + plane1[0] = video::S3DVertex(0, 0, minZ, 0, 0, 0, white, 0.1f, 0.95f); + plane1[1] = video::S3DVertex(0, height, minZ, 0, 0, 0, white, 0.1f, 0.1f); + plane1[2] = video::S3DVertex(0, height, maxZ, 0, 0, 0, white, 0.95f, 0.1f); + plane1[3] = video::S3DVertex(0, 0, maxZ, 0, 0, 0, white, 0.95f, 0.95f); + plane2[0] = video::S3DVertex(minX, 0, 0, 0, 0, 0, white, 0.1f, 0.95f); + plane2[1] = video::S3DVertex(minX, height, 0, 0, 0, 0, white, 0.1f, 0.1f); + plane2[2] = video::S3DVertex(maxX, height, 0, 0, 0, 0, white, 0.95f, 0.1f); + plane2[3] = video::S3DVertex(maxX, 0, 0, 0, 0, 0, white, 0.95f, 0.95f); + indices[0] = 0; indices[1] = 1; indices[2] = 2; + indices[3] = 0; indices[4] = 2; indices[5] = 3; + } + + CFireSceneNode::~CFireSceneNode() + { + delete[] plane1; + delete[] plane2; + delete[] indices; + } + + void CFireSceneNode::OnPreRender() + { + if (IsVisible == true) + SceneManager->registerNodeForRendering(this); + + ISceneNode::OnPreRender(); + } + + void CFireSceneNode::render() + { + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + driver->setMaterial(material); + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + + u32 deltaTime = os::Timer::getTime() - prevTime; + timer1 += deltaTime; + + if (timer1 > step) + { + prevTime += deltaTime; + u8* pixels; + u8* pixels_cool; + pixels = (u8*)flameTexture->lock(); + pixels_cool = (u8*)coolingTexture->lock(); + s32 prev_index_minus1; + s32 prev_index_plus1; + s32 color_average; + s32 size_of_a_row = texX * 4; + s32 pix_count = (texY-1) * size_of_a_row; + s32 max_index = texY * size_of_a_row; + s32 cool_index_diff; + + for (s32 j = 1; j < texX - 1; j++) + { + s32 index = j * 4 + pix_count; + pixels[index] = blue; + pixels[index + 1] = green; + pixels[index + 2] = red; + } + + for (s32 i = 0; i < texY - 1; i++) + { + cool_index_diff = coolOffset * size_of_a_row; + s32 column = i * texX; + + for (s32 j = 1; j < texX - 1; j++) + { + s32 index = (column + j) * 4; + s32 cool_index = index + cool_index_diff; + cool_index %= max_index; + s32 prev_index = index + size_of_a_row; + prev_index_minus1 = prev_index-4; + prev_index_plus1 = prev_index+4; + + for (u32 k = 0; k != 3; k++) + { + color_average = + m( avg( pixels[prev_index + k], pixels[prev_index_minus1 + k], + pixels[prev_index_plus1 + k] ), + pixels_cool[cool_index + k] / 128.0f ); + + if (k != fadeto) + color_average = (s32)(color_average * faderate); + + pixels[index + k] = color_average; + } + } + } + + flameTexture->unlock(); + coolingTexture->unlock(); + pixels_cool = NULL; + pixels = NULL; + timer1 %= step; + coolOffset += 2; + + if (coolOffset >= texY) + coolOffset -= texY; + } + + driver->drawIndexedTriangleList(&plane1[0], 4, &indices[0], 2); + driver->drawIndexedTriangleList(&plane2[0], 4, &indices[0], 2); + } + + /***************************************************************** + PRIVATE FUNCTIONS + *****************************************************************/ + u8 CFireSceneNode::m(u8 a, f32 b) + { + if (b < 1.0f) + b = 1.0f; + + if (a > b) + a = (u8)(a/b); + + return a; + } + + u8 CFireSceneNode::avg( u8& a, u8& b, u8& c ) + { + u32 ret = 0; + ret += a; + ret += b; + ret += c; + ret /= 3; + return (u8)ret; + } + + void CFireSceneNode::eraseTexture(video::ITexture* texture) + { + u8* pixels; + pixels = (u8*)texture->lock(); + s32 w = texture->getSize().Width; + s32 h = texture->getSize().Height; + + for (s32 i = 0; i < w; i++) + { + for (s32 j = 0; j < h; j++) + { + s32 index = (i * h + j) * 4; + u8 rnd = (u8)(os::Randomizer::rand() % 255); + pixels[index] = 0; + pixels[index + 1] = 0; + pixels[index + 2] = 0; + } + } + + texture->unlock(); + } + +} // namespace scene +} // namespace irr + diff -Naurw source/Irrlicht/CFireSceneNode.h source/Irrlicht/CFireSceneNode.h --- source/Irrlicht/CFireSceneNode.h 1970-01-01 01:00:00.000000000 +0100 +++ source/Irrlicht/CFireSceneNode.h 2005-11-21 08:42:56.000000000 +0100 @@ -0,0 +1,64 @@ +// Copyright (C) 2005 Cestmir "CZestmyr" Houska +// This file uses the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in Irrlicht.h + +#ifndef _C_FIRE_SCENE_NODE_H_1674_ +#define _C_FIRE_SCENE_NODE_H_1674_ + +#include "irrlicht.h" + +namespace irr +{ +namespace scene +{ + + class CFireSceneNode : public ISceneNode + { + public: + CFireSceneNode( ISceneNode* parent, ISceneManager* mgr, + c8* coolingTextureFilename, const video::SColor& color = video::SColor(255,255,192,0), + s32 fadeTo = 2, f32 fadeRate = 0.95f, s32 textureX = 64, s32 textureY = 128, + f32 width = 10.0f, f32 height = 20.0f, u32 timeStep = 50, s32 id = -1, + const core::vector3df &pos = core::vector3df(0, 0, 0), + const core::vector3df &rot = core::vector3df(0, 0, 0) ); + ~CFireSceneNode(); + + void OnPreRender(); + void render(); + + const core::aabbox3df& getBoundingBox() const {return boundingBox;} + s32 getMaterialCount() { return 1; } + video::SMaterial& getMaterial(s32 i) { return material; } + + private: + u8 m(u8 a, f32 b); + u8 avg( u8& a, u8& b, u8& c ); + void eraseTexture(video::ITexture* texture); + + video::IVideoDriver* driver; + video::ITexture* flameTexture; + video::ITexture* coolingTexture; + s32 texX; + s32 texY; + s32 coolOffset; + video::S3DVertex* plane1; + video::S3DVertex* plane2; + u16* indices; + u32 prevTime; + u32 step; + u32 timer1; + core::aabbox3d boundingBox; + video::SMaterial material; + u8 red; + u8 green; + u8 blue; + u8 fadeto; + f32 faderate; + }; + +} // End namespace scene + +} // End namespace irr + +#endif + diff -Naurw source/Irrlicht/CSceneManager.cpp source/Irrlicht/CSceneManager.cpp --- source/Irrlicht/CSceneManager.cpp 2005-09-27 15:50:08.000000000 +0200 +++ source/Irrlicht/CSceneManager.cpp 2005-10-27 17:00:52.000000000 +0200 @@ -22,6 +22,7 @@ #include "COgreMeshFileLoader.h" #include "COBJMeshFileLoader.h" +#include "CFireSceneNode.h" #include "CCubeSceneNode.h" #include "CAnimatedMeshSceneNode.h" #include "COctTreeSceneNode.h" @@ -246,6 +248,25 @@ } +//! Adds a fire scene node for rendering procedural flames +ISceneNode* CSceneManager::addFireSceneNode( ISceneNode* parent, + c8* coolingTextureFilename, const video::SColor& color, s32 fadeTo, f32 fadeRate, + s32 textureX, s32 textureY, f32 width, f32 height, u32 timeStep, s32 id, + const core::vector3df& pos, const core::vector3df& rot ) +{ + if( !parent ) + parent = this; + + ISceneNode* node = new CFireSceneNode( parent, this, coolingTextureFilename, + color, fadeTo, fadeRate, textureX, textureY, width, height, timeStep, id, pos, rot ); + + node->drop(); + + return node; +} + + + //! Adds a scene node for rendering a animated water surface mesh. ISceneNode* CSceneManager::addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 waveLenght, ISceneNode* parent, s32 id, const core::vector3df& position, diff -Naurw source/Irrlicht/CSceneManager.h source/Irrlicht/CSceneManager.h --- source/Irrlicht/CSceneManager.h 2005-09-27 15:46:54.000000000 +0200 +++ source/Irrlicht/CSceneManager.h 2005-11-23 23:23:16.000000000 +0100 @@ -56,6 +56,14 @@ virtual ISceneNode* addMeshSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); + //! Adds a fire scene node for rendering procedural flames + virtual ISceneNode* addFireSceneNode( ISceneNode* parent, + c8* coolingTextureFilename, const video::SColor& color = video::SColor(255,255,192,0), + s32 fadeTo = 2, f32 fadeRate = 0.95f, s32 textureX = 64, s32 textureY = 128, + f32 width = 10.0f, f32 height = 20.0f, u32 timeStep = 50, s32 id = -1, + const core::vector3df &pos = core::vector3df(0, 0, 0), + const core::vector3df &rot = core::vector3df(0, 0, 0) ); + //! Adds a scene node for rendering a animated water surface mesh. virtual ISceneNode* addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 wlenght, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), diff -Naurw include/ISceneManager.h include/ISceneManager.h --- include/ISceneManager.h 2005-09-27 15:46:10.000000000 +0200 +++ include/ISceneManager.h 2005-11-23 23:22:50.000000000 +0100 @@ -385,6 +386,14 @@ const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + //! Adds a fire scene node for rendering procedural flames + virtual ISceneNode* addFireSceneNode( ISceneNode* parent, + c8* coolingTextureFilename, const video::SColor& color = video::SColor(255,255,192,0), + s32 fadeTo = 2, f32 fadeRate = 0.95f, s32 textureX = 64, s32 textureY = 128, + f32 width = 10.0f, f32 height = 20.0f, u32 timeStep = 50, s32 id = -1, + const core::vector3df &pos = core::vector3df(0, 0, 0), + const core::vector3df &rot = core::vector3df(0, 0, 0) ) = 0; + //! Adds a scene node for rendering a animated water surface mesh. /** Looks really good when the Material type EMT_TRANSPARENT_REFLECTION is used.