--- Irrlicht.old/CSceneManager.cpp 2005-03-28 10:28:44.000000000 +0200 +++ water/CSceneManager.cpp 2005-04-10 10:57:35.000000000 +0200 @@ -247,18 +247,18 @@ //! Adds a scene node for rendering a animated water surface mesh. -ISceneNode* CSceneManager::addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 waveLength, - ISceneNode* parent, s32 id, const core::vector3df& position, - const core::vector3df& rotation, const core::vector3df& scale) +IWaterSceneNode* CSceneManager::addWaterSurfaceSceneNode(core::dimension2d& m_TileCount, + f32 Size,f32 D,f32 T,f32 Mu,f32 C,ISceneNode* parent, s32 id, + const core::vector3df& position,const core::vector3df& rotation, + const core::vector3df& scale) { - if (!mesh) - return 0; - + if (!parent) parent = this; - ISceneNode* node = new CWaterSurfaceSceneNode(waveHeight, waveSpeed, waveLength, - mesh, parent, this, id, position, rotation, scale); + IWaterSceneNode* node = new CWaterSurfaceSceneNode(parent, this,m_TileCount, + Size , D , T , Mu , C ,id , + position , rotation , scale ); node->drop(); --- Irrlicht.old/CSceneManager.h 2005-03-28 10:28:44.000000000 +0200 +++ water/CSceneManager.h 2005-04-10 10:52:39.000000000 +0200 @@ -7,6 +7,7 @@ #include "ISceneManager.h" #include "ISceneNode.h" +#include "IWaterSceneNode.h" #include "ICursorControl.h" #include "irrString.h" #include "irrArray.h" @@ -56,10 +57,11 @@ 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 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), - const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); + virtual IWaterSceneNode* addWaterSurfaceSceneNode(core::dimension2d& m_TileCount, + f32 Size = 10.0f,f32 D = 0.45f,f32 T = 0.144f,f32 Mu = 0.051f,f32 C = 0.45f,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)); //! renders the node. virtual void render(); --- Irrlicht.old/CWaterSurfaceSceneNode.cpp 2005-03-28 10:28:44.000000000 +0200 +++ water/CWaterSurfaceSceneNode.cpp 2005-04-11 23:13:34.000000000 +0200 @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CWaterSurfaceSceneNode.h" +#include "CGeometryCreator.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "S3DVertex.h" @@ -11,6 +12,7 @@ #include "IMeshManipulator.h" #include "SMesh.h" #include "os.h" +#include namespace irr { @@ -20,27 +22,71 @@ //! constructor -CWaterSurfaceSceneNode::CWaterSurfaceSceneNode(f32 waveHeight, f32 waveSpeed, f32 waveLength, - IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, - const core::vector3df& position, const core::vector3df& rotation, - const core::vector3df& scale) -: CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale), OriginalMesh(0) +CWaterSurfaceSceneNode::CWaterSurfaceSceneNode(ISceneNode* parent, ISceneManager* mgr,core::dimension2d& m_TileCount, + f32 Size ,f32 D ,f32 T,f32 Mu ,f32 C , s32 id, + const core::vector3df& position , + const core::vector3df& rotation , + const core::vector3df& scale ) +: IWaterSceneNode(parent, mgr,m_TileCount,Size,D,T,Mu,C,id, position, rotation, scale), Mesh(0), PassCount(0) { #ifdef _DEBUG setDebugName("CWaterSurfaceSceneNode"); #endif - WaveSpeed = waveSpeed;//300.0f; - WaveLength = waveLength;//10.0f; - WaveHeight = waveHeight;//2.0f; - + + IAnimatedMesh* animatedMesh =SceneManager->addHillPlaneMesh("water", + core::dimension2d(Size,Size), + m_tileCount, 0, 0, + core::dimension2d(0,0), + core::dimension2d(10,10)); + + m_tileCount.Height+=1; + m_tileCount.Width+=1; + // create copy of the mesh - if (!mesh) + if (!animatedMesh) return; - IMesh* clone = SceneManager->getMeshManipulator()->createMeshCopy(mesh); - OriginalMesh = Mesh; - Mesh = clone; + //IMesh* clone = SceneManager->getMeshManipulator()->createMeshCopy(animatedMesh->getMesh(0)); + Mesh = SceneManager->getMeshManipulator()->createMeshCopy(animatedMesh->getMesh(0)); + + if (Mesh) + { + // get materials. + video::SMaterial mat; + + //it's an water plane so it has 1 meshbuffer + IMeshBuffer* mb = Mesh->getMeshBuffer(0); + if (mb) + mat = mb->getMaterial(); + + Material =mat; + + // grab the mesh + + Mesh->grab(); + } + + s32 vtxCnt = Mesh->getMeshBuffer(0)->getVertexCount(); + + f32 * t0 = new f32[vtxCnt]; + memset(t0, 0, sizeof(f32)*vtxCnt); + f32 * t1 = new f32[vtxCnt]; + memset(t1, 0, sizeof(f32)*vtxCnt); + f32 * t2 = new f32[vtxCnt]; + memset(t2, 0, sizeof(f32)*vtxCnt); + + + mPosition.push_back(t0); + mPosition.push_back(t1); + mPosition.push_back(t2); + + currentPos = 0; + + //update(); + + //animatedMesh->drop(); + } @@ -48,8 +94,11 @@ //! destructor CWaterSurfaceSceneNode::~CWaterSurfaceSceneNode() { - if (OriginalMesh) - OriginalMesh->drop(); + if (Mesh) + Mesh->drop(); + if (!mPosition.empty()) + mPosition.clear(); + } @@ -58,69 +107,156 @@ void CWaterSurfaceSceneNode::OnPreRender() { if (IsVisible) - SceneManager->registerNodeForRendering(this); + { + //SceneManager->registerNodeForRendering(this); - animateWaterSurface(); + // because this node supports rendering of mixed mode meshes consisting of + // transparent and solid material at the same time, we need to go through all + // materials, check of what type they are and register this node for the right + // render pass according to that. + + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + + PassCount = 0; + int transparentCount = 0; + int solidCount = 0; + + // count transparent and solid materials in this scene node + + video::IMaterialRenderer* rnd = + driver->getMaterialRenderer(Material.MaterialType); + + if (rnd && rnd->isTransparent()) + ++transparentCount; + else + ++solidCount; + + // register according to material types counted + + if (solidCount) + SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); + + if (transparentCount) + SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); + + } + + update(); - CMeshSceneNode::OnPreRender(); + ISceneNode::OnPreRender(); } +//! returns the axis aligned bounding box of this node +const core::aabbox3d& CWaterSurfaceSceneNode::getBoundingBox() const +{ + return Mesh ? Mesh->getBoundingBox() : Box; +} -void CWaterSurfaceSceneNode::animateWaterSurface() +//! returns the material based on the zero based index i. To get the amount +//! of materials used by this scene node, use getMaterialCount(). +//! This function is needed for inserting the node into the scene hierarchy on a +//! optimal position for minimizing renderstate changes, but can also be used +//! to directly modify the material of a scene node. +video::SMaterial& CWaterSurfaceSceneNode::getMaterial(s32 i) +{ + if (i < 0 || i > 1) + return ISceneNode::getMaterial(i); + + return Material; +} + +//! returns amount of materials used by this scene node. +s32 CWaterSurfaceSceneNode::getMaterialCount() +{ + return 1; +} + +void CWaterSurfaceSceneNode::update() { if (!Mesh) return; - s32 meshBufferCount = Mesh->getMeshBufferCount(); - f32 time = os::Timer::getTime() / WaveSpeed; + //f32 time = os::Timer::getTime()/WaveSpeed; - for (s32 b=0; bgetMeshBuffer(b)->getVertexCount(); + //has 1 meshbuffer + currentPos = (currentPos + 1) % 3 ; + + core::array2D pos0(mPosition[currentPos], m_tileCount.Height, m_tileCount.Width); + core::array2D pos1(mPosition[(currentPos+2)%3], m_tileCount.Height, m_tileCount.Width); + core::array2D pos2(mPosition[(currentPos+1)%3], m_tileCount.Height, m_tileCount.Width); + + video::S3DVertex* v = + (video::S3DVertex*)Mesh->getMeshBuffer(0)->getVertices(); + + //core::array2D position(v, m_tileCount.Height, m_tileCount.Width); + + for (int y = 1; y < m_tileCount.Height-1; ++y) + { + for (int x = 1; x < m_tileCount.Width-1; ++x) + { + pos0(x,y) = coefA*pos1(x,y) + coefB*pos2(x,y) + + coefC*(pos1(x+1,y) + pos1(x-1,y) + pos1(x,y+1) + pos1(x,y-1)); + + v[y*m_tileCount.Width + x].Pos.Y = pos0(x,y); + } + } + + SceneManager->getMeshManipulator()->recalculateNormals(Mesh); + SceneManager->getMeshManipulator()->recalculateBoundingBox(Mesh->getMeshBuffer(0)); + +} + +void CWaterSurfaceSceneNode::hitWater(u32 x,u32 y,f32 depth) +{ + currentPos = (currentPos + 1) % 3 ; + + core::array2D pos0(mPosition[currentPos], m_tileCount.Height, m_tileCount.Width); + //core::array2D pos1(mPosition[(currentPos+2)%3], m_tileCount.Height, m_tileCount.Width); + //core::array2D pos2(mPosition[(currentPos+1)%3], m_tileCount.Height, m_tileCount.Width); + pos0(x,y)-= depth*0.2f; + //pos1(x,y)-= depth*0.2f; + //pos2(x,y)-= depth*0.2f; +} + +//! renders the node. +void CWaterSurfaceSceneNode::render() +{ + video::IVideoDriver* driver = SceneManager->getVideoDriver(); - switch(Mesh->getMeshBuffer(b)->getVertexType()) + if (!Mesh || !driver) + return; + + bool isTransparentPass = + SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; + + ++PassCount; + + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + Box = Mesh->getBoundingBox(); + + // for debug purposes only: + if (DebugDataVisible && PassCount==1) + { + video::SMaterial m; + m.Lighting = false; + driver->setMaterial(m); + driver->draw3DBox(Box, video::SColor(0,255,255,255)); + } + + + video::IMaterialRenderer* rnd = driver->getMaterialRenderer(Material.MaterialType); + bool transparent = (rnd && rnd->isTransparent()); + + // only render transparent buffer if this is the transparent render pass + // and solid only in solid pass + if (transparent == isTransparentPass) { - case video::EVT_STANDARD: - { - video::S3DVertex* v = - (video::S3DVertex*)Mesh->getMeshBuffer(b)->getVertices(); - - video::S3DVertex* v2 = - (video::S3DVertex*)OriginalMesh->getMeshBuffer(b)->getVertices(); - - for (s32 i=0; igetMeshBuffer(b)->getVertices(); - - video::S3DVertex2TCoords* v2 = - (video::S3DVertex2TCoords*)OriginalMesh->getMeshBuffer(b)->getVertices(); - - for (s32 i=0; igetMeshBuffer(0); + driver->setMaterial(Material); + driver->drawMeshBuffer(mb); + } - }// end for all mesh buffers - SceneManager->getMeshManipulator()->recalculateNormals(Mesh); } --- Irrlicht.old/CWaterSurfaceSceneNode.h 2005-03-28 10:28:44.000000000 +0200 +++ water/CWaterSurfaceSceneNode.h 2005-04-11 23:12:58.000000000 +0200 @@ -5,23 +5,26 @@ #ifndef __C_WATER_SURFACE_SCENE_NODE_H_INCLUDED__ #define __C_WATER_SURFACE_SCENE_NODE_H_INCLUDED__ -#include "CMeshSceneNode.h" +#include "IWaterSceneNode.h" +#include "SMeshBuffer.h" +#include "SMesh.h" +#include "S3DVertex.h" namespace irr { namespace scene { - class CWaterSurfaceSceneNode : public CMeshSceneNode + class CWaterSurfaceSceneNode : public IWaterSceneNode { public: //! constructor - CWaterSurfaceSceneNode(f32 waveHeight, f32 waveSpeed, f32 waveLength, - IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, - 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)); + CWaterSurfaceSceneNode(ISceneNode* parent, ISceneManager* mgr,core::dimension2d& m_TileCount, + f32 Size ,f32 D ,f32 T ,f32 Mu ,f32 C , 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)); //! destructor virtual ~CWaterSurfaceSceneNode(); @@ -29,16 +32,42 @@ //! frame virtual void OnPreRender(); + //! renders the node. + virtual void render(); + + //! returns the axis aligned bounding box of this node + virtual const core::aabbox3d& getBoundingBox() const; + + //! returns the material based on the zero based index i. To get the amount + //! of materials used by this scene node, use getMaterialCount(). + //! This function is needed for inserting the node into the scene hirachy on a + //! optimal position for minimizing renderstate changes, but can also be used + //! to directly modify the material of a scene node. + virtual video::SMaterial& getMaterial(s32 i); + + //! returns amount of materials used by this scene node. + virtual s32 getMaterialCount(); + + // Release a drop of water into the simulation. + // - must be in [1, -2] + // - must be in [1, -2] + void hitWater(u32 x,u32 y,f32 depth); + //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() { return ESNT_WATER_SURFACE; } private: + + void update(); - void animateWaterSurface(); - f32 WaveLength; - f32 WaveSpeed; - f32 WaveHeight; - IMesh* OriginalMesh; + core::array mPosition; + int currentPos; + + video::SMaterial Material; + core::aabbox3d Box; + IMesh* Mesh; + + s32 PassCount; }; } // end namespace scene --- Irrlicht.old/include/irrlicht.h 2005-03-28 10:28:48.000000000 +0200 +++ water/include/irrlicht.h 2005-04-10 10:47:40.000000000 +0200 @@ -78,6 +78,7 @@ #include "irrString.h" #include "ISceneManager.h" #include "ISceneNode.h" +#include "IWaterSceneNode.h" #include "IStringParameters.h" #include "ITriangleSelector.h" #include "ISceneNodeAnimator.h" --- Irrlicht.old/include/ISceneManager.h 2005-03-28 10:28:48.000000000 +0200 +++ water/include/ISceneManager.h 2005-04-10 10:53:00.000000000 +0200 @@ -14,6 +14,7 @@ #include "IEventReceiver.h" #include "ITerrainSceneNode.h" #include "SceneParameters.h" +#include "IWaterSceneNode.h" namespace irr { @@ -330,12 +331,11 @@ \param scale: Initial scale of the scene node. \return Returns pointer to the created scene node. This pointer should not be dropped. See IUnknown::drop() for more information. */ - virtual ISceneNode* addWaterSurfaceSceneNode(IMesh* mesh, - f32 waveHeight=2.0f, f32 waveSpeed=300.0f, f32 waveLength=10.0f, - 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)) = 0; + virtual IWaterSceneNode* addWaterSurfaceSceneNode(core::dimension2d& m_TileCount, + f32 Size = 10.0f,f32 D = 0.45f,f32 T = 0.144f,f32 Mu = 0.051f,f32 C = 0.45f,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)) = 0; //! Adds a scene node for rendering using a octtree to the scene graph. --- Irrlicht.old/include/IWaterSceneNode.h 1970-01-01 01:00:00.000000000 +0100 +++ water/include/IWaterSceneNode.h 2005-04-11 23:12:23.000000000 +0200 @@ -0,0 +1,112 @@ +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in Irrlicht.h + +//created by Kat'Oun + +#ifndef __I_WATER_SCENE_NODE_H_INCLUDED__ +#define __I_WATER_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" + + +//must have a IWaterSceneNode to add a water_drop function +//that makes posible to drop particles or objects on the +//water and so waves will be generated!! + +namespace irr +{ +namespace scene +{ + + class ISceneManager; + + //! Scene node interface. + /** A scene node is a node in the hirachical scene graph. Every scene node may have children, + which are other scene nodes. Children move relative the their parents position. If the parent of a node is not + visible, its children won't be visible too. In this way, it is for example easily possible + to attach a light to a moving car, or to place a walking character on a moving platform + on a moving ship. */ + class IWaterSceneNode : public ISceneNode + { + public: + + //! Constructor + IWaterSceneNode(ISceneNode* parent, ISceneManager* mgr,core::dimension2d& m_TileCount, + f32 Size ,f32 D ,f32 T ,f32 Mu ,f32 C , 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)) + :ISceneNode(parent,mgr,id,position,rotation,scale), + m_tileCount(m_TileCount),m_Size(Size),d(D),t(T),mu(Mu),c(C) + { + + precomputeCoef();//once parameters set must have coef ready + } + + //! Destructor + virtual ~IWaterSceneNode() + { + + } + + virtual void setD(f32 D) + { + d=D; + precomputeCoef(); + } + + virtual void setT(f32 T) + { + t=T; + precomputeCoef(); + } + + virtual void setMu(f32 Mu) + { + mu=Mu; + precomputeCoef(); + } + + virtual void setC(f32 C) + { + c=C; + precomputeCoef(); + } + + // Release a drop of water into the simulation. + // - must be in [1, -1] + // - must be in [1, -1] + virtual void hitWater(u32 x,u32 y,f32 depth) = 0; + + protected: + + void precomputeCoef() + { + // pre-compute the coefficients in the fluid equation + coefA = (4 - (8*c*c*t*t) / (d*d)) / (mu*t + 2); + coefB = (mu*t - 2) / (mu*t + 2); + coefC = ((2*c*c*t*t) / (d*d)) / (mu*t + 2); + + } + + core::dimension2d m_tileCount;//size of the water grid + + f32 m_Size;//size of the tile grid + + // parameters to the fluid simulation equation + f32 d; + f32 t; + f32 mu; + f32 c; + + // pre-computed coefficients in the fluid equation + f32 coefA, coefB, coefC; + + }; + +} // end namespace scene +} // end namespace irr + +#endif +