diff --git a/include/ESceneNodeTypes.h b/include/ESceneNodeTypes.h index 8b81b3a0..0a36bc92 100644 --- a/include/ESceneNodeTypes.h +++ b/include/ESceneNodeTypes.h @@ -75,6 +75,9 @@ namespace scene //! Quake3 Model Scene Node ( has tag to link to ) ESNT_MD3_SCENE_NODE = MAKE_IRR_ID('m','d','3','_'), + //! Volume Light Scene Node + ESNT_VOLUME_LIGHT = MAKE_IRR_ID('v','o','l','l'), + //! Maya Camera Scene Node /** Legacy, for loading version <= 1.4.x .irr files */ ESNT_CAMERA_MAYA = MAKE_IRR_ID('c','a','m','M'), diff --git a/include/IVolumeLightSceneNode.h b/include/IVolumeLightSceneNode.h index 2a218368..cdf0d3d2 100644 --- a/include/IVolumeLightSceneNode.h +++ b/include/IVolumeLightSceneNode.h @@ -27,21 +27,20 @@ namespace scene : ISceneNode(parent, mgr, id, position, rotation, scale) {}; //! Returns type of the scene node - virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; } + virtual ESCENE_NODE_TYPE getType() const { return ESNT_VOLUME_LIGHT; } - virtual void setSubDivideU (const u32 inU) =0; - virtual void setSubDivideV (const u32 inV) =0; + virtual void setSubDivideU(const u32 inU) =0; + virtual void setSubDivideV(const u32 inV) =0; - virtual u32 getSubDivideU () const =0; - virtual u32 getSubDivideV () const =0; + virtual u32 getSubDivideU() const =0; + virtual u32 getSubDivideV() const =0; virtual void setFootColour(const video::SColor inColour) =0; virtual void setTailColour(const video::SColor inColour) =0; - virtual video::SColor getFootColour () const =0; - virtual video::SColor getTailColour () const =0; + virtual video::SColor getFootColour() const =0; + virtual video::SColor getTailColour() const =0; - virtual IMeshBuffer * getMeshBuffer(void) const =0; }; } // end namespace scene diff --git a/source/Irrlicht/CVolumeLightSceneNode.cpp b/source/Irrlicht/CVolumeLightSceneNode.cpp index b1526f66..7415a9cf 100644 --- a/source/Irrlicht/CVolumeLightSceneNode.cpp +++ b/source/Irrlicht/CVolumeLightSceneNode.cpp @@ -21,185 +21,52 @@ CVolumeLightSceneNode::CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : IVolumeLightSceneNode(parent, mgr, id, position, rotation, scale), - LPDistance(8.0f), SubdivideU(subdivU), SubdivideV(subdivV), - FootColour(foot), TailColour(tail), + Mesh(0), LPDistance(8.0f), + SubdivideU(subdivU), SubdivideV(subdivV), + FootColor(foot), TailColor(tail), LightDimensions(core::vector3df(1.0f, 1.2f, 1.0f)) { #ifdef _DEBUG setDebugName("CVolumeLightSceneNode"); #endif - Buffer = new SMeshBuffer(); - if (Buffer) - { - Buffer->setHardwareMappingHint(EHM_STATIC); - constructLight(); - } + constructLight(); } CVolumeLightSceneNode::~CVolumeLightSceneNode() { - if (Buffer) - Buffer->drop(); -} - - -void CVolumeLightSceneNode::addToBuffer(const video::S3DVertex& v) -{ - const s32 tnidx = Buffer->Vertices.linear_reverse_search(v); - const bool alreadyIn = (tnidx != -1); - u16 nidx = (u16)tnidx; - if (!alreadyIn) { - nidx = (u16)Buffer->Vertices.size(); - Buffer->Indices.push_back(nidx); - Buffer->Vertices.push_back(v); - } else - Buffer->Indices.push_back(nidx); + if (Mesh) + Mesh->drop(); } void CVolumeLightSceneNode::constructLight() { - const core::vector3df lightPoint(0, -(LPDistance*LightDimensions.Y), 0); - const f32 ax = LightDimensions.X * 0.5f; // X Axis - const f32 az = LightDimensions.Z * 0.5f; // Z Axis - - Buffer->Vertices.clear(); - Buffer->Vertices.reallocate(6+12*(SubdivideU+SubdivideV)); - Buffer->Indices.clear(); - Buffer->Indices.reallocate(6+12*(SubdivideU+SubdivideV)); - //draw the bottom foot.. the glowing region - addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, FootColour, 0, 1)); - addToBuffer(video::S3DVertex(ax , 0, az, 0,0,0, FootColour, 1, 1)); - addToBuffer(video::S3DVertex(ax , 0,-az, 0,0,0, FootColour, 1, 0)); - - addToBuffer(video::S3DVertex(ax , 0,-az, 0,0,0, FootColour, 1, 0)); - addToBuffer(video::S3DVertex(-ax, 0,-az, 0,0,0, FootColour, 0, 0)); - addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, FootColour, 0, 1)); - - f32 tu = 0.f; - const f32 tuStep = 1.f/SubdivideU; - f32 bx = -ax; - const f32 bxStep = LightDimensions.X * tuStep; - // Slices in X/U space - for (u32 i = 0; i <= SubdivideU; ++i) - { - // These are the two endpoints for a slice at the foot - core::vector3df end1(bx, 0.0f, -az); - core::vector3df end2(bx, 0.0f, az); - - end1 -= lightPoint; // get a vector from point to lightsource - end1.normalize(); // normalize vector - end1 *= LightDimensions.Y; // multiply it out by shootlength - - end1.X += bx; // Add the original point location to the vector - end1.Z -= az; - - // Do it again for the other point. - end2 -= lightPoint; - end2.normalize(); - end2 *= LightDimensions.Y; - - end2.X += bx; - end2.Z += az; - - addToBuffer(video::S3DVertex(bx , 0, az, 0,0,0, FootColour, tu, 1)); - addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, FootColour, tu, 0)); - addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, TailColour, tu, 1)); - - addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, FootColour, tu, 0)); - addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, TailColour, tu, 0)); - addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, TailColour, tu, 1)); - - //back side - addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, TailColour, tu, 1)); - addToBuffer(video::S3DVertex(-bx , 0, -az, 0,0,0, FootColour, tu, 1)); - addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, FootColour, tu, 0)); - - addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, FootColour, tu, 0)); - addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, TailColour, tu, 0)); - addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, TailColour, tu, 1)); - tu += tuStep; - bx += bxStep; - } - - f32 tv = 0.f; - const f32 tvStep = 1.f/SubdivideV; - f32 bz = -az; - const f32 bzStep = LightDimensions.Z * tvStep; - // Slices in Z/V space - for(u32 i = 0; i <= SubdivideV; ++i) - { - // These are the two endpoints for a slice at the foot - core::vector3df end1(-ax, 0.0f, bz); - core::vector3df end2(ax, 0.0f, bz); - - end1 -= lightPoint; // get a vector from point to lightsource - end1.normalize(); // normalize vector - end1 *= LightDimensions.Y; // multiply it out by shootlength - - end1.X -= ax; // Add the original point location to the vector - end1.Z += bz; - - // Do it again for the other point. - end2 -= lightPoint; - end2.normalize(); - end2 *= LightDimensions.Y; - - end2.X += ax; - end2.Z += bz; - - addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, FootColour, 0, tv)); - addToBuffer(video::S3DVertex(ax , 0, bz, 0,0,0, FootColour, 1, tv)); - addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, TailColour, 1, tv)); - - addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, TailColour, 1, tv)); - addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, TailColour, 0, tv)); - addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, FootColour, 0, tv)); - - //back side - addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, FootColour, 0, tv)); - addToBuffer(video::S3DVertex(-ax , 0, -bz, 0,0,0, FootColour, 1, tv)); - addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, TailColour, 1, tv)); - - addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, TailColour, 1, tv)); - addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, TailColour, 0, tv)); - addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, FootColour, 0, tv)); - tv += tvStep; - bz += bzStep; - } - - Buffer->recalculateBoundingBox(); - - Buffer->Material.MaterialType = video::EMT_ONETEXTURE_BLEND; - Buffer->Material.MaterialTypeParam = pack_texureBlendFunc( video::EBF_SRC_COLOR, video::EBF_SRC_ALPHA, video::EMFN_MODULATE_1X ); - - Buffer->Material.Lighting = false; - Buffer->Material.ZWriteEnable = false; - - Buffer->setDirty(EBT_VERTEX_AND_INDEX); + if (Mesh) + Mesh->drop(); + Mesh = SceneManager->getGeometryCreator()->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor); } //! renders the node. void CVolumeLightSceneNode::render() { - if (!Buffer) + if (!Mesh) return; video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - driver->setMaterial(Buffer->Material); - driver->drawMeshBuffer(Buffer); + driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); + driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); } //! returns the axis aligned bounding box of this node const core::aabbox3d& CVolumeLightSceneNode::getBoundingBox() const { - return Buffer->BoundingBox; + return Mesh->getBoundingBox(); } @@ -220,7 +87,7 @@ void CVolumeLightSceneNode::OnRegisterSceneNode() //! to directly modify the material of a scene node. video::SMaterial& CVolumeLightSceneNode::getMaterial(u32 i) { - return Buffer->Material; + return Mesh->getMeshBuffer(i)->getMaterial(); } @@ -233,29 +100,41 @@ u32 CVolumeLightSceneNode::getMaterialCount() const void CVolumeLightSceneNode::setSubDivideU (const u32 inU) { - SubdivideU = inU; - constructLight(); + if (inU != SubdivideU) + { + SubdivideU = inU; + constructLight(); + } } void CVolumeLightSceneNode::setSubDivideV (const u32 inV) { - SubdivideV = inV; - constructLight(); + if (inV != SubdivideV) + { + SubdivideV = inV; + constructLight(); + } } -void CVolumeLightSceneNode::setFootColour(const video::SColor inColouf) +void CVolumeLightSceneNode::setFootColour(const video::SColor inColor) { - FootColour = inColouf; - constructLight(); + if (inColor != FootColor) + { + FootColor = inColor; + constructLight(); + } } -void CVolumeLightSceneNode::setTailColour(const video::SColor inColouf) +void CVolumeLightSceneNode::setTailColour(const video::SColor inColor) { - TailColour = inColouf; - constructLight(); + if (inColor != TailColor) + { + TailColor = inColor; + constructLight(); + } } @@ -268,8 +147,8 @@ void CVolumeLightSceneNode::serializeAttributes(io::IAttributes* out, io::SAttri out->addInt("subDivideU", SubdivideU); out->addInt("subDivideV", SubdivideV); - out->addColor("footColour", FootColour); - out->addColor("tailColour", TailColour); + out->addColor("footColour", FootColor); + out->addColor("tailColour", TailColor); out->addVector3d("lightDimension", LightDimensions); } @@ -287,8 +166,8 @@ void CVolumeLightSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttr SubdivideV = in->getAttributeAsInt("subDivideV"); SubdivideV = core::max_(SubdivideV, 1u); - FootColour = in->getAttributeAsColor("footColour"); - TailColour = in->getAttributeAsColor("tailColour"); + FootColor = in->getAttributeAsColor("footColour"); + TailColor = in->getAttributeAsColor("tailColour"); LightDimensions = in->getAttributeAsVector3d("lightDimension"); @@ -307,10 +186,10 @@ ISceneNode* CVolumeLightSceneNode::clone(ISceneNode* newParent, ISceneManager* n newManager = SceneManager; CVolumeLightSceneNode* nb = new CVolumeLightSceneNode(newParent, - newManager, ID, SubdivideU, SubdivideV, FootColour, TailColour, RelativeTranslation); + newManager, ID, SubdivideU, SubdivideV, FootColor, TailColor, RelativeTranslation); nb->cloneMembers(this, newManager); - nb->Buffer->Material = Buffer->Material; + nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial(); nb->drop(); return nb; diff --git a/source/Irrlicht/CVolumeLightSceneNode.h b/source/Irrlicht/CVolumeLightSceneNode.h index 3ae4b7bb..7bc39fa0 100644 --- a/source/Irrlicht/CVolumeLightSceneNode.h +++ b/source/Irrlicht/CVolumeLightSceneNode.h @@ -8,7 +8,7 @@ #define __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ #include "IVolumeLightSceneNode.h" -#include "SMeshBuffer.h" +#include "IMesh.h" namespace irr { @@ -37,11 +37,7 @@ namespace scene //! 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. + //! returns the material based on the zero based index i. virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. @@ -59,25 +55,22 @@ namespace scene //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); - virtual void setSubDivideU (const u32 inU); - virtual void setSubDivideV (const u32 inV); + virtual void setSubDivideU(const u32 inU); + virtual void setSubDivideV(const u32 inV); - virtual u32 getSubDivideU () const { return SubdivideU; } - virtual u32 getSubDivideV () const { return SubdivideV; } + virtual u32 getSubDivideU() const { return SubdivideU; } + virtual u32 getSubDivideV() const { return SubdivideV; } - virtual void setFootColour(const video::SColor inColouf); - virtual void setTailColour(const video::SColor inColouf); + virtual void setFootColour(const video::SColor inColor); + virtual void setTailColour(const video::SColor inColor); - virtual video::SColor getFootColour () const { return FootColour; } - virtual video::SColor getTailColour () const { return TailColour; } - - virtual IMeshBuffer * getMeshBuffer(void) const { return Buffer; } + virtual video::SColor getFootColour() const { return FootColor; } + virtual video::SColor getTailColour() const { return TailColor; } private: - void addToBuffer(const video::S3DVertex& v); void constructLight(); - SMeshBuffer* Buffer; + IMesh* Mesh; f32 LPDistance; // Distance to hypothetical lightsource point -- affects fov angle @@ -86,8 +79,8 @@ namespace scene // NOTE : Total number of polygons = 2 + ((SubdivideU + 1) + (SubdivideV + 1)) * 2 // Each slice being a quad plus the rectangular plane at the bottom. - video::SColor FootColour; // Color at the source - video::SColor TailColour; // Color at the end. + video::SColor FootColor; // Color at the source + video::SColor TailColor; // Color at the end. core::vector3df LightDimensions; // LightDimensions.Y Distance of shooting -- Length of beams // LightDimensions.X and LightDimensions.Z determine the size/dimension of the plane