|
From: <cn...@us...> - 2009-06-23 04:53:52
|
Revision: 359
http://hgengine.svn.sourceforge.net/hgengine/?rev=359&view=rev
Author: cnlohr
Date: 2009-06-23 04:53:46 +0000 (Tue, 23 Jun 2009)
Log Message:
-----------
woot text node
Modified Paths:
--------------
Mercury2/modules/Makefile
Added Paths:
-----------
Mercury2/modules/TextNode.cpp
Modified: Mercury2/modules/Makefile
===================================================================
--- Mercury2/modules/Makefile 2009-06-23 00:23:23 UTC (rev 358)
+++ Mercury2/modules/Makefile 2009-06-23 04:53:46 UTC (rev 359)
@@ -2,7 +2,7 @@
CXXFLAGS=${CFLAGS}
LDFLAGS=-shared
-all : BillboardNode.so
+all : BillboardNode.so TextNode.so
clean :
rm -rf *~ *.o *.so
@@ -10,3 +10,5 @@
BillboardNode.so : BillboardNode.o
g++ -o$@ $^ ${LDFLAGS}
+TextNode.so : TextNode.o
+ g++ -o$@ $^ ${LDFLAGS}
Added: Mercury2/modules/TextNode.cpp
===================================================================
--- Mercury2/modules/TextNode.cpp (rev 0)
+++ Mercury2/modules/TextNode.cpp 2009-06-23 04:53:46 UTC (rev 359)
@@ -0,0 +1,285 @@
+#include "TextNode.h"
+#include <MercuryVertex.h>
+#include <Viewport.h>
+#include <MercuryFile.h>
+#include <MercuryVBO.h>
+#include <Texture.h>
+#include <vector>
+
+REGISTER_NODE_TYPE(TextNode);
+
+TextNode::TextNode()
+ :MercuryNode(),m_fSize(1.),m_bDirty(0), m_kVBO(0), m_kTEX(0)
+{
+}
+
+void TextNode::Update(float dTime)
+{
+ if( m_bDirty )
+ {
+ RenderText();
+ }
+
+ MercuryNode::Update( dTime );
+}
+
+void TextNode::LoadFromXML(const XMLNode& node)
+{
+ MercuryNode::LoadFromXML(node);
+
+ if ( !node.Attribute("font").empty() )
+ LoadFont( node.Attribute("font") );
+ if ( !node.Attribute("size").empty() )
+ SetSize( StrToFloat( node.Attribute("size") ) );
+ if ( !node.Attribute("text").empty() )
+ SetText( node.Attribute("text") );
+}
+
+void TextNode::RenderText()
+{
+ std::vector< DChar > chars;
+ float xps = 0;
+ float yps = 0;
+
+ if( !m_pThisFont )
+ return;
+
+// AddAsset( AssetFactory::GetInstance().Generate( "Quad", "MyQuad" ) );
+
+ if( !m_kTEX )
+ {
+ m_kTEX = MAutoPtr< MercuryAsset >( Texture::LoadFromFile( m_pThisFont->m_sImage ) );
+ if( !m_kTEX )
+ {
+ fprintf( stderr, "Could not create Texture for text.\n" );
+ return;
+ }
+ m_kTEX->Init( this );
+ }
+
+ //Setup FBO and Texture
+ if( !m_kVBO )
+ {
+ m_kVBO = new MercuryVBO;
+ if( !m_kVBO )
+ {
+ fprintf( stderr, "Could not create VBO for text.\n" );
+ return;
+ }
+ AddAsset( m_kVBO );
+ }
+
+ //Pass 1: Figure out actual char positions and count
+ for( const char * c = &m_sText[0]; *c != 0; c++ )
+ {
+ if( *c == 9 )
+ xps+=80;
+ else if( *c == 10 )
+ {
+ xps = 0;
+ yps += m_pThisFont->m_fHeight; //??XXXX NEED TO SET TO RIGHT VALUE!
+ }
+ else if( *c == 32 )
+ xps+=20;
+ else
+ {
+ if( m_pThisFont->m_mGlyphs.find( *c ) != m_pThisFont->m_mGlyphs.end() )
+ {
+ Glyph & g = m_pThisFont->m_mGlyphs[*c];
+
+ chars.push_back( DChar( &g, *c, xps, yps ) );
+ //Here is the right place to do line-splitting if need be.
+
+ xps += g.ilx+4; //Why 4?
+ }
+ }
+ }
+
+ //Stage 2: Actually generate the geometry.
+ ((MercuryVBO*)m_kVBO.Ptr())->AllocateIndexSpace(chars.size()*6);
+ ((MercuryVBO*)m_kVBO.Ptr())->AllocateVertexSpace(chars.size()*4);
+
+ for( unsigned i = 0; i < chars.size(); i++ )
+ {
+ DChar & dc = chars[i];
+ Glyph * g = dc.glyph;
+ float * vd = ((MercuryVBO*)m_kVBO.Ptr())->GetVertexHandle();
+ short unsigned int * id = ((MercuryVBO*)m_kVBO.Ptr())->GetIndexHandle();
+
+ float sx = (-g->iox + dc.xps)*m_fSize;
+ float sy = -(-g->ioy + dc.yps)*m_fSize;
+ float ex = (g->ilx-g->iox + dc.xps)*m_fSize;
+ float ey = -(g->ily-g->ioy + dc.yps)*m_fSize;
+
+ //Vertex1: Upper Left
+ vd[(i*4+0)*8+0] = g->fsx;
+ vd[(i*4+0)*8+1] = g->fsy; //U,V
+ vd[(i*4+0)*8+2] = 0;
+ vd[(i*4+0)*8+3] = 0;
+ vd[(i*4+0)*8+4] = -1; //Normal <0,0,-1>
+ vd[(i*4+0)*8+5] = sx;
+ vd[(i*4+0)*8+6] = sy;
+ vd[(i*4+0)*8+7] = 0;
+
+ //Vertex 2: Upper Right
+ vd[(i*4+1)*8+0] = g->fex;
+ vd[(i*4+1)*8+1] = g->fsy;
+ vd[(i*4+1)*8+2] = 0;
+ vd[(i*4+1)*8+3] = 0;
+ vd[(i*4+1)*8+4] = -1; //Normal <0,0,-1>
+ vd[(i*4+1)*8+5] = ex;
+ vd[(i*4+1)*8+6] = sy;
+ vd[(i*4+1)*8+7] = 0;
+
+ //Vertex 3: Lower Right
+ vd[(i*4+2)*8+0] = g->fex;
+ vd[(i*4+2)*8+1] = g->fey;
+ vd[(i*4+2)*8+2] = 0;
+ vd[(i*4+2)*8+3] = 0;
+ vd[(i*4+2)*8+4] = -1; //Normal <0,0,-1>
+ vd[(i*4+2)*8+5] = ex;
+ vd[(i*4+2)*8+6] = ey;
+ vd[(i*4+2)*8+7] = 0;
+
+ //Vertex 4: Lower Left
+ vd[(i*4+3)*8+0] = g->fsx;
+ vd[(i*4+3)*8+1] = g->fey;
+ vd[(i*4+3)*8+2] = 0;
+ vd[(i*4+3)*8+3] = 0;
+ vd[(i*4+3)*8+4] = -1; //Normal <0,0,-1>
+ vd[(i*4+3)*8+5] = sx;
+ vd[(i*4+3)*8+6] = ey;
+ vd[(i*4+3)*8+7] = 0;
+
+ printf( "%f %f %f %f %f %f %f %f\n", vd[(i*4+0)*8+5], vd[(i*4+0)*8+6], vd[(i*4+1)*8+5], vd[(i*4+1)*8+6], vd[(i*4+2)*8+5], vd[(i*4+2)*8+6], vd[(i*4+3)*8+5], vd[(i*4+3)*8+6] );
+ id[i*6+0] = i * 4 + 2;
+ id[i*6+1] = i * 4 + 1;
+ id[i*6+2] = i * 4 + 0;
+ id[i*6+3] = i * 4 + 0;
+ id[i*6+4] = i * 4 + 3;
+ id[i*6+5] = i * 4 + 2;
+ }
+
+ m_bDirty = false;
+ m_kVBO->Init( this );
+}
+
+bool TextNode::LoadFont( const MString & sFont )
+{
+ if( g_AllFonts.get( sFont ) == 0 )
+ {
+ m_pThisFont = &g_AllFonts[sFont];
+ if( !m_pThisFont->LoadFromFile( sFont ) )
+ {
+ fprintf( stderr, "Error: Could not load font: \"%s\".", sFont.c_str() );
+ g_AllFonts.remove( sFont );
+ return false;
+ }
+ } else
+ m_pThisFont = &g_AllFonts[sFont];
+ SetDirtyText();
+
+ return true;
+}
+
+void TextNode::SetSize( float fSize )
+{
+ m_fSize = fSize;
+ SetDirtyText();
+}
+
+void TextNode::SetText( const MString & sText )
+{
+ m_sText = sText;
+ SetDirtyText();
+}
+
+
+bool TextNode::Font::LoadFromFile( const MString & fName )
+{
+ int line = 0;
+ MString sLine;
+
+ MercuryFile * f = FILEMAN.Open( fName );
+ if( !f )
+ return false;
+
+ if( !f->ReadLine( m_sImage ) )
+ {
+ delete f;
+ return false;
+ }
+
+ if( !f->ReadLine( sLine ) )
+ {
+ delete f;
+ return false;
+ }
+
+ if( sscanf( sLine.c_str(), "%f", &m_fHeight ) != 1 )
+ {
+ fprintf( stderr, "Malformatted font size.\n" );
+ delete f;
+ return false;
+ }
+
+ while( !f->Eof() )
+ {
+ int res;
+ line++;
+
+ Glyph g;
+ int ch;
+
+ f->ReadLine( sLine );
+ if( ( res = sscanf( sLine.c_str(), "%d %f %f %f %f %f %f %f %f", &ch,
+ &g.fsx, &g.fsy, &g.fex, &g.fey, &g.ilx, &g.ily, &g.iox, &g.ioy ) ) != 9 )
+ {
+ if( res == 0 || res == -1 ) continue;
+ fprintf( stderr, "Error on line %d of font \"%s\" (invalid number of args) (%d args).\n", line, fName.c_str(), res );
+ delete f;
+ return false;
+ }
+
+ //Insert the glyph into the map.
+ m_mGlyphs[ch] = g;
+ }
+
+ delete f;
+ return true;
+}
+
+MHash< TextNode::Font > TextNode::g_AllFonts;
+
+
+/****************************************************************************
+ * Copyright (C) 2009 by Charles Lohr *
+ * *
+ * *
+ * All rights reserved. *
+ * *
+ * Redistribution and use in source and binary forms, with or without *
+ * modification, are permitted provided that the following conditions *
+ * are met: *
+ * * Redistributions of source code must retain the above copyright *
+ * notice, this list of conditions and the following disclaimer. *
+ * * Redistributions in binary form must reproduce the above *
+ * copyright notice, this list of conditions and the following *
+ * disclaimer in the documentation and/or other materials provided *
+ * with the distribution. *
+ * * Neither the name of the Mercury Engine nor the names of its *
+ * contributors may be used to endorse or promote products derived *
+ * from this software without specific prior written permission. *
+ * *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+ ***************************************************************************/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cn...@us...> - 2009-08-23 05:24:42
|
Revision: 516
http://hgengine.svn.sourceforge.net/hgengine/?rev=516&view=rev
Author: cnlohr
Date: 2009-08-23 05:24:34 +0000 (Sun, 23 Aug 2009)
Log Message:
-----------
fix up text
Modified Paths:
--------------
Mercury2/modules/TextNode.cpp
Mercury2/modules/TextNode.h
Modified: Mercury2/modules/TextNode.cpp
===================================================================
--- Mercury2/modules/TextNode.cpp 2009-08-23 02:11:55 UTC (rev 515)
+++ Mercury2/modules/TextNode.cpp 2009-08-23 05:24:34 UTC (rev 516)
@@ -6,6 +6,8 @@
#include <Texture.h>
#include <vector>
+#define BIG_NUMBER 1e20
+
REGISTER_NODE_TYPE(TextNode);
TextNode::TextNode()
@@ -13,7 +15,9 @@
m_bDirty(false),m_pThisFont(NULL),
m_alignment( LEFT ),
m_fTextWidth( INFINITY ),
- m_kVBO(0), m_kTEX(0)
+ m_kVBO(0), m_kTEX(0),
+ m_fRMinX(0),m_fRMinY(0),
+ m_fRMaxX(0),m_fRMaxY(0)
{
}
@@ -186,6 +190,8 @@
if( m_alignment == RIGHT )
{
float offset = m_fTextWidth - fEndOfLine;
+ if( m_fTextWidth > BIG_NUMBER )
+ offset = -fEndOfLine;
for( unsigned j = iLineStart; j < i; j++ )
{
chars[j].xps += offset;
@@ -194,14 +200,16 @@
{
float offset = m_fTextWidth - fEndOfLine;
offset/=2;
+ if( m_fTextWidth > BIG_NUMBER )
+ offset = -fEndOfLine/2.;
for( unsigned j = iLineStart; j < i; j++ )
- {
chars[j].xps += offset;
- }
} else if( m_alignment == FIT_FULL )
{
float offset = m_fTextWidth - fEndOfLine;
offset/=float(iLettersOnLine);
+ if( m_fTextWidth > BIG_NUMBER )
+ offset = 0;
float letter = 0;
@@ -214,6 +222,9 @@
{
float offset = m_fTextWidth - fEndOfLine;
+ if( m_fTextWidth > BIG_NUMBER )
+ offset = 0;
+
if( iWordsOnLine != 0 )
{
offset/=float(iWordsOnLine-1);
@@ -241,6 +252,11 @@
}
}
+ m_fRMinX = 0;
+ m_fRMinY = 0;
+ m_fRMaxX = 0;
+ m_fRMaxY = 0;
+
//Stage 3: Actually generate the geometry.
((MercuryVBO*)m_kVBO.Ptr())->AllocateIndexSpace((unsigned)chars.size()*6);
((MercuryVBO*)m_kVBO.Ptr())->AllocateVertexSpace((unsigned)chars.size()*4);
@@ -303,8 +319,16 @@
id[i*6+3] = i * 4 + 0;
id[i*6+4] = i * 4 + 3;
id[i*6+5] = i * 4 + 2;
+
+ if( sy > m_fRMaxY ) m_fRMaxY = sy;
+ if( ex > m_fRMaxX ) m_fRMaxX = ex;
+ if( ey < m_fRMinY ) m_fRMinY = ey;
+ if( sx < m_fRMinX ) m_fRMinX = sx;
}
+ ((MercuryVBO*)m_kVBO.Ptr())->DirtyVertices();
+ ((MercuryVBO*)m_kVBO.Ptr())->DirtyIndices();
+
m_bDirty = false;
}
Modified: Mercury2/modules/TextNode.h
===================================================================
--- Mercury2/modules/TextNode.h 2009-08-23 02:11:55 UTC (rev 515)
+++ Mercury2/modules/TextNode.h 2009-08-23 05:24:34 UTC (rev 516)
@@ -39,12 +39,18 @@
inline const MString & GetText() { return m_sText; }
inline void SetDirtyText() { m_bDirty = true; }
-
+
+ inline float GetRMinX() { return m_fRMinX; }
+ inline float GetRMinY() { return m_fRMinY; }
+ inline float GetRMaxX() { return m_fRMaxX; }
+ inline float GetRMaxY() { return m_fRMaxY; }
+
GENRTTI(TextNode);
private:
class Font;
+
float m_fSize;
MString m_sText;
MString m_sFont;
@@ -52,11 +58,16 @@
Font * m_pThisFont;
TextAlignment m_alignment;
float m_fTextWidth;
-
+
MAutoPtr< MercuryAsset > m_kVBO;
MAutoPtr< MercuryAsset > m_kTEX;
+ float m_fRMinX;
+ float m_fRMinY;
+ float m_fRMaxX;
+ float m_fRMaxY;
+
//Font-class specific stuff
class Glyph
{
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <axl...@us...> - 2009-10-10 22:22:59
|
Revision: 556
http://hgengine.svn.sourceforge.net/hgengine/?rev=556&view=rev
Author: axlecrusher
Date: 2009-10-10 22:22:50 +0000 (Sat, 10 Oct 2009)
Log Message:
-----------
add terrain
Modified Paths:
--------------
Mercury2/modules/Makefile
Added Paths:
-----------
Mercury2/modules/Terrain.cpp
Mercury2/modules/Terrain.h
Modified: Mercury2/modules/Makefile
===================================================================
--- Mercury2/modules/Makefile 2009-10-10 22:21:49 UTC (rev 555)
+++ Mercury2/modules/Makefile 2009-10-10 22:22:50 UTC (rev 556)
@@ -1,8 +1,8 @@
-CFLAGS=-O2 -g0 -Wall -I/usr/include/libxml2 -I.. -msse2 -DHAVE_CONFIG -DHGENGINE -fno-exceptions -fPIC -I../src -g
+CFLAGS=-O2 -g0 -Wall -I/usr/include/libxml2 -I.. -msse2 -DHAVE_CONFIG -DHGENGINE -fexceptions -fPIC -I../src -I../src/DataTypes -I../src/DataStructures -g
CXXFLAGS=${CFLAGS}
LDFLAGS=-shared
-all : BillboardNode.so TextNode.so
+all : BillboardNode.so TextNode.so Terrain.so
clean :
rm -rf *~ *.o *.so
@@ -12,3 +12,6 @@
TextNode.so : TextNode.o
g++ -o$@ $^ ${LDFLAGS}
+
+Terrain.so : Terrain.o
+ g++ -o$@ $^ ${LDFLAGS}
Added: Mercury2/modules/Terrain.cpp
===================================================================
--- Mercury2/modules/Terrain.cpp (rev 0)
+++ Mercury2/modules/Terrain.cpp 2009-10-10 22:22:50 UTC (rev 556)
@@ -0,0 +1,70 @@
+#include "Terrain.h"
+
+REGISTER_ASSET_TYPE(Terrain);
+
+Terrain::Terrain()
+ :base()
+{
+}
+
+Terrain::~Terrain()
+{
+}
+
+Terrain* Terrain::Generate()
+{
+ LOG.Write( "new Terrain" );
+ return new Terrain();
+}
+
+void Terrain::LoadedCallback()
+{
+ BuildHash();
+ base::LoadedCallback();
+}
+
+void Terrain::BuildHash()
+{
+ for( unsigned int i = 0; i < m_meshes.size(); ++i)
+ {
+ MAutoPtr< HGMDLMesh > mesh = m_meshes[i];
+ const HGMDLMesh& m = *mesh;
+ ImportMeshToHash( m );
+ }
+}
+
+void Terrain::ImportMeshToHash(const HGMDLMesh& mesh)
+{
+ const float* vertice = mesh.GetVertexHandle() + MercuryVBO::VERTEX_OFFSET;
+ const short unsigned int* indice = mesh.GetIndexHandle();
+
+ uint16_t length = mesh.IndiceCount();
+
+ float xMax, yMax, zMax;
+ xMax = yMax = zMax = 0;
+
+ for(uint16_t i = 0; i < length; ++i)
+ {
+ MercuryVertex v(vertice+(indice[i]*HGMDLMesh::STRIDE));
+ xMax = MAX<float>(v.GetX(),xMax);
+ yMax = MAX<float>(v.GetY(),yMax);
+ zMax = MAX<float>(v.GetZ(),zMax);
+ }
+
+ printf("%f %f %f\n", xMax, yMax, zMax);
+ m_hash.Allocate(xMax, yMax, zMax, 1);
+
+ for(uint16_t i = 0; i < length; i+=3)
+ {
+ MercuryVertex v1(vertice+(indice[i]*HGMDLMesh::STRIDE));
+ MercuryVertex v2(vertice+(indice[i+1]*HGMDLMesh::STRIDE));
+ MercuryVertex v3(vertice+(indice[i+2]*HGMDLMesh::STRIDE));
+ MTriangle t( v1, v2, v3 );
+
+ m_hash.Insert( v1.GetX(), v1.GetY(), v1.GetZ(), t );
+ m_hash.Insert( v2.GetX(), v2.GetY(), v2.GetZ(), t );
+ m_hash.Insert( v3.GetX(), v3.GetY(), v3.GetZ(), t );
+ }
+}
+
+
Added: Mercury2/modules/Terrain.h
===================================================================
--- Mercury2/modules/Terrain.h (rev 0)
+++ Mercury2/modules/Terrain.h 2009-10-10 22:22:50 UTC (rev 556)
@@ -0,0 +1,64 @@
+#ifndef TERRAIN_H
+#define TERRAIN_H
+
+#include <MercuryAsset.h>
+#include <HGMDLModel.h>
+#include <MercuryFile.h>
+
+#include <SpatialHash.h>
+#include <MTriangle.h>
+
+class Terrain : public HGMDLModel
+{
+ public:
+ Terrain();
+ ~Terrain();
+
+ static Terrain* Generate();
+ virtual void LoadedCallback(); //thread safe
+
+ private:
+ CLASS_HELPERS( HGMDLModel );
+ void BuildHash();
+ void ImportMeshToHash(const HGMDLMesh& mesh);
+
+ SpatialHash<MTriangle> m_hash;
+// void LoadHGMDL( const MString& path );
+// static void* LoaderThread(void* d);
+
+// std::vector< MAutoPtr< HGMDLMesh > > m_meshes;
+};
+
+#endif
+
+/****************************************************************************
+ * Copyright (C) 2009 by Joshua Allen *
+ * *
+ * *
+ * All rights reserved. *
+ * *
+ * Redistribution and use in source and binary forms, with or without *
+ * modification, are permitted provided that the following conditions *
+ * are met: *
+ * * Redistributions of source code must retain the above copyright *
+ * notice, this list of conditions and the following disclaimer. *
+ * * Redistributions in binary form must reproduce the above *
+ * copyright notice, this list of conditions and the following *
+ * disclaimer in the documentation and/or other materials provided *
+ * with the distribution. *
+ * * Neither the name of the Mercury Engine nor the names of its *
+ * contributors may be used to endorse or promote products derived *
+ * from this software without specific prior written permission. *
+ * *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+ ***************************************************************************/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <axl...@us...> - 2009-10-12 23:55:52
|
Revision: 567
http://hgengine.svn.sourceforge.net/hgengine/?rev=567&view=rev
Author: axlecrusher
Date: 2009-10-12 23:55:41 +0000 (Mon, 12 Oct 2009)
Log Message:
-----------
updates to allow for walking on terrain
Modified Paths:
--------------
Mercury2/modules/Terrain.cpp
Mercury2/modules/Terrain.h
Modified: Mercury2/modules/Terrain.cpp
===================================================================
--- Mercury2/modules/Terrain.cpp 2009-10-12 23:54:57 UTC (rev 566)
+++ Mercury2/modules/Terrain.cpp 2009-10-12 23:55:41 UTC (rev 567)
@@ -1,4 +1,6 @@
#include "Terrain.h"
+#include <MercuryMessageManager.h>
+#include <MercuryNode.h>
REGISTER_ASSET_TYPE(Terrain);
@@ -17,6 +19,11 @@
return new Terrain();
}
+MercuryAssetInstance* Terrain::GenerateInstanceData(MercuryNode* parentNode)
+{
+ return new TerrainAssetInstance(this, parentNode);
+}
+
void Terrain::LoadedCallback()
{
BuildHash();
@@ -67,4 +74,119 @@
}
}
+MercuryVertex Terrain::ComputePositionLinear(const MercuryVertex& p)
+{
+ HGMDLMesh& mesh = *m_meshes[0];
+ const float* vertice = mesh.GetVertexHandle() + MercuryVBO::VERTEX_OFFSET;
+ const short unsigned int* indice = mesh.GetIndexHandle();
+
+ MercuryVertex l( p );
+ l[2] = 0;
+
+ MercuryVector result = l;
+
+ uint16_t length = mesh.IndiceCount();
+ uint16_t foundCount = 0;
+ for(uint16_t i = 0; i < length; i+=3)
+ {
+ MercuryVertex v1(vertice+(indice[i]*HGMDLMesh::STRIDE));
+ MercuryVertex v2(vertice+(indice[i+1]*HGMDLMesh::STRIDE));
+ MercuryVertex v3(vertice+(indice[i+2]*HGMDLMesh::STRIDE));
+
+ MTriangle t( v1, v2, v3 );
+ MTriangle tflat(t);
+
+ tflat.m_verts[0][2] = 0;
+ tflat.m_verts[1][2] = 0;
+ tflat.m_verts[2][2] = 0;
+ if ( tflat.IsInTriangle(l) )
+ {
+ ++foundCount;
+ MercuryVector b = tflat.Barycentric(l);
+
+ MercuryVector pos( t.InterpolatePosition(b) );
+ result = pos;
+// return result;
+ }
+ }
+
+ if (foundCount > 1) LOG.Write( ssprintf("!!!!!! Found %d triangles !!!!!!", foundCount) );
+ return result;
+}
+/*
+MercuryVertex Terrain::ComputePosition(const MercuryVertex& p)
+{
+ MercuryVertex l( p );
+ l[2] = 0;
+
+ std::list<MTriangle> triangles = m_hash.FindByXY(p[0], p[1]);
+ LOG.Write( ssprintf("%d", triangles.size()) );
+
+ MercuryVector result = l;
+
+ if (!triangles.empty())
+ {
+ std::list<MTriangle>::iterator i = triangles.begin();
+ for(;i != triangles.end(); ++i)
+ {
+ MTriangle t = *i;
+ t.m_verts[0][2] = 0;
+ t.m_verts[1][2] = 0;
+ t.m_verts[2][2] = 0;
+ if ( t.IsInTriangle(l) )
+ {
+ MercuryVector b = t.Barycentric(l);
+ t = *i;
+
+ MercuryVector pos;//(t.m_verts[0]);
+
+ pos = t.m_verts[0]*b[0] + t.m_verts[1]*b[1] + t.m_verts[2]*b[2];
+// pos.Print();
+// pos += (t.m_verts[0] - t.m_verts[1]) * b;
+// pos += (t.m_verts[0] - t.m_verts[2]) * b;
+
+
+// pos.Print();
+ LOG.Write("Found");
+ result[2] = result[2]<pos[2]?pos[2]:result[2];
+// return pos;
+ }
+ }
+ }
+
+ return result;
+}
+*/
+
+TerrainAssetInstance::TerrainAssetInstance(MercuryAsset* asset, MercuryNode* parentNode)
+ :base(asset, parentNode)
+{
+ REGISTER_FOR_MESSAGE("QueryTerrainPoint");
+}
+
+TerrainAssetInstance::~TerrainAssetInstance()
+{
+ UNREGISTER_FOR_MESSAGE("QueryTerrainPoint");
+}
+
+void TerrainAssetInstance::HandleMessage(const MString& message, const MessageData* data)
+{
+ if (message == "QueryTerrainPoint")
+ {
+ VertexDataMessage* v = (VertexDataMessage*)data;
+
+ //compute local space position
+ MercuryVertex local = v->Vertex * m_parentNode->GetGlobalMatrix();
+ local[3] = 1; //no W
+
+ Terrain* t = (Terrain*)m_asset.Ptr();
+ local = t->ComputePositionLinear( local );
+ local[2] += 0.5; //height of player
+
+ local = m_parentNode->GetGlobalMatrix() * local;
+ POST_MESSAGE("SetCameraPosition", new VertexDataMessage(local), 0);
+ }
+}
+
+
Modified: Mercury2/modules/Terrain.h
===================================================================
--- Mercury2/modules/Terrain.h 2009-10-12 23:54:57 UTC (rev 566)
+++ Mercury2/modules/Terrain.h 2009-10-12 23:55:41 UTC (rev 567)
@@ -17,6 +17,10 @@
static Terrain* Generate();
virtual void LoadedCallback(); //thread safe
+ virtual MercuryAssetInstance* GenerateInstanceData(MercuryNode* parentNode);
+ MercuryVertex ComputePosition(const MercuryVertex& p);
+ MercuryVertex ComputePositionLinear(const MercuryVertex& p);
+
private:
CLASS_HELPERS( HGMDLModel );
void BuildHash();
@@ -29,6 +33,16 @@
// std::vector< MAutoPtr< HGMDLMesh > > m_meshes;
};
+class TerrainAssetInstance : public MercuryAssetInstance
+{
+ public:
+ TerrainAssetInstance(MercuryAsset* asset, MercuryNode* parentNode);
+ ~TerrainAssetInstance();
+ virtual void HandleMessage(const MString& message, const MessageData* data);
+ private:
+ CLASS_HELPERS( MercuryAssetInstance );
+};
+
#endif
/****************************************************************************
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cn...@us...> - 2009-11-13 07:46:10
|
Revision: 619
http://hgengine.svn.sourceforge.net/hgengine/?rev=619&view=rev
Author: cnlohr
Date: 2009-11-13 07:45:59 +0000 (Fri, 13 Nov 2009)
Log Message:
-----------
Allow for post-shifting of text.
Modified Paths:
--------------
Mercury2/modules/TextNode.cpp
Mercury2/modules/TextNode.h
Modified: Mercury2/modules/TextNode.cpp
===================================================================
--- Mercury2/modules/TextNode.cpp 2009-11-13 07:44:56 UTC (rev 618)
+++ Mercury2/modules/TextNode.cpp 2009-11-13 07:45:59 UTC (rev 619)
@@ -17,7 +17,9 @@
m_fTextWidth( INFINITY ),
m_kVBO(0), m_kTEX(0),
m_fRMinX(0),m_fRMinY(0),
- m_fRMaxX(0),m_fRMaxY(0)
+ m_fRMaxX(0),m_fRMaxY(0),
+ m_fShiftX(0),m_fShiftY(0),
+ m_bShiftAbsolute(false)
{
//Disabling saving of children... As, we create many temporary children.
m_bEnableSaveChildren = false;
@@ -45,6 +47,13 @@
if( m_fTextWidth < 1e9 )
sXMLStream += ssprintf( "width=\"%f\" ", m_fTextWidth );
+ if( ABS(m_fShiftX) > 1e-9 )
+ sXMLStream += ssprintf( "shiftx=\"%f\" ", m_fShiftX );
+ if( ABS(m_fShiftY) > 1e-9 )
+ sXMLStream += ssprintf( "shifty=\"%f\" ", m_fShiftY );
+ if( m_bShiftAbsolute )
+ sXMLStream += ssprintf( "shiftAbsolute=\"%d\" ", m_bShiftAbsolute );
+
sXMLStream += "alignment=\"";
switch( m_alignment )
{
@@ -70,6 +79,10 @@
{
MercuryNode::LoadFromXML(node);
+ LOAD_FROM_XML( "shiftx", m_fShiftX, StrToFloat );
+ LOAD_FROM_XML( "shifty", m_fShiftY, StrToFloat );
+ LOAD_FROM_XML( "shiftAbsolute", m_bShiftAbsolute, StrToBool );
+
if ( !node.Attribute("font").empty() )
LoadFont( node.Attribute("font") );
if ( !node.Attribute("size").empty() )
@@ -100,12 +113,14 @@
if( !m_kTEX )
{
- m_kTEX = MAutoPtr< MercuryAsset >( Texture::LoadFromFile( m_pThisFont->m_sImage ) );
+
+ m_kTEX = ASSETFACTORY.Generate( "Texture", m_pThisFont->m_sImage );
if( !m_kTEX )
{
fprintf( stderr, "Could not create Texture for text.\n" );
return;
}
+ m_kTEX->ChangeKey( m_pThisFont->m_sImage );
AddAsset( m_kTEX );
}
@@ -294,12 +309,13 @@
((MercuryVBO*)m_kVBO.Ptr())->AllocateIndexSpace((unsigned)chars.size()*6);
((MercuryVBO*)m_kVBO.Ptr())->AllocateVertexSpace((unsigned)chars.size()*4);
+ float * vd = ((MercuryVBO*)m_kVBO.Ptr())->GetVertexHandle();
+ short unsigned int * id = ((MercuryVBO*)m_kVBO.Ptr())->GetIndexHandle();
+
for( unsigned i = 0; i < chars.size(); i++ )
{
DChar & dc = chars[i];
Glyph * g = dc.glyph;
- float * vd = ((MercuryVBO*)m_kVBO.Ptr())->GetVertexHandle();
- short unsigned int * id = ((MercuryVBO*)m_kVBO.Ptr())->GetIndexHandle();
float sx = (-g->iox + dc.xps)*m_fSize;
float sy = -(-g->ioy + dc.yps)*m_fSize;
@@ -359,6 +375,23 @@
if( sx < m_fRMinX ) m_fRMinX = sx;
}
+ if( ABS(m_fShiftX) > 1e-9 || ABS(m_fShiftY) > 1e-9 || m_bShiftAbsolute )
+ {
+ for( unsigned i = 0; i < chars.size(); i++ )
+ {
+ for( unsigned j = 0; j < 4; j++ )
+ {
+ vd[(i*4+j)*8+5] += ((m_bShiftAbsolute)?-m_fRMinX:0) + m_fShiftX;
+ vd[(i*4+j)*8+6] += ((m_bShiftAbsolute)?-m_fRMinY:0) + m_fShiftY;
+ }
+ }
+
+ m_fRMaxX += ((m_bShiftAbsolute)?-m_fRMinX:0) + m_fShiftX;
+ m_fRMaxY += ((m_bShiftAbsolute)?-m_fRMinY:0) + m_fShiftY;
+ m_fRMinX += ((m_bShiftAbsolute)?-m_fRMinX:0) + m_fShiftX;
+ m_fRMinY += ((m_bShiftAbsolute)?-m_fRMinY:0) + m_fShiftY;
+ }
+
((MercuryVBO*)m_kVBO.Ptr())->DirtyVertices();
((MercuryVBO*)m_kVBO.Ptr())->DirtyIndices();
Modified: Mercury2/modules/TextNode.h
===================================================================
--- Mercury2/modules/TextNode.h 2009-11-13 07:44:56 UTC (rev 618)
+++ Mercury2/modules/TextNode.h 2009-11-13 07:45:59 UTC (rev 619)
@@ -45,6 +45,12 @@
inline float GetRMaxX() { return m_fRMaxX; }
inline float GetRMaxY() { return m_fRMaxY; }
+ inline float GetShiftX() { return m_fShiftX; }
+ inline float GetShiftY() { return m_fShiftY; }
+ inline void SetShiftX( float fX ) { m_fShiftX = fX; }
+ inline void SetShiftY( float fY ) { m_fShiftY = fY; }
+ inline void SetShiftAbsolute( bool bAbs ) { m_bShiftAbsolute = bAbs; }
+
virtual void SaveToXMLTag( MString & sXMLStream );
GENRTTI(TextNode);
@@ -70,6 +76,11 @@
float m_fRMaxX;
float m_fRMaxY;
+ float m_fShiftX;
+ float m_fShiftY;
+
+ bool m_bShiftAbsolute;
+
//Font-class specific stuff
class Glyph
{
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cn...@us...> - 2009-11-18 22:10:46
|
Revision: 623
http://hgengine.svn.sourceforge.net/hgengine/?rev=623&view=rev
Author: cnlohr
Date: 2009-11-18 22:10:37 +0000 (Wed, 18 Nov 2009)
Log Message:
-----------
add dialogs
Modified Paths:
--------------
Mercury2/modules/Cu2.cpp
Mercury2/modules/Cu2.h
Modified: Mercury2/modules/Cu2.cpp
===================================================================
--- Mercury2/modules/Cu2.cpp 2009-11-18 22:09:24 UTC (rev 622)
+++ Mercury2/modules/Cu2.cpp 2009-11-18 22:10:37 UTC (rev 623)
@@ -10,7 +10,7 @@
///////////////////////////////////////COPPER 2 ELEMENT///////////////////////////////////////
Cu2Element::Cu2Element() : TransformNode(),
- m_pFocusNode(0), m_bCanTabStop( false ), m_iButtonMask(0), m_bWasMouseInThisFrame(0),
+ m_pFocusNode(0), m_bCanTabStop( true ), m_bWasMouseInThisFrame(0),
m_fX(0), m_fY(0), m_fW(100), m_fH(100),
m_fOrigX(0), m_fOrigY(0), m_fOrigW(100), m_fOrigH(100)
{
@@ -45,7 +45,7 @@
SetSize( m_fOrigW, m_fOrigH );
}
-bool Cu2Element::MouseMotion( int x, int y, unsigned char iCurrentButtonMask )
+bool Cu2Element::MouseMotion( int x, int y, unsigned char iCurrentButtonMask, unsigned char iLastButtonMask )
{
if( IsHidden() )
return false;
@@ -62,13 +62,12 @@
for( unsigned button = 0; button < 8; button++ )
{
unsigned char Mask = 1<<button;
- bool bWasDown = m_iButtonMask & Mask;
+ bool bWasDown = iLastButtonMask & Mask;
bool bIsDown = iCurrentButtonMask & Mask;
if( bWasDown && !bIsDown )
{
//XXX: When we release outside - we want to propogate that information, and that can be tricky..
//So, instead, we choose to propogate that elsewhere...
- m_iButtonMask &= ~Mask;
if( bIsInside )
MouseAction( x, y, RELEASE_IN, button );
else
@@ -76,18 +75,19 @@
}
else if( !bWasDown && bIsDown && bIsInside )
{
- m_iButtonMask |= Mask;
MouseAction( x, y, PRESS_IN, button );
}
}
if( bIsInside )
- for( MercuryNode* send = FirstChild(); send; send = NextChild( send ) )
+ for( MercuryNode* send = LastChild(); send; send = PrevChild( send ) )
{
Cu2Element * sa = dynamic_cast<Cu2Element*>(send);
if( sa )
{
- sa->MouseMotion( x - int(sa->m_fX), y - int(sa->m_fY), iCurrentButtonMask );
+ //Break on the first one that is a hit, that way we don't pass mouse info to buttons below.
+ if( sa->MouseMotion( x - int(sa->m_fX), y - int(sa->m_fY), iCurrentButtonMask, iLastButtonMask ) )
+ return bIsInside;
}
}
@@ -108,7 +108,8 @@
void Cu2Element::MouseAction( int x, int y, Cu2Action c, int iWhichButton )
{
- //nothing
+ if( c == PRESS_IN )
+ RaiseFocus();
}
void Cu2Element::AddChild(MercuryNode* n)
@@ -154,6 +155,39 @@
return 0;
}
+bool Cu2Element::HasFocus()
+{
+ Cu2Element * sa = dynamic_cast<Cu2Element*>(Parent());
+
+ if( sa && sa->m_pFocusNode == this )
+ return true;
+ else
+ return false;
+}
+
+void Cu2Element::RaiseFocus()
+{
+ Cu2Element * ca = dynamic_cast<Cu2Element*>(Parent());
+
+ if( ca )
+ {
+ bool bCouldTabStop = IsEnableTabStop( );
+
+ //Remove this node from wherever it is
+ ca->RemoveChild( this );
+
+ //This is reset by RemoveChild - so we have to update.
+ SetEnableTabStop( bCouldTabStop );
+
+ //Make it so it draws last.
+ ca->AddChild( this );
+
+ ca->m_pFocusNode = this;
+
+ ca->RaiseFocus();
+ }
+}
+
void Cu2Element::SetHidden( bool bHide )
{
MercuryNode::SetHidden( bHide );
@@ -184,12 +218,14 @@
for( MercuryNode* send = FirstChild(); send; send = NextChild( send ) )
{
Cu2Element * sa = dynamic_cast<Cu2Element*>(send);
+
if( sa && sa->IsEnableTabStop() && !sa->IsHidden() )
{
m_pFocusNode = sa;
return;
}
}
+
m_pFocusNode = 0;
}
@@ -242,8 +278,10 @@
}
else
{
- MouseMotion( m.dx, MercuryWindow::GetCurrentWindow()->Height()-m.dy, m.buttons.data );
+ MouseMotion( m.dx, MercuryWindow::GetCurrentWindow()->Height()-m.dy, m.buttons.data, m_iLastButtonMask );
}
+
+ m_iLastButtonMask = m.buttons.data;
}
void Cu2Root::HandleKeyboardInput(const MessageData& data)
@@ -312,7 +350,7 @@
if( c == RELEASE_IN )
{
if( m_bDown )
- Click();
+ Click( x, y );
m_bDown = false;
}
@@ -320,6 +358,8 @@
{
m_bDown = false;
}
+
+ Cu2Element::MouseAction( x, y, c, iWhichButton );
}
void Cu2Button::Refresh()
@@ -336,11 +376,10 @@
if( m_bAutoSize )
{
SetSize( m_pText->GetRMaxX() + 8, m_pText->GetRMaxY() + 8 );
- printf( "Size: %f %f\n", m_pText->GetRMaxX() + 8, m_pText->GetRMaxY() + 8 );
}
}
-void Cu2Button::Click()
+void Cu2Button::Click( int x, int y )
{
if( m_sMessageToSend.length() )
MESSAGEMAN.BroadcastMessage( m_sMessageToSend, new PointerDataMessage( this ) );
@@ -389,7 +428,128 @@
REGISTER_NODE_TYPE(Cu2Button);
+///////////////////////////////////////COPPER 2 DIALOG///////////////////////////////////////
+
+Cu2Dialog::Cu2Dialog() : Cu2Element(), m_bDragging( false ), m_iClickX( 0 ), m_iClickY( 0 )
+{
+ m_sTitle = "(not set)";
+ m_pTitle = (TextNode*)NODEFACTORY.Generate( "TextNode" );
+ AddChild( m_pTitle );
+}
+
+void Cu2Dialog::LoadFromXML(const XMLNode& node)
+{
+ LOAD_FROM_XML( "text", m_sTitle, );
+
+ if( m_pTitle )
+ {
+ m_pTitle->SetAlignment( TextNode::LEFT );
+ m_pTitle->LoadFont( node.Attribute("font") );
+ m_pTitle->SetSize( StrToFloat( node.Attribute("size") ) );
+ m_pTitle->SetShiftAbsolute( true );
+ m_pTitle->SetShiftX( 3 );
+ m_pTitle->SetShiftY( GetH() - 18 );
+ SetText( m_sTitle );
+ }
+ Cu2Element::LoadFromXML( node );
+}
+
+void Cu2Dialog::SaveToXMLTag( MString & sXMLStream )
+{
+ if( !m_pTitle )
+ m_pTitle->SaveToXMLTag( sXMLStream );
+
+ Cu2Element::SaveToXMLTag( sXMLStream );
+}
+
+void Cu2Dialog::Render( const MercuryMatrix& m )
+{
+ glDisable( GL_TEXTURE_2D );
+ glColor3f( 0.5, 0.5, 0.5 );
+
+ glBegin( GL_QUADS );
+ glVertex2f( 1., 1. );
+ glVertex2f( GetW()-1, 1 );
+ glVertex2f( GetW()-1, GetH()-1);
+ glVertex2f( 1., GetH()-1 );
+ glEnd();
+
+ glLineWidth( 2 );
+ glBegin( GL_LINES );
+ glColor3f( 0.7, 0.7, 0.7 );
+ glVertex2f( 1, 1 );
+ glVertex2f( 1, GetH()-1 );
+ glVertex2f( 1, GetH()-1 );
+ glVertex2f( GetW()-2, GetH()-1 );
+ glColor3f( 0.1, 0.1, 0.1 );
+ glVertex2f( GetW()-1, GetH()-2 );
+ glVertex2f( GetW()-1, 1 );
+ glVertex2f( GetW()-1, 1 );
+ glVertex2f( 1, 1 );
+ glEnd();
+
+ if( HasFocus() )
+ glColor3f( 0., 0., 1. );
+ else
+ glColor3f( .3, .3, .3 );
+
+ glBegin( GL_QUADS );
+ glVertex2f( 2., GetH()-18 );
+ glVertex2f( GetW()-2, GetH()-18 );
+ glVertex2f( GetW()-2, GetH()-3 );
+ glVertex2f( 2., GetH()-3 );
+ glEnd();
+
+ glEnable( GL_TEXTURE_2D );
+
+ glColor3f( 1., 1., 1. );
+
+ TransformNode::Render( m );
+}
+
+void Cu2Dialog::MouseAction( int x, int y, Cu2Action c, int iWhichButton )
+{
+ if( y > GetH() - 14 && c == PRESS_IN )
+ {
+ m_bDragging = true;
+ m_iClickX = x;
+ m_iClickY = y;
+ }
+
+ if( c == RELEASE_IN || c == RELEASE_OUT )
+ m_bDragging = false;
+
+
+ Cu2Element::MouseAction( x, y, c, iWhichButton );
+}
+
+bool Cu2Dialog::MouseMotion( int x, int y, unsigned char iCurrentButtonMask, unsigned char iLastButtonMask )
+{
+ if( m_bDragging )
+ {
+ float ix = GetX() - ( m_iClickX - x );
+ float iy = GetY() - ( m_iClickY - y );
+
+ SetXY( ix, iy );
+ }
+ return Cu2Element::MouseMotion( x, y, iCurrentButtonMask, iLastButtonMask );
+}
+
+void Cu2Dialog::SetText( const MString & sText )
+{
+ m_sTitle = sText;
+ if( m_pTitle )
+ {
+ m_pTitle->SetText( m_sTitle );
+ m_pTitle->RenderText();
+ }
+}
+
+
+REGISTER_NODE_TYPE(Cu2Dialog);
+
+
/****************************************************************************
* Copyright (C) 2008-2009 by Joshua Allen *
* Charles Lohr *
Modified: Mercury2/modules/Cu2.h
===================================================================
--- Mercury2/modules/Cu2.h 2009-11-18 22:09:24 UTC (rev 622)
+++ Mercury2/modules/Cu2.h 2009-11-18 22:10:37 UTC (rev 623)
@@ -37,7 +37,7 @@
///Push raw mouse event. Generally, this calls MouseAction, and is only called internally.
///You may override this if you want to take actions that require mouse motion.
- virtual bool MouseMotion( int x, int y, unsigned char iCurrentButtonMask );
+ virtual bool MouseMotion( int x, int y, unsigned char iCurrentButtonMask, unsigned char iLastButtonMask );
///Called when a key is pressed - down the focus line.
virtual void GetKeypress( int key, bool bDown, bool bRepeat );
@@ -53,6 +53,12 @@
///Also handle tab stopping correctly.
virtual void SetHidden( bool bHide );
+ ///Does this node have focus?
+ bool HasFocus();
+
+ ///Make this object get focus.
+ void RaiseFocus();
+
///Progress to the next tab.
Cu2Element * NextTab();
@@ -68,12 +74,6 @@
///Propogate Release (You should not override this or modify it)
void PropogateReleaseOut( int x, int y, int iWhichButton );
- ///Get current button mask
- inline unsigned char GetCurrentButtonMask() { return m_iButtonMask; }
-
- ///Get if current button is down
- inline bool IsButtonDown( char iWhichButton ) { return (m_iButtonMask)&(1<<iWhichButton); }
-
///Set Position
void SetXY( float fX, float fY ) { m_fX = fX; m_fY = fY; SetPosition( MercuryVertex( m_fX, m_fY, 0. ) ); }
void SetX( float fX ) { m_fX = fX; SetPosition( MercuryVertex( m_fX, m_fY, 0 ) ); }
@@ -102,9 +102,6 @@
bool m_bCanTabStop;
- ///Mask of currently depressed buttons.
- unsigned char m_iButtonMask;
-
bool m_bWasMouseInThisFrame;
float m_fX, m_fY, m_fW, m_fH;
@@ -133,6 +130,7 @@
GENRTTI( Cu2Root );
private:
static Cu2Root * g_pCurrentInstance;
+ unsigned char m_iLastButtonMask;
};
class TextNode;
@@ -145,7 +143,7 @@
virtual void MouseAction( int x, int y, Cu2Action c, int iWhichButton );
///This function gets called whenever the button is clicked, you should abstract from this.
- virtual void Click();
+ virtual void Click( int x, int y );
virtual void LoadFromXML(const XMLNode& node);
virtual void SaveToXMLTag( MString & sXMLStream );
@@ -168,6 +166,29 @@
TextNode * m_pText;
};
+class Cu2Dialog : public Cu2Element
+{
+public:
+ Cu2Dialog();
+ GENRTTI( Cu2Dialog );
+
+ TextNode * GetTextNodeHandle() { return m_pTitle; }
+
+ virtual void LoadFromXML(const XMLNode& node);
+ virtual void SaveToXMLTag( MString & sXMLStream );
+ virtual void Render( const MercuryMatrix& m );
+ virtual bool MouseMotion( int x, int y, unsigned char iCurrentButtonMask, unsigned char iLastButtonMask );
+ virtual void MouseAction( int x, int y, Cu2Action c, int iWhichButton );
+
+ void SetText( const MString & sText );
+
+private:
+ bool m_bDragging;
+ int m_iClickX, m_iClickY;
+ TextNode * m_pTitle;
+ MString m_sTitle;
+};
+
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <axl...@us...> - 2009-12-14 20:17:48
|
Revision: 627
http://hgengine.svn.sourceforge.net/hgengine/?rev=627&view=rev
Author: axlecrusher
Date: 2009-12-14 20:17:42 +0000 (Mon, 14 Dec 2009)
Log Message:
-----------
add particle emitter
Modified Paths:
--------------
Mercury2/modules/Makefile
Added Paths:
-----------
Mercury2/modules/ParticleEmitter.cpp
Mercury2/modules/ParticleEmitter.h
Modified: Mercury2/modules/Makefile
===================================================================
--- Mercury2/modules/Makefile 2009-12-14 20:16:40 UTC (rev 626)
+++ Mercury2/modules/Makefile 2009-12-14 20:17:42 UTC (rev 627)
@@ -2,7 +2,7 @@
CXXFLAGS=${CFLAGS}
LDFLAGS=-shared
-all : BillboardNode.so TextNode.so Terrain.so TextPlate.so Cu2.so
+all : BillboardNode.so TextNode.so Terrain.so TextPlate.so ParticleEmitter.so Cu2.so
clean :
rm -rf *~ *.o *.so
Added: Mercury2/modules/ParticleEmitter.cpp
===================================================================
--- Mercury2/modules/ParticleEmitter.cpp (rev 0)
+++ Mercury2/modules/ParticleEmitter.cpp 2009-12-14 20:17:42 UTC (rev 627)
@@ -0,0 +1,209 @@
+#include <ParticleEmitter.h>
+#include <Shader.h>
+#include <GLHeaders.h>
+
+//REGISTER_NODE_TYPE(ParticleBase);
+REGISTER_NODE_TYPE(ParticleEmitter);
+
+
+ParticleBase::ParticleBase()
+ :m_nextParticle(NULL), m_age(0), m_lifespan(0)
+{
+}
+
+ParticleBase::~ParticleBase()
+{
+// m_children.clear();
+}
+
+void ParticleBase::Init()
+{
+ base::Init();
+ m_age = 0;
+// m_lifespan = (rand()%5000)/1000.f;
+// LOG.Write("init particle");
+}
+
+void ParticleBase::Update(float dTime)
+{
+ base::Update(dTime);
+
+ m_age += dTime;
+ if (m_age >= m_lifespan) m_emitter->DeactivateParticle(this);
+}
+
+void ParticleBase::RecursiveRender()
+{
+ ShaderAttribute sa;
+ sa.type = ShaderAttribute::TYPE_FLOATV4;
+ sa.value.fFloatV4[0] = m_age;
+ sa.value.fFloatV4[1] = m_lifespan;
+ sa.value.fFloatV4[2] = m_seed1;
+ sa.value.fFloatV4[3] = m_seed2;
+ Shader::SetAttribute("HG_ParticleTime", sa);
+
+ GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT) );
+ GLCALL( glDepthMask( false ) );
+ GLCALL( glDisable(GL_CULL_FACE) );
+
+ base::RecursiveRender();
+
+ GLCALL( glPopAttrib() );
+}
+/*
+void ParticleBase::Activate()
+{
+ LOG.Write("Activate");
+ m_emitter->AddChild(this);
+}
+
+void ParticleBase::Deactivate()
+{
+ LOG.Write("Deactivate");
+ m_emitter->RemoveChild(this);
+ m_emitter->DeactivateParticle(this);
+}
+*/
+ParticleEmitter::ParticleEmitter()
+ :m_maxParticles(50), m_age(0), m_emitDelay(0.01), m_lifespan(0),
+ m_particlesEmitted(0), m_particleMinLife(0.01), m_particleMaxLife(5),
+ m_inactiveParticles(NULL), m_particles(NULL), GenerateParticlesClbk(NULL)
+{
+ Init();
+}
+
+
+ParticleEmitter::~ParticleEmitter()
+{
+ DestroyParticles();
+
+ SAFE_DELETE(GenerateParticlesClbk);
+// SAFE_DELETE(m_masterParticle);
+}
+
+
+void ParticleEmitter::Init()
+{
+ MercuryNode::Init();
+ DestroyParticles();
+
+ if (GenerateParticlesClbk) m_particles = (*GenerateParticlesClbk)(m_maxParticles);
+ m_particles = new ParticleBase[m_maxParticles];
+ m_inactiveParticles = m_particles;
+ FillUnusedParticleList(m_particles, 0);
+}
+
+
+void ParticleEmitter::DestroyParticles()
+{
+ for (uint32_t i = 0; (i < m_maxParticles) && m_particles; ++i)
+ RemoveChild(m_particles+i);
+ SAFE_DELETE_ARRAY(m_particles); //do we need to destroy each element????
+}
+
+void ParticleEmitter::Update(float dTime)
+{
+ m_age += dTime;
+
+ /* create particles until we meet the total number of
+ particles possible in terms of the age of the emitter */
+ while (((m_age-(m_particlesEmitted*m_emitDelay)) > m_emitDelay) && (m_emitDelay>0))
+ {
+// LOG.Write("Emit");
+ ++m_particlesEmitted; //always increment even if the maximum number of particles exist
+ ActivateParticle();
+ }
+}
+
+void ParticleEmitter::ActivateParticle()
+{
+ if (m_inactiveParticles)
+ {
+ ParticleBase* p = m_inactiveParticles;
+ m_inactiveParticles = p->m_nextParticle;
+ p->m_nextParticle = NULL;
+ p->Init();
+
+
+ p->m_lifespan = m_particleMinLife;
+ p->m_lifespan = (rand()%(int(m_particleMaxLife*1000) - int(m_particleMinLife*1000)))/1000.0f;
+ p->m_seed1 = rand()%100000;
+ p->m_seed2 = rand()%100000;
+// +((rand()%((m_particleMaxLife*1000)-(m_particleMinLife*1000)))/1000.0f);
+
+ AddChild(p);
+ }
+}
+
+void ParticleEmitter::DeactivateParticle(ParticleBase* p)
+{
+// LOG.Write("Deactivate");
+ RemoveChild(p);
+ if (!m_inactiveParticles)
+ {
+ m_inactiveParticles = p;
+ }
+ else
+ {
+ ParticleBase* ip = m_inactiveParticles;
+ while (ip->m_nextParticle) ip = ip->m_nextParticle;
+ ip->m_nextParticle = p;
+ }
+}
+
+void ParticleEmitter::FillUnusedParticleList(ParticleBase* p, uint32_t i)
+{
+ if (p)
+ {
+ p->m_emitter = this;
+ ++i;
+ if (i<m_maxParticles) p->m_nextParticle = m_particles+i;
+ FillUnusedParticleList(p->m_nextParticle, i);
+ }
+}
+
+void ParticleEmitter::LoadFromXML(const XMLNode& node)
+{
+ base::LoadFromXML(node);
+
+ XMLNode particleXML;
+ for (XMLNode n = node.Child(); n.IsValid(); n=n.NextNode())
+ if (n.Name() == "particle")
+ particleXML = n;
+
+ for (uint32_t i = 0; (i < m_maxParticles) && m_particles; ++i)
+ m_particles[i].LoadFromXML(particleXML);
+}
+
+
+/****************************************************************************
+ * Copyright (C) 2009 by Joshua Allen *
+ * *
+ * *
+ * All rights reserved. *
+ * *
+ * Redistribution and use in source and binary forms, with or without *
+ * modification, are permitted provided that the following conditions *
+ * are met: *
+ * * Redistributions of source code must retain the above copyright *
+ * notice, this list of conditions and the following disclaimer. *
+ * * Redistributions in binary form must reproduce the above *
+ * copyright notice, this list of conditions and the following *
+ * disclaimer in the documentation and/or other materials provided *
+ * with the distribution. *
+ * * Neither the name of the Mercury Engine nor the names of its *
+ * contributors may be used to endorse or promote products derived *
+ * from this software without specific prior written permission. *
+ * *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+ ***************************************************************************/
Added: Mercury2/modules/ParticleEmitter.h
===================================================================
--- Mercury2/modules/ParticleEmitter.h (rev 0)
+++ Mercury2/modules/ParticleEmitter.h 2009-12-14 20:17:42 UTC (rev 627)
@@ -0,0 +1,102 @@
+#ifndef PARTICLEEMITTER_H
+#define PARTICLEEMITTER_H
+
+#include <MercuryNode.h>
+#include <Callback.h>
+
+class ParticleEmitter;
+
+class ParticleBase : public MercuryNode
+{
+ public:
+ ParticleBase();
+ ~ParticleBase();
+
+ virtual void Init();
+ virtual void Update(float dTime);
+
+ virtual void RecursiveRender();
+
+// void Activate();
+// void Deactivate();
+
+ GENRTTI( ParticleBase );
+ private:
+ CLASS_HELPERS( MercuryNode );
+
+ friend class ParticleEmitter;
+ ParticleBase* m_nextParticle;
+ float m_age;
+ float m_lifespan;
+ float m_seed1, m_seed2;
+ ParticleEmitter* m_emitter;
+// MercuryNode* m_particleGraph;
+};
+
+class ParticleEmitter : public MercuryNode
+{
+ public:
+ ParticleEmitter();
+ ~ParticleEmitter();
+
+ virtual void Init();
+ virtual void Update(float dTime);
+
+ void DeactivateParticle(ParticleBase* p);
+ virtual void LoadFromXML(const XMLNode& node);
+
+ GENRTTI( ParticleEmitter );
+ private:
+ void DestroyParticles();
+ void ActivateParticle();
+ void FillUnusedParticleList(ParticleBase* p, uint32_t);
+ CLASS_HELPERS( MercuryNode );
+
+ uint32_t m_maxParticles;
+ float m_age;
+ float m_emitDelay; //seconds
+ float m_lifespan; //emitter lifespan
+ uint32_t m_particlesEmitted;
+ float m_particleMinLife, m_particleMaxLife;
+
+ ParticleBase* m_inactiveParticles;
+ ParticleBase* m_particles;
+
+ Callback1R<uint32_t,ParticleBase*>* GenerateParticlesClbk;
+
+// MercuryNode* m_masterParticle;
+};
+
+#endif
+
+/****************************************************************************
+ * Copyright (C) 2009 by Joshua Allen *
+ * *
+ * *
+ * All rights reserved. *
+ * *
+ * Redistribution and use in source and binary forms, with or without *
+ * modification, are permitted provided that the following conditions *
+ * are met: *
+ * * Redistributions of source code must retain the above copyright *
+ * notice, this list of conditions and the following disclaimer. *
+ * * Redistributions in binary form must reproduce the above *
+ * copyright notice, this list of conditions and the following *
+ * disclaimer in the documentation and/or other materials provided *
+ * with the distribution. *
+ * * Neither the name of the Mercury Engine nor the names of its *
+ * contributors may be used to endorse or promote products derived *
+ * from this software without specific prior written permission. *
+ * *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+ ***************************************************************************/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <axl...@us...> - 2009-12-23 01:29:43
|
Revision: 633
http://hgengine.svn.sourceforge.net/hgengine/?rev=633&view=rev
Author: axlecrusher
Date: 2009-12-23 01:29:35 +0000 (Wed, 23 Dec 2009)
Log Message:
-----------
working on faster particles
Modified Paths:
--------------
Mercury2/modules/ParticleEmitter.cpp
Mercury2/modules/ParticleEmitter.h
Modified: Mercury2/modules/ParticleEmitter.cpp
===================================================================
--- Mercury2/modules/ParticleEmitter.cpp 2009-12-22 16:08:48 UTC (rev 632)
+++ Mercury2/modules/ParticleEmitter.cpp 2009-12-23 01:29:35 UTC (rev 633)
@@ -2,23 +2,28 @@
#include <Shader.h>
#include <GLHeaders.h>
+#include <MercuryVBO.h>
+#include <Texture.h>
+
//REGISTER_NODE_TYPE(ParticleBase);
REGISTER_NODE_TYPE(ParticleEmitter);
+#define BUFFER_OFFSET(i) ((char*)NULL + (i))
ParticleBase::ParticleBase()
- :m_nextParticle(NULL), m_age(0), m_lifespan(0)
+ :m_nextParticle(NULL), m_age(0), m_lifespan(0), m_particleVobData(NULL)
{
}
ParticleBase::~ParticleBase()
{
+ m_particleVobData = NULL;
// m_children.clear();
}
void ParticleBase::Init()
{
- base::Init();
+// base::Init();
m_age = 0;
// m_lifespan = (rand()%5000)/1000.f;
// LOG.Write("init particle");
@@ -26,20 +31,26 @@
void ParticleBase::Update(float dTime)
{
- base::Update(dTime);
+// base::Update(dTime);
m_age += dTime;
- if (m_age >= m_lifespan) m_emitter->DeactivateParticle(this);
+ WriteAgeToVBO();
+
+ if (m_age >= m_lifespan)
+ {
+ m_emitter->DeactivateParticle(this);
+ Deactivate();
+ }
}
-
+/*
void ParticleBase::RecursiveRender()
{
ShaderAttribute sa;
sa.type = ShaderAttribute::TYPE_FLOATV4;
sa.value.fFloatV4[0] = m_age;
sa.value.fFloatV4[1] = m_lifespan;
- sa.value.fFloatV4[2] = m_seed1;
- sa.value.fFloatV4[3] = m_seed2;
+ sa.value.fFloatV4[2] = m_rand1;
+ sa.value.fFloatV4[3] = m_rand2;
Shader::SetAttribute("HG_ParticleTime", sa);
GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT) );
@@ -50,6 +61,89 @@
GLCALL( glPopAttrib() );
}
+*/
+void ParticleBase::WriteAgeToVBO()
+{
+ m_emitter->SetDirtyVBO();
+ for (uint8_t i = 0; i < 4; ++i)
+ WriteFloatToVertices(m_age,i,3);
+}
+
+void ParticleBase::WriteLifespanToVBO()
+{
+ m_emitter->SetDirtyVBO();
+ for (uint8_t i = 0; i < 4; ++i)
+ WriteFloatToVertices(m_lifespan,i,4);
+}
+
+void ParticleBase::WriteRand1ToVBO()
+{
+ m_emitter->SetDirtyVBO();
+ for (uint8_t i = 0; i < 4; ++i)
+ WriteFloatToVertices(m_rand1,i,5);
+}
+
+void ParticleBase::WriteRand2ToVBO()
+{
+ m_emitter->SetDirtyVBO();
+ for (uint8_t i = 0; i < 4; ++i)
+ WriteFloatToVertices(m_rand2,i,6);
+}
+
+void ParticleBase::Activate()
+{
+ uint8_t i = 0;
+
+ //upper left
+ m_particleVobData[i++] = -0.5; m_particleVobData[i++] = 0.5; m_particleVobData[i++] = 0;
+ i+=4; m_particleVobData[i++] = 1; m_particleVobData[i++] = 0; //skip color data and set U,V
+
+ //lower left
+ m_particleVobData[i++] = -0.5; m_particleVobData[i++] = -0.5; m_particleVobData[i++] = 0;
+ i+=4; m_particleVobData[i++] = 0; m_particleVobData[i++] = 0; //skip color data and set U,V
+
+ //lower right
+ m_particleVobData[i++] = 0.5; m_particleVobData[i++] = -0.5; m_particleVobData[i++] = 0;
+ i+=4; m_particleVobData[i++] = 0; m_particleVobData[i++] = 1; //skip color data and set U,V
+
+ //upper right
+ m_particleVobData[i++] = 0.5; m_particleVobData[i++] = 0.5; m_particleVobData[i++] = 0;
+ i+=4; m_particleVobData[i++] = 1; m_particleVobData[i++] = 1; //skip color data and set U,V
+
+/* for (uint8_t i = 0; i < 4; ++i)
+ {
+ WriteFloatToVertices(0,i,0);
+ WriteFloatToVertices(0,i,1);
+ WriteFloatToVertices(0,i,2);
+ }
+*/
+ m_emitter->SetDirtyVBO();
+}
+
+void ParticleBase::Deactivate()
+{
+ m_emitter->SetDirtyVBO();
+ for (uint8_t i = 0; i < 4; ++i)
+ {
+ WriteFloatToVertices(0,i,0);
+ WriteFloatToVertices(0,i,1);
+ WriteFloatToVertices(0,i,2);
+ }
+}
+
+void ParticleBase::WriteFloatToVertices(float v, uint8_t vertexIndex, uint8_t offset)
+{
+ *(m_particleVobData+((STRIDE*vertexIndex)+offset)) = v;
+}
+
+void ParticleBase::WriteToVBO()
+{
+ WriteAgeToVBO();
+ WriteLifespanToVBO();
+ WriteRand1ToVBO();
+ WriteRand2ToVBO();
+}
+
/*
void ParticleBase::Activate()
{
@@ -67,7 +161,8 @@
ParticleEmitter::ParticleEmitter()
:m_maxParticles(50), m_age(0), m_emitDelay(0.01), m_lifespan(0),
m_particlesEmitted(0), m_particleMinLife(0.01), m_particleMaxLife(5),
- m_inactiveParticles(NULL), m_particles(NULL), GenerateParticlesClbk(NULL)
+ m_inactiveParticles(NULL), m_particles(NULL), GenerateParticlesClbk(NULL),
+ m_bufferID(0), m_dirtyVBO(false)
{
Init();
}
@@ -77,6 +172,8 @@
{
DestroyParticles();
+ if (m_bufferID > 0) { GLCALL( glDeleteBuffersARB(1, &m_bufferID) ); }
+
SAFE_DELETE(GenerateParticlesClbk);
// SAFE_DELETE(m_masterParticle);
}
@@ -86,18 +183,15 @@
{
MercuryNode::Init();
DestroyParticles();
-
- if (GenerateParticlesClbk) m_particles = (*GenerateParticlesClbk)(m_maxParticles);
- m_particles = new ParticleBase[m_maxParticles];
- m_inactiveParticles = m_particles;
- FillUnusedParticleList(m_particles, 0);
+
+ SetMaxParticleCount(m_maxParticles);
}
void ParticleEmitter::DestroyParticles()
{
- for (uint32_t i = 0; (i < m_maxParticles) && m_particles; ++i)
- RemoveChild(m_particles+i);
+/// for (uint32_t i = 0; (i < m_maxParticles) && m_particles; ++i)
+// RemoveChild(m_particles+i);
SAFE_DELETE_ARRAY(m_particles); //do we need to destroy each element????
}
@@ -123,22 +217,23 @@
m_inactiveParticles = p->m_nextParticle;
p->m_nextParticle = NULL;
p->Init();
+ p->Activate();
p->m_lifespan = m_particleMinLife;
p->m_lifespan += (rand()%(int(m_particleMaxLife*1000) - int(m_particleMinLife*1000)))/1000.0f;
- p->m_seed1 = rand()%100000;
- p->m_seed2 = rand()%100000;
+ p->m_rand1 = rand()%100000;
+ p->m_rand2 = rand()%100000;
// +((rand()%((m_particleMaxLife*1000)-(m_particleMinLife*1000)))/1000.0f);
- AddChild(p);
+// AddChild(p);
}
}
void ParticleEmitter::DeactivateParticle(ParticleBase* p)
{
// LOG.Write("Deactivate");
- RemoveChild(p);
+// RemoveChild(p);
if (!m_inactiveParticles)
{
m_inactiveParticles = p;
@@ -165,7 +260,7 @@
void ParticleEmitter::LoadFromXML(const XMLNode& node)
{
base::LoadFromXML(node);
-
+/*
XMLNode particleXML;
for (XMLNode n = node.Child(); n.IsValid(); n=n.NextNode())
if (n.Name() == "particle")
@@ -173,9 +268,82 @@
for (uint32_t i = 0; (i < m_maxParticles) && m_particles; ++i)
m_particles[i].LoadFromXML(particleXML);
+ */
}
+void ParticleEmitter::SetMaxParticleCount(uint16_t count)
+{
+ //3 floats for position
+ //1 age, 1 lifespan, 2 random
+ //7 floats total per particle
+ m_maxParticles = count;
+ m_vertexData.Allocate(m_maxParticles*ParticleBase::STRIDE*4);
+
+ SAFE_DELETE_ARRAY(m_particles);
+// if (GenerateParticlesClbk) m_particles = (*GenerateParticlesClbk)(m_maxParticles);
+ m_particles = new ParticleBase[m_maxParticles];
+ m_inactiveParticles = m_particles;
+ InitNewParticles(m_particles, 0, ParticleBase::STRIDE*4, m_vertexData.Buffer());
+}
+
+void ParticleEmitter::InitNewParticles(ParticleBase* p, uint32_t i, uint16_t vobStep, float* vob)
+{
+ if (p)
+ {
+ p->m_emitter = this;
+ p->m_particleVobData = vob;
+ p->Deactivate();
+ ++i;
+ if (i<m_maxParticles) p->m_nextParticle = m_particles+i;
+ InitNewParticles(p->m_nextParticle, i, vobStep, vob+vobStep);
+ }
+}
+
+void ParticleEmitter::Render(const MercuryMatrix& matrix)
+{
+ GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT) );
+ GLCALL( glDepthMask( false ) );
+ GLCALL( glDisable(GL_CULL_FACE) );
+
+ if (m_bufferID==0)
+ {
+ GLCALL( glGenBuffersARB(1, &m_bufferID) );
+ }
+
+ GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID) );
+ MercuryVBO::m_lastVBOrendered = this;
+
+ if (m_dirtyVBO)
+ {
+ m_dirtyVBO = false;
+ GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_vertexData.LengthInBytes(), m_vertexData.Buffer(), GL_STATIC_DRAW_ARB) );
+ }
+
+ GLCALL( glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT) );
+
+ //do render stuff here
+// GLCALL( glDisableClientState(GL_TEXTURE_COORD_ARRAY) );
+ Texture::ApplyActiveTextures(ParticleBase::STRIDE*sizeof(float));
+
+ GLCALL( glEnableClientState(GL_VERTEX_ARRAY) );
+ GLCALL( glEnableClientState( GL_COLOR_ARRAY ) ); //used for attributes
+ GLCALL( glVertexPointer(3, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 0*sizeof(float) ) ) );
+ GLCALL( glColorPointer(4, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 3*sizeof(float) ) ) );
+ GLCALL( glTexCoordPointer(3, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 7*sizeof(float) ) ) );
+
+// GLCALL( glDrawRangeElements(GL_QUADS, 0, m_indexData.Length()-1, m_indexData.Length(), GL_UNSIGNED_SHORT, NULL) );
+// GLCALL( glDrawElements(GL_QUADS, m_maxParticles*4, GL_UNSIGNED_BYTE, 0) );
+ GLCALL( glDrawArrays(GL_QUADS, 0, m_maxParticles*4) );
+
+ GLCALL( glPopClientAttrib() );
+
+ base::Render(matrix);
+
+ GLCALL( glPopAttrib() );
+
+}
+
/****************************************************************************
* Copyright (C) 2009 by Joshua Allen *
* *
Modified: Mercury2/modules/ParticleEmitter.h
===================================================================
--- Mercury2/modules/ParticleEmitter.h 2009-12-22 16:08:48 UTC (rev 632)
+++ Mercury2/modules/ParticleEmitter.h 2009-12-23 01:29:35 UTC (rev 633)
@@ -6,7 +6,7 @@
class ParticleEmitter;
-class ParticleBase : public MercuryNode
+class ParticleBase
{
public:
ParticleBase();
@@ -15,22 +15,32 @@
virtual void Init();
virtual void Update(float dTime);
- virtual void RecursiveRender();
+// virtual void RecursiveRender();
-// void Activate();
-// void Deactivate();
+ void Activate();
+ void Deactivate();
+ void WriteToVBO();
- GENRTTI( ParticleBase );
+// GENRTTI( ParticleBase );
private:
- CLASS_HELPERS( MercuryNode );
+// CLASS_HELPERS( MercuryNode );
+ static const uint8_t STRIDE = 9;
+
+ void WriteAgeToVBO();
+ void WriteLifespanToVBO();
+ void WriteRand1ToVBO();
+ void WriteRand2ToVBO();
+ void WriteFloatToVertices(float v, uint8_t vertexIndex, uint8_t offset);
+
friend class ParticleEmitter;
ParticleBase* m_nextParticle;
float m_age;
float m_lifespan;
- float m_seed1, m_seed2;
+ float m_rand1, m_rand2;
ParticleEmitter* m_emitter;
// MercuryNode* m_particleGraph;
+ float* m_particleVobData; //pointer to position in VBO
};
class ParticleEmitter : public MercuryNode
@@ -44,12 +54,19 @@
void DeactivateParticle(ParticleBase* p);
virtual void LoadFromXML(const XMLNode& node);
+ virtual void Render(const MercuryMatrix& matrix);
+ void SetMaxParticleCount(uint16_t count);
+ inline void SetDirtyVBO() { m_dirtyVBO=true; }
+
GENRTTI( ParticleEmitter );
private:
void DestroyParticles();
void ActivateParticle();
- void FillUnusedParticleList(ParticleBase* p, uint32_t);
+
+ void FillUnusedParticleList(ParticleBase* p, uint32_t i);
+ void InitNewParticles(ParticleBase* p, uint32_t i, uint16_t vobStep, float* vob);
+
CLASS_HELPERS( MercuryNode );
uint32_t m_maxParticles;
@@ -63,7 +80,11 @@
ParticleBase* m_particles;
Callback1R<uint32_t,ParticleBase*>* GenerateParticlesClbk;
+ AlignedBuffer<float> m_vertexData;
+ unsigned int m_bufferID;
+ bool m_dirtyVBO;
+
// MercuryNode* m_masterParticle;
};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <axl...@us...> - 2009-12-23 21:24:36
|
Revision: 634
http://hgengine.svn.sourceforge.net/hgengine/?rev=634&view=rev
Author: axlecrusher
Date: 2009-12-23 21:24:26 +0000 (Wed, 23 Dec 2009)
Log Message:
-----------
faster particles
still not 100% working
Modified Paths:
--------------
Mercury2/modules/ParticleEmitter.cpp
Mercury2/modules/ParticleEmitter.h
Modified: Mercury2/modules/ParticleEmitter.cpp
===================================================================
--- Mercury2/modules/ParticleEmitter.cpp 2009-12-23 01:29:35 UTC (rev 633)
+++ Mercury2/modules/ParticleEmitter.cpp 2009-12-23 21:24:26 UTC (rev 634)
@@ -5,63 +5,36 @@
#include <MercuryVBO.h>
#include <Texture.h>
+#include <list>
+using namespace std;
//REGISTER_NODE_TYPE(ParticleBase);
REGISTER_NODE_TYPE(ParticleEmitter);
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
ParticleBase::ParticleBase()
- :m_nextParticle(NULL), m_age(0), m_lifespan(0), m_particleVobData(NULL)
+ :m_age(0), m_lifespan(0), m_particleVobData(NULL)
{
}
ParticleBase::~ParticleBase()
{
m_particleVobData = NULL;
-// m_children.clear();
}
void ParticleBase::Init()
{
-// base::Init();
m_age = 0;
-// m_lifespan = (rand()%5000)/1000.f;
-// LOG.Write("init particle");
}
void ParticleBase::Update(float dTime)
{
-// base::Update(dTime);
-
m_age += dTime;
WriteAgeToVBO();
- if (m_age >= m_lifespan)
- {
- m_emitter->DeactivateParticle(this);
- Deactivate();
- }
+ if (m_age >= m_lifespan) Deactivate();
}
-/*
-void ParticleBase::RecursiveRender()
-{
- ShaderAttribute sa;
- sa.type = ShaderAttribute::TYPE_FLOATV4;
- sa.value.fFloatV4[0] = m_age;
- sa.value.fFloatV4[1] = m_lifespan;
- sa.value.fFloatV4[2] = m_rand1;
- sa.value.fFloatV4[3] = m_rand2;
- Shader::SetAttribute("HG_ParticleTime", sa);
-
- GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT) );
- GLCALL( glDepthMask( false ) );
- GLCALL( glDisable(GL_CULL_FACE) );
-
- base::RecursiveRender();
-
- GLCALL( glPopAttrib() );
-}
-*/
+
void ParticleBase::WriteAgeToVBO()
{
m_emitter->SetDirtyVBO();
@@ -92,6 +65,7 @@
void ParticleBase::Activate()
{
+// printf("Activate\n");
uint8_t i = 0;
//upper left
@@ -122,13 +96,13 @@
void ParticleBase::Deactivate()
{
- m_emitter->SetDirtyVBO();
for (uint8_t i = 0; i < 4; ++i)
{
WriteFloatToVertices(0,i,0);
WriteFloatToVertices(0,i,1);
WriteFloatToVertices(0,i,2);
}
+ m_emitter->SetDirtyVBO();
}
void ParticleBase::WriteFloatToVertices(float v, uint8_t vertexIndex, uint8_t offset)
@@ -144,24 +118,10 @@
WriteRand2ToVBO();
}
-/*
-void ParticleBase::Activate()
-{
- LOG.Write("Activate");
- m_emitter->AddChild(this);
-}
-
-void ParticleBase::Deactivate()
-{
- LOG.Write("Deactivate");
- m_emitter->RemoveChild(this);
- m_emitter->DeactivateParticle(this);
-}
-*/
ParticleEmitter::ParticleEmitter()
- :m_maxParticles(50), m_age(0), m_emitDelay(0.01), m_lifespan(0),
- m_particlesEmitted(0), m_particleMinLife(0.01), m_particleMaxLife(5),
- m_inactiveParticles(NULL), m_particles(NULL), GenerateParticlesClbk(NULL),
+ :base(), m_maxParticles(50), m_age(0), m_emitDelay(0.1), m_lifespan(0),
+ m_particlesEmitted(0), m_particleMinLife(0.1), m_particleMaxLife(5),
+ m_particles(NULL), GenerateParticlesClbk(NULL),
m_bufferID(0), m_dirtyVBO(false)
{
Init();
@@ -170,31 +130,21 @@
ParticleEmitter::~ParticleEmitter()
{
- DestroyParticles();
-
if (m_bufferID > 0) { GLCALL( glDeleteBuffersARB(1, &m_bufferID) ); }
+ SAFE_DELETE_ARRAY(m_particles); //do we need to destroy each element????
SAFE_DELETE(GenerateParticlesClbk);
-// SAFE_DELETE(m_masterParticle);
}
void ParticleEmitter::Init()
{
MercuryNode::Init();
- DestroyParticles();
+ SAFE_DELETE_ARRAY(m_particles); //do we need to destroy each element????
SetMaxParticleCount(m_maxParticles);
}
-
-void ParticleEmitter::DestroyParticles()
-{
-/// for (uint32_t i = 0; (i < m_maxParticles) && m_particles; ++i)
-// RemoveChild(m_particles+i);
- SAFE_DELETE_ARRAY(m_particles); //do we need to destroy each element????
-}
-
void ParticleEmitter::Update(float dTime)
{
m_age += dTime;
@@ -207,58 +157,55 @@
++m_particlesEmitted; //always increment even if the maximum number of particles exist
ActivateParticle();
}
+
+ list< ParticleBase* >::iterator i = m_active.begin();
+ while ( i!=m_active.end() )
+ {
+ ParticleBase *p = *i;
+ p->Update(dTime);
+ if ( !p->IsActive() )
+ {
+ m_active.erase(i++); //don't invalidate iterator before incrementing it
+ m_inactive.push_back(p);
+ }
+ else
+ {
+ ++i;
+ }
+ }
}
void ParticleEmitter::ActivateParticle()
{
- if (m_inactiveParticles)
+ if (!m_inactive.empty())
{
- ParticleBase* p = m_inactiveParticles;
- m_inactiveParticles = p->m_nextParticle;
- p->m_nextParticle = NULL;
+ ParticleBase* p = m_inactive.front();
+ m_inactive.pop_front();
+
p->Init();
p->Activate();
-
p->m_lifespan = m_particleMinLife;
p->m_lifespan += (rand()%(int(m_particleMaxLife*1000) - int(m_particleMinLife*1000)))/1000.0f;
p->m_rand1 = rand()%100000;
p->m_rand2 = rand()%100000;
// +((rand()%((m_particleMaxLife*1000)-(m_particleMinLife*1000)))/1000.0f);
-
-// AddChild(p);
- }
-}
-void ParticleEmitter::DeactivateParticle(ParticleBase* p)
-{
-// LOG.Write("Deactivate");
-// RemoveChild(p);
- if (!m_inactiveParticles)
- {
- m_inactiveParticles = p;
- }
- else
- {
- ParticleBase* ip = m_inactiveParticles;
- while (ip->m_nextParticle) ip = ip->m_nextParticle;
- ip->m_nextParticle = p;
- }
-}
-void ParticleEmitter::FillUnusedParticleList(ParticleBase* p, uint32_t i)
-{
- if (p)
- {
- p->m_emitter = this;
- ++i;
- if (i<m_maxParticles) p->m_nextParticle = m_particles+i;
- FillUnusedParticleList(p->m_nextParticle, i);
+ p->WriteAgeToVBO();
+ p->WriteLifespanToVBO();
+ p->WriteRand1ToVBO();
+ p->WriteRand2ToVBO();
+
+ //add to the active list
+// printf("push %p\n", p);
+ m_active.push_back(p);
}
}
void ParticleEmitter::LoadFromXML(const XMLNode& node)
{
+ printf("LOADED!!!!!\n");
base::LoadFromXML(node);
/*
XMLNode particleXML;
@@ -283,25 +230,32 @@
SAFE_DELETE_ARRAY(m_particles);
// if (GenerateParticlesClbk) m_particles = (*GenerateParticlesClbk)(m_maxParticles);
m_particles = new ParticleBase[m_maxParticles];
- m_inactiveParticles = m_particles;
- InitNewParticles(m_particles, 0, ParticleBase::STRIDE*4, m_vertexData.Buffer());
-}
+// m_inactiveParticles = m_particles;
+// InitNewParticles(m_particles, 0, ParticleBase::STRIDE*4, m_vertexData.Buffer());
-void ParticleEmitter::InitNewParticles(ParticleBase* p, uint32_t i, uint16_t vobStep, float* vob)
-{
- if (p)
+ m_inactive.clear();
+ m_active.clear();
+
+ for (uint32_t i = 0; i < m_maxParticles; ++i)
{
+ ParticleBase* p = m_particles+i;
p->m_emitter = this;
- p->m_particleVobData = vob;
+ p->m_particleVobData = m_vertexData.Buffer()+(ParticleBase::STRIDE*4*i);
p->Deactivate();
- ++i;
- if (i<m_maxParticles) p->m_nextParticle = m_particles+i;
- InitNewParticles(p->m_nextParticle, i, vobStep, vob+vobStep);
+// printf("addr1 %p\n", p);
+ m_inactive.push_back( p );
}
}
+void ParticleEmitter::PreRender(const MercuryMatrix& matrix)
+{
+ MercuryNode::PreRender(matrix);
+ SetCulled(false);
+}
+
void ParticleEmitter::Render(const MercuryMatrix& matrix)
{
+// printf("render particles\n");
GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT) );
GLCALL( glDepthMask( false ) );
GLCALL( glDisable(GL_CULL_FACE) );
@@ -335,12 +289,12 @@
// GLCALL( glDrawRangeElements(GL_QUADS, 0, m_indexData.Length()-1, m_indexData.Length(), GL_UNSIGNED_SHORT, NULL) );
// GLCALL( glDrawElements(GL_QUADS, m_maxParticles*4, GL_UNSIGNED_BYTE, 0) );
GLCALL( glDrawArrays(GL_QUADS, 0, m_maxParticles*4) );
-
+//printf("darw\n");
GLCALL( glPopClientAttrib() );
+ GLCALL( glPopAttrib() );
base::Render(matrix);
- GLCALL( glPopAttrib() );
}
Modified: Mercury2/modules/ParticleEmitter.h
===================================================================
--- Mercury2/modules/ParticleEmitter.h 2009-12-23 01:29:35 UTC (rev 633)
+++ Mercury2/modules/ParticleEmitter.h 2009-12-23 21:24:26 UTC (rev 634)
@@ -21,6 +21,8 @@
void Deactivate();
void WriteToVBO();
+ inline bool IsActive() const { return m_age < m_lifespan; }
+
// GENRTTI( ParticleBase );
private:
// CLASS_HELPERS( MercuryNode );
@@ -34,7 +36,7 @@
void WriteFloatToVertices(float v, uint8_t vertexIndex, uint8_t offset);
friend class ParticleEmitter;
- ParticleBase* m_nextParticle;
+// ParticleBase *m_prev, *m_next;
float m_age;
float m_lifespan;
float m_rand1, m_rand2;
@@ -54,6 +56,9 @@
void DeactivateParticle(ParticleBase* p);
virtual void LoadFromXML(const XMLNode& node);
+
+
+ virtual void PreRender(const MercuryMatrix& matrix);
virtual void Render(const MercuryMatrix& matrix);
void SetMaxParticleCount(uint16_t count);
@@ -61,11 +66,11 @@
GENRTTI( ParticleEmitter );
private:
- void DestroyParticles();
+// void DestroyParticles();
void ActivateParticle();
- void FillUnusedParticleList(ParticleBase* p, uint32_t i);
- void InitNewParticles(ParticleBase* p, uint32_t i, uint16_t vobStep, float* vob);
+// void FillUnusedParticleList(ParticleBase* p, uint32_t i);
+// void InitNewParticles(ParticleBase* p, uint32_t i, uint16_t vobStep, float* vob);
CLASS_HELPERS( MercuryNode );
@@ -76,8 +81,7 @@
uint32_t m_particlesEmitted;
float m_particleMinLife, m_particleMaxLife;
- ParticleBase* m_inactiveParticles;
- ParticleBase* m_particles;
+ ParticleBase *m_particles;
Callback1R<uint32_t,ParticleBase*>* GenerateParticlesClbk;
AlignedBuffer<float> m_vertexData;
@@ -85,6 +89,7 @@
unsigned int m_bufferID;
bool m_dirtyVBO;
+ std::list< ParticleBase* > m_active, m_inactive;
// MercuryNode* m_masterParticle;
};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <axl...@us...> - 2009-12-24 18:12:07
|
Revision: 639
http://hgengine.svn.sourceforge.net/hgengine/?rev=639&view=rev
Author: axlecrusher
Date: 2009-12-24 18:11:56 +0000 (Thu, 24 Dec 2009)
Log Message:
-----------
update for faster particle rendering, use gl_Color instead of uniforms to set values
Modified Paths:
--------------
Mercury2/modules/ParticleEmitter.cpp
Mercury2/modules/ParticleEmitter.h
Modified: Mercury2/modules/ParticleEmitter.cpp
===================================================================
--- Mercury2/modules/ParticleEmitter.cpp 2009-12-24 18:11:04 UTC (rev 638)
+++ Mercury2/modules/ParticleEmitter.cpp 2009-12-24 18:11:56 UTC (rev 639)
@@ -255,8 +255,7 @@
void ParticleEmitter::Render(const MercuryMatrix& matrix)
{
-// printf("render particles\n");
- GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT) );
+ GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT|GL_CURRENT_BIT) );
GLCALL( glDepthMask( false ) );
GLCALL( glDisable(GL_CULL_FACE) );
@@ -266,38 +265,47 @@
}
GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID) );
+// GLCALL( glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0) );
+
MercuryVBO::m_lastVBOrendered = this;
if (m_dirtyVBO)
{
m_dirtyVBO = false;
- GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_vertexData.LengthInBytes(), m_vertexData.Buffer(), GL_STATIC_DRAW_ARB) );
+ GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_vertexData.LengthInBytes(), m_vertexData.Buffer(), GL_STREAM_DRAW_ARB) );
}
GLCALL( glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT) );
//do render stuff here
-// GLCALL( glDisableClientState(GL_TEXTURE_COORD_ARRAY) );
- Texture::ApplyActiveTextures(ParticleBase::STRIDE*sizeof(float));
+ Texture::ApplyActiveTextures(ParticleBase::STRIDE*sizeof(float), 7*sizeof(float));
GLCALL( glEnableClientState(GL_VERTEX_ARRAY) );
GLCALL( glEnableClientState( GL_COLOR_ARRAY ) ); //used for attributes
+// GLCALL( glDisableClientState( GL_NORMAL_ARRAY ) );
+
GLCALL( glVertexPointer(3, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 0*sizeof(float) ) ) );
GLCALL( glColorPointer(4, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 3*sizeof(float) ) ) );
- GLCALL( glTexCoordPointer(3, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 7*sizeof(float) ) ) );
-// GLCALL( glDrawRangeElements(GL_QUADS, 0, m_indexData.Length()-1, m_indexData.Length(), GL_UNSIGNED_SHORT, NULL) );
-// GLCALL( glDrawElements(GL_QUADS, m_maxParticles*4, GL_UNSIGNED_BYTE, 0) );
GLCALL( glDrawArrays(GL_QUADS, 0, m_maxParticles*4) );
-//printf("darw\n");
+
GLCALL( glPopClientAttrib() );
GLCALL( glPopAttrib() );
+ m_particlesDrawn+=m_maxParticles;
+
base::Render(matrix);
+}
-
+uint32_t ParticleEmitter::ResetDrawnCount()
+{
+ uint32_t t = m_particlesDrawn;
+ m_particlesDrawn = 0;
+ return t;
}
+uint32_t ParticleEmitter::m_particlesDrawn = 0;
+
/****************************************************************************
* Copyright (C) 2009 by Joshua Allen *
* *
Modified: Mercury2/modules/ParticleEmitter.h
===================================================================
--- Mercury2/modules/ParticleEmitter.h 2009-12-24 18:11:04 UTC (rev 638)
+++ Mercury2/modules/ParticleEmitter.h 2009-12-24 18:11:56 UTC (rev 639)
@@ -64,6 +64,8 @@
void SetMaxParticleCount(uint16_t count);
inline void SetDirtyVBO() { m_dirtyVBO=true; }
+ static uint32_t ResetDrawnCount();
+
GENRTTI( ParticleEmitter );
private:
// void DestroyParticles();
@@ -91,6 +93,7 @@
std::list< ParticleBase* > m_active, m_inactive;
// MercuryNode* m_masterParticle;
+ static uint32_t m_particlesDrawn;
};
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cn...@us...> - 2010-02-24 05:40:31
|
Revision: 680
http://hgengine.svn.sourceforge.net/hgengine/?rev=680&view=rev
Author: cnlohr
Date: 2010-02-24 05:40:25 +0000 (Wed, 24 Feb 2010)
Log Message:
-----------
forgot to add some stuff :(
Added Paths:
-----------
Mercury2/modules/Skybox.cpp
Mercury2/modules/Skybox.h
Added: Mercury2/modules/Skybox.cpp
===================================================================
--- Mercury2/modules/Skybox.cpp (rev 0)
+++ Mercury2/modules/Skybox.cpp 2010-02-24 05:40:25 UTC (rev 680)
@@ -0,0 +1,72 @@
+#include "Skybox.h"
+#include <Camera.h>
+#include <MercuryMessageManager.h>
+
+REGISTER_NODE_TYPE(Skybox);
+
+Skybox::Skybox()
+ :TransformNode(), m_bFirst(true)
+{
+ REGISTER_MESSAGE_WITH_DELEGATE( "SetCameraPosition", &Skybox::SetCameraPosition );
+}
+
+Skybox::~Skybox()
+{
+ UNREGISTER_FOR_MESSAGE( "SetCameraPosition" );
+}
+
+
+void Skybox::SetCameraPosition(const MessageData& data)
+{
+ const VertexDataMessage& m( dynamic_cast<const VertexDataMessage&>( data ) );
+
+ if( !m_bFirst )
+ SetPosition(m.Vertex);
+}
+
+void Skybox::RecursivePreRender()
+{
+/* CameraNode * cn = CameraNode::GetLastPreRenderedCamera();
+ if( cn )
+ {
+ const MercuryVertex& cp = cn->GetPosition();
+ cn->ComputeMatrix();
+ SetPosition( cp );
+ ComputeMatrix();
+ }
+*/
+ TransformNode::RecursivePreRender( );
+ m_bFirst = false;
+}
+
+/****************************************************************************
+ * Copyright (C) 2010 by Charles Lohr *
+ * *
+ * *
+ * All rights reserved. *
+ * *
+ * Redistribution and use in source and binary forms, with or without *
+ * modification, are permitted provided that the following conditions *
+ * are met: *
+ * * Redistributions of source code must retain the above copyright *
+ * notice, this list of conditions and the following disclaimer. *
+ * * Redistributions in binary form must reproduce the above *
+ * copyright notice, this list of conditions and the following *
+ * disclaimer in the documentation and/or other materials provided *
+ * with the distribution. *
+ * * Neither the name of the Mercury Engine nor the names of its *
+ * contributors may be used to endorse or promote products derived *
+ * from this software without specific prior written permission. *
+ * *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+ ***************************************************************************/
Added: Mercury2/modules/Skybox.h
===================================================================
--- Mercury2/modules/Skybox.h (rev 0)
+++ Mercury2/modules/Skybox.h 2010-02-24 05:40:25 UTC (rev 680)
@@ -0,0 +1,54 @@
+#ifndef Skybox_H
+#define Skybox_H
+
+#include <TransformNode.h>
+
+class Skybox : public TransformNode
+{
+public:
+ Skybox();
+ ~Skybox();
+ virtual void RecursivePreRender();
+
+ void SetCameraPosition(const MessageData& data);
+
+ GENRTTI(Skybox);
+private:
+ bool m_bFirst;
+};
+
+#endif
+
+
+/****************************************************************************
+ * Copyright (C) 2010 by Charles Lohr *
+ * *
+ * *
+ * All rights reserved. *
+ * *
+ * Redistribution and use in source and binary forms, with or without *
+ * modification, are permitted provided that the following conditions *
+ * are met: *
+ * * Redistributions of source code must retain the above copyright *
+ * notice, this list of conditions and the following disclaimer. *
+ * * Redistributions in binary form must reproduce the above *
+ * copyright notice, this list of conditions and the following *
+ * disclaimer in the documentation and/or other materials provided *
+ * with the distribution. *
+ * * Neither the name of the Mercury Engine nor the names of its *
+ * contributors may be used to endorse or promote products derived *
+ * from this software without specific prior written permission. *
+ * *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+ ***************************************************************************/
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cn...@us...> - 2010-04-28 09:21:59
|
Revision: 710
http://hgengine.svn.sourceforge.net/hgengine/?rev=710&view=rev
Author: cnlohr
Date: 2010-04-28 09:21:53 +0000 (Wed, 28 Apr 2010)
Log Message:
-----------
tweak Cu2, gotta look into more what could be going on, though
Modified Paths:
--------------
Mercury2/modules/Cu2.cpp
Mercury2/modules/Cu2.h
Modified: Mercury2/modules/Cu2.cpp
===================================================================
--- Mercury2/modules/Cu2.cpp 2010-04-28 09:21:34 UTC (rev 709)
+++ Mercury2/modules/Cu2.cpp 2010-04-28 09:21:53 UTC (rev 710)
@@ -327,6 +327,14 @@
LOAD_FROM_XML( "associatedValue", m_sAssociatedValue, );
LOAD_FROM_XML( "associatedValueSet", m_sAssociatedValueSet, );
+ LOAD_FROM_XML( "associatedValueX", m_sAssociatedValueX, );
+ LOAD_FROM_XML( "associatedValueY", m_sAssociatedValueY, );
+
+ LOAD_FROM_XML( "xRangeMin", m_sxRangeMin, );
+ LOAD_FROM_XML( "xRangeMax", m_sxRangeMax, );
+ LOAD_FROM_XML( "yRangeMin", m_syRangeMin, );
+ LOAD_FROM_XML( "yRangeMax", m_syRangeMax, );
+
if( m_pText )
{
m_pText->SetAlignment( TextNode::LEFT );
@@ -350,7 +358,14 @@
if( m_bAutoSize ) sXMLStream += ssprintf( "autoSize=\"%d\" ", m_bAutoSize );
if( m_sAssociatedValue.length() ) sXMLStream += ssprintf( "associatedValue=\"%s\" ", m_sAssociatedValue.c_str() );
if( m_sAssociatedValueSet.length() ) sXMLStream += ssprintf( "associatedValueSet=\"%s\" ", m_sAssociatedValueSet.c_str() );
+ if( m_sAssociatedValueX.length() ) sXMLStream += ssprintf( "associatedValueX=\"%s\" ", m_sAssociatedValueX.c_str() );
+ if( m_sAssociatedValueY.length() ) sXMLStream += ssprintf( "associatedValueY=\"%s\" ", m_sAssociatedValueY.c_str() );
+ if( m_sxRangeMin.length() ) sXMLStream += ssprintf( "xRangeMin=\"%s\" ",m_sxRangeMin.c_str() );
+ if( m_sxRangeMax.length() ) sXMLStream += ssprintf( "xRangeMax=\"%s\" ",m_sxRangeMax.c_str() );
+ if( m_syRangeMin.length() ) sXMLStream += ssprintf( "yRangeMin=\"%s\" ",m_syRangeMin.c_str() );
+ if( m_syRangeMax.length() ) sXMLStream += ssprintf( "yRangeMax=\"%s\" ",m_syRangeMax.c_str() );
+
if( !m_pText )
m_pText->SaveToXMLTag( sXMLStream );
@@ -361,6 +376,7 @@
{
if( c == PRESS_IN )
m_bDown = true;
+
if( c == RELEASE_IN )
{
if( m_bDown )
@@ -376,6 +392,30 @@
Cu2Element::MouseAction( x, y, c, iWhichButton );
}
+int Cu2Button::MouseMotion( int x, int y, unsigned char iCurrentButtonMask, unsigned char iLastButtonMask )
+{
+ if( m_sAssociatedValueX.length() && m_bDown && x >= 0 && y >= 0 && x < GetW() && y < GetH() )
+ {
+ float fxRangeMin = atof( m_sxRangeMin.c_str() );
+ float fxRangeMax = m_sxRangeMax.length()?atof( m_sxRangeMax.c_str() ):GetW();
+
+ float fX = ( float(x) / float(GetW()-1) ) * (fxRangeMax - fxRangeMin) + fxRangeMin;
+ MESSAGEMAN.GetValue( m_sAssociatedValueX )->SetFloat( fX );
+ }
+
+ if( m_sAssociatedValueY.length() && m_bDown && x >= 0 && y >= 0 && x < GetW() && y < GetH() )
+ {
+ float fyRangeMin = atof( m_syRangeMin.c_str() );
+ float fyRangeMax = m_syRangeMax.length()?atof( m_syRangeMax.c_str() ):GetW();
+
+ float fY = ( float(y) / float(GetH()-1) ) * (fyRangeMax - fyRangeMin) + fyRangeMin;
+ MESSAGEMAN.GetValue( m_sAssociatedValueY )->SetFloat( fY );
+ }
+
+ return Cu2Element::MouseMotion( x, y, iCurrentButtonMask, iLastButtonMask );
+}
+
+
void Cu2Button::Refresh()
{
if( !m_pText )
Modified: Mercury2/modules/Cu2.h
===================================================================
--- Mercury2/modules/Cu2.h 2010-04-28 09:21:34 UTC (rev 709)
+++ Mercury2/modules/Cu2.h 2010-04-28 09:21:53 UTC (rev 710)
@@ -150,6 +150,7 @@
public:
Cu2Button();
+ virtual int MouseMotion( int x, int y, unsigned char iCurrentButtonMask, unsigned char iLastButtonMask );
virtual void MouseAction( int x, int y, Cu2Action c, int iWhichButton );
///This function gets called whenever the button is clicked, you should abstract from this.
virtual void Click( int x, int y );
@@ -172,10 +173,18 @@
private:
MString m_sAssociatedValue;
MString m_sAssociatedValueSet;
+ MString m_sAssociatedValueX;
+ MString m_sAssociatedValueY;
MString m_sMessageToSend;
MString m_sValueToSend;
MString m_sText;
+
+ MString m_sxRangeMin;
+ MString m_sxRangeMax;
+ MString m_syRangeMin;
+ MString m_syRangeMax;
+
bool m_bAutoSize;
bool m_bDown;
TextNode * m_pText;
@@ -238,6 +247,7 @@
MString m_sTitle;
};
+
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <axl...@us...> - 2010-05-16 15:29:02
|
Revision: 732
http://hgengine.svn.sourceforge.net/hgengine/?rev=732&view=rev
Author: axlecrusher
Date: 2010-05-16 15:28:56 +0000 (Sun, 16 May 2010)
Log Message:
-----------
Use indices to take advantave of degenerate triangles.
Modified Paths:
--------------
Mercury2/modules/ParticleEmitter.cpp
Mercury2/modules/ParticleEmitter.h
Modified: Mercury2/modules/ParticleEmitter.cpp
===================================================================
--- Mercury2/modules/ParticleEmitter.cpp 2010-05-06 07:11:07 UTC (rev 731)
+++ Mercury2/modules/ParticleEmitter.cpp 2010-05-16 15:28:56 UTC (rev 732)
@@ -13,13 +13,14 @@
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
ParticleBase::ParticleBase()
- :m_age(0), m_lifespan(0), m_particleVobData(NULL)
+ :m_age(0), m_lifespan(0), m_particleVobData(NULL), m_particleIndexData(NULL)
{
}
ParticleBase::~ParticleBase()
{
m_particleVobData = NULL;
+ m_particleIndexData = NULL;
}
void ParticleBase::Init()
@@ -37,28 +38,28 @@
void ParticleBase::WriteAgeToVBO()
{
- m_emitter->SetDirtyVBO();
+ m_emitter->SetDirtyVertices();
for (uint8_t i = 0; i < 4; ++i)
WriteFloatToVertices(m_age,i,3);
}
void ParticleBase::WriteLifespanToVBO()
{
- m_emitter->SetDirtyVBO();
+ m_emitter->SetDirtyVertices();
for (uint8_t i = 0; i < 4; ++i)
WriteFloatToVertices(m_lifespan,i,4);
}
void ParticleBase::WriteRand1ToVBO()
{
- m_emitter->SetDirtyVBO();
+ m_emitter->SetDirtyVertices();
for (uint8_t i = 0; i < 4; ++i)
WriteFloatToVertices(m_rand1,i,5);
}
void ParticleBase::WriteRand2ToVBO()
{
- m_emitter->SetDirtyVBO();
+ m_emitter->SetDirtyVertices();
for (uint8_t i = 0; i < 4; ++i)
WriteFloatToVertices(m_rand2,i,6);
}
@@ -84,29 +85,18 @@
m_particleVobData[i++] = 0.5; m_particleVobData[i++] = 0.5; m_particleVobData[i++] = 0;
i+=4; m_particleVobData[i++] = 1; m_particleVobData[i++] = 1; //skip color data and set U,V
-/* for (uint8_t i = 0; i < 4; ++i)
- {
- WriteFloatToVertices(0,i,0);
- WriteFloatToVertices(0,i,1);
- WriteFloatToVertices(0,i,2);
- }
-*/
- m_emitter->SetDirtyVBO();
+ for (uint8_t i = 1; i < 4; ++i)
+ m_particleIndexData[i] = m_particleIndexData[0]+i; //reconstruct indices
+
+ m_emitter->SetDirtyVertices();
+ m_emitter->SetDirtyIndices();
}
void ParticleBase::Deactivate()
{
-// m_age = 0; //doing this breaks IsActive()
-// WriteAgeToVBO();
- for (uint8_t i = 0; i < 4; ++i)
- {
- //zero vertices should enable fast empty set culling but does not work might need FBO
- WriteFloatToVertices(0,i,0);
- WriteFloatToVertices(0,i,1);
- WriteFloatToVertices(0,i,2);
- WriteFloatToVertices(0,i,3); //fake zero age
- }
- m_emitter->SetDirtyVBO();
+ for (uint8_t i = 1; i < 4; ++i)
+ m_particleIndexData[i] = m_particleIndexData[0]; //degenerate triangle renders nothing
+ m_emitter->SetDirtyIndices();
}
void ParticleBase::WriteFloatToVertices(float v, uint8_t vertexIndex, uint8_t offset)
@@ -126,8 +116,9 @@
:base(), m_maxParticles(50), m_age(0), m_emitDelay(0.1), m_lifespan(0),
m_particlesEmitted(0), m_particleMinLife(0.1), m_particleMaxLife(5),
m_particles(NULL), GenerateParticlesClbk(NULL),
- m_bufferID(0), m_dirtyVBO(false)
+ m_dirtyVBO(0)
{
+ m_bufferID[0] = 0;
m_iForcePasses = m_iForcePasses | (1<<15);
m_iForcePasses = m_iForcePasses | (1<<7);
Init();
@@ -136,7 +127,7 @@
ParticleEmitter::~ParticleEmitter()
{
- if (m_bufferID > 0) { GLCALL( glDeleteBuffersARB(1, &m_bufferID) ); }
+ if (m_bufferID[0] > 0) { GLCALL( glDeleteBuffersARB(2, m_bufferID) ); }
SAFE_DELETE_ARRAY(m_particles); //do we need to destroy each element????
SAFE_DELETE(GenerateParticlesClbk);
@@ -231,6 +222,7 @@
m_maxParticles = count;
m_vertexData.Allocate(m_maxParticles*ParticleBase::STRIDE*4);
+ m_indexData.Allocate(m_maxParticles*4);
SAFE_DELETE_ARRAY(m_particles);
// if (GenerateParticlesClbk) m_particles = (*GenerateParticlesClbk)(m_maxParticles);
@@ -246,6 +238,8 @@
ParticleBase* p = m_particles+i;
p->m_emitter = this;
p->m_particleVobData = m_vertexData.Buffer()+(ParticleBase::STRIDE*4*i);
+ p->m_particleIndexData = m_indexData.Buffer() + (4*i);
+ p->m_particleIndexData[0]=p->m_particleIndexData[1]=p->m_particleIndexData[2]=p->m_particleIndexData[3]=i*4; //initial degenerate
p->Deactivate();
// printf("addr1 %p\n", p);
m_inactive.push_back( p );
@@ -263,22 +257,26 @@
GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_CURRENT_BIT) );
GLCALL( glDisable(GL_CULL_FACE) );
- if (m_bufferID==0)
+ if (m_bufferID[0]==0)
{
- GLCALL( glGenBuffersARB(1, &m_bufferID) );
+ GLCALL( glGenBuffersARB(2, m_bufferID) );
}
- GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID) );
+ GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID[0]) );
+ GLCALL( glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_bufferID[1]) );
// GLCALL( glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0) );
MercuryVBO::SetLastRendered(this);
- if (m_dirtyVBO)
+ if (m_dirtyVBO&&0x1)
{
- m_dirtyVBO = false;
GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_vertexData.LengthInBytes(), m_vertexData.Buffer(), GL_STREAM_DRAW_ARB) );
}
-
+ if (m_dirtyVBO&&0x2)
+ {
+ GLCALL( glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_indexData.LengthInBytes(), m_indexData.Buffer(), GL_STREAM_DRAW_ARB) );
+ }
+ m_dirtyVBO = 0;
GLCALL( glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT) );
//do render stuff here
@@ -291,7 +289,9 @@
GLCALL( glVertexPointer(3, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 0*sizeof(float) ) ) );
GLCALL( glColorPointer(4, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 3*sizeof(float) ) ) );
- GLCALL( glDrawArrays(GL_QUADS, 0, m_maxParticles*4) );
+// GLCALL( glDrawArrays(GL_QUADS, 0, m_maxParticles*4) );
+// GLCALL( glDrawRangeElements( GL_QUADS, 0, m_maxParticles*4,m_maxParticles*4, GL_UNSIGNED_SHORT, NULL) );
+ GLCALL( glDrawElements(GL_QUADS,m_maxParticles*4,GL_UNSIGNED_SHORT,0) );
GLCALL( glPopClientAttrib() );
GLCALL( glPopAttrib() );
Modified: Mercury2/modules/ParticleEmitter.h
===================================================================
--- Mercury2/modules/ParticleEmitter.h 2010-05-06 07:11:07 UTC (rev 731)
+++ Mercury2/modules/ParticleEmitter.h 2010-05-16 15:28:56 UTC (rev 732)
@@ -43,6 +43,7 @@
ParticleEmitter* m_emitter;
// MercuryNode* m_particleGraph;
float* m_particleVobData; //pointer to position in VBO
+ uint16_t* m_particleIndexData; //pointer to position in index list
};
class ParticleEmitter : public MercuryNode
@@ -62,8 +63,10 @@
virtual void Render(const MercuryMatrix& matrix);
void SetMaxParticleCount(uint16_t count);
- inline void SetDirtyVBO() { m_dirtyVBO=true; }
+ inline void SetDirtyVertices() { m_dirtyVBO = m_dirtyVBO||0x1; }
+ inline void SetDirtyIndices() { m_dirtyVBO = m_dirtyVBO||0x2; }
+
static uint32_t ResetDrawnCount();
GENRTTI( ParticleEmitter );
@@ -87,9 +90,11 @@
Callback1R<uint32_t,ParticleBase*>* GenerateParticlesClbk;
AlignedBuffer<float> m_vertexData;
+ AlignedBuffer<uint16_t> m_indexData;
- unsigned int m_bufferID;
- bool m_dirtyVBO;
+ unsigned int m_bufferID[2];
+// bool m_dirtyVBO;
+ uint8_t m_dirtyVBO;
std::list< ParticleBase* > m_active, m_inactive;
// MercuryNode* m_masterParticle;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <axl...@us...> - 2010-05-22 19:12:13
|
Revision: 744
http://hgengine.svn.sourceforge.net/hgengine/?rev=744&view=rev
Author: axlecrusher
Date: 2010-05-22 19:12:07 +0000 (Sat, 22 May 2010)
Log Message:
-----------
Copy less data each render. A little faster.
Modified Paths:
--------------
Mercury2/modules/ParticleEmitter.cpp
Mercury2/modules/ParticleEmitter.h
Modified: Mercury2/modules/ParticleEmitter.cpp
===================================================================
--- Mercury2/modules/ParticleEmitter.cpp 2010-05-19 22:07:06 UTC (rev 743)
+++ Mercury2/modules/ParticleEmitter.cpp 2010-05-22 19:12:07 UTC (rev 744)
@@ -4,6 +4,7 @@
#include <MercuryVBO.h>
#include <Texture.h>
+#include <Shader.h>
#include <list>
using namespace std;
@@ -13,95 +14,71 @@
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
ParticleBase::ParticleBase()
- :m_age(0), m_lifespan(0), m_particleVobData(NULL), m_particleIndexData(NULL)
+ :m_startTime(0), m_currentTime(0), m_lifespan(0), m_particleDynamicData(NULL), m_particleIndexData(NULL)
{
}
ParticleBase::~ParticleBase()
{
- m_particleVobData = NULL;
+ m_particleDynamicData = NULL;
m_particleIndexData = NULL;
}
-void ParticleBase::Init()
+void ParticleBase::Init(float time)
{
- m_age = 0;
+ //absolute time
+ m_startTime = m_currentTime = time;
}
-void ParticleBase::Update(float dTime)
+void ParticleBase::Update(float currentTime)
{
- m_age += dTime;
- WriteAgeToVBO();
-
- if (m_age >= m_lifespan) Deactivate();
+ m_currentTime = currentTime;
+ if ( !IsActive() ) Deactivate();
}
void ParticleBase::WriteAgeToVBO()
{
- m_emitter->SetDirtyVertices();
for (uint8_t i = 0; i < 4; ++i)
- WriteFloatToVertices(m_age,i,3);
+ WriteFloatToVertices(m_startTime,i,0);
}
void ParticleBase::WriteLifespanToVBO()
{
- m_emitter->SetDirtyVertices();
for (uint8_t i = 0; i < 4; ++i)
- WriteFloatToVertices(m_lifespan,i,4);
+ WriteFloatToVertices(m_lifespan,i,1);
}
void ParticleBase::WriteRand1ToVBO()
{
- m_emitter->SetDirtyVertices();
for (uint8_t i = 0; i < 4; ++i)
- WriteFloatToVertices(m_rand1,i,5);
+ WriteFloatToVertices(m_rand1,i,2);
}
void ParticleBase::WriteRand2ToVBO()
{
- m_emitter->SetDirtyVertices();
for (uint8_t i = 0; i < 4; ++i)
- WriteFloatToVertices(m_rand2,i,6);
+ WriteFloatToVertices(m_rand2,i,3);
}
void ParticleBase::Activate()
{
-// printf("Activate\n");
- uint8_t i = 0;
-
- //upper left
- m_particleVobData[i++] = -0.5; m_particleVobData[i++] = 0.5; m_particleVobData[i++] = 0;
- i+=4; m_particleVobData[i++] = 1; m_particleVobData[i++] = 0; //skip color data and set U,V
-
- //lower left
- m_particleVobData[i++] = -0.5; m_particleVobData[i++] = -0.5; m_particleVobData[i++] = 0;
- i+=4; m_particleVobData[i++] = 0; m_particleVobData[i++] = 0; //skip color data and set U,V
-
- //lower right
- m_particleVobData[i++] = 0.5; m_particleVobData[i++] = -0.5; m_particleVobData[i++] = 0;
- i+=4; m_particleVobData[i++] = 0; m_particleVobData[i++] = 1; //skip color data and set U,V
-
- //upper right
- m_particleVobData[i++] = 0.5; m_particleVobData[i++] = 0.5; m_particleVobData[i++] = 0;
- i+=4; m_particleVobData[i++] = 1; m_particleVobData[i++] = 1; //skip color data and set U,V
-
for (uint8_t i = 1; i < 4; ++i)
m_particleIndexData[i] = m_particleIndexData[0]+i; //reconstruct indices
-
- m_emitter->SetDirtyVertices();
- m_emitter->SetDirtyIndices();
+ m_emitter->SetIndexUpdateRange(m_particleIndexData,m_particleIndexData+4);
}
void ParticleBase::Deactivate()
{
for (uint8_t i = 1; i < 4; ++i)
m_particleIndexData[i] = m_particleIndexData[0]; //degenerate triangle renders nothing
- m_emitter->SetDirtyIndices();
+ m_emitter->SetIndexUpdateRange(m_particleIndexData,m_particleIndexData+4);
}
void ParticleBase::WriteFloatToVertices(float v, uint8_t vertexIndex, uint8_t offset)
{
- *(m_particleVobData+((STRIDE*vertexIndex)+offset)) = v;
+ unsigned long o = (4*vertexIndex)+offset;
+ *(m_particleDynamicData+o) = v;
+ m_emitter->SetDynamicUpdateRange(m_particleDynamicData+o,m_particleDynamicData+o+1);
}
void ParticleBase::WriteToVBO()
@@ -116,7 +93,9 @@
:base(), m_maxParticles(50), m_age(0), m_emitDelay(0.1f), m_lifespan(0),
m_particlesEmitted(0), m_particleMinLife(0.1f), m_particleMaxLife(5.0f),
m_particles(NULL), GenerateParticlesClbk(NULL),
- m_dirtyVBO(0)
+ m_fLastD(0),m_fLastI(0),
+ m_dBegin(0), m_dEnd(0),
+ m_iBegin(0), m_iEnd(0)
{
m_bufferID[0] = 0;
m_iForcePasses = m_iForcePasses | (1<<15);
@@ -127,9 +106,9 @@
ParticleEmitter::~ParticleEmitter()
{
- if (m_bufferID[0] > 0) { GLCALL( glDeleteBuffersARB(2, m_bufferID) ); }
+ if (m_bufferID[0] > 0) { GLCALL( glDeleteBuffersARB(3, m_bufferID) ); }
- SAFE_DELETE_ARRAY(m_particles); //do we need to destroy each element????
+ SAFE_DELETE_ARRAY(m_particles);
SAFE_DELETE(GenerateParticlesClbk);
}
@@ -137,29 +116,53 @@
void ParticleEmitter::Init()
{
MercuryNode::Init();
- SAFE_DELETE_ARRAY(m_particles); //do we need to destroy each element????
+ SAFE_DELETE_ARRAY(m_particles);
SetMaxParticleCount(m_maxParticles);
}
+void ParticleEmitter::InitGeometry(float* g)
+{
+ uint8_t i = 0;
+
+ //upper left
+ g[i++] = -0.5; g[i++] = 0.5; g[i++] = 0;
+ g[i++] = 1; g[i++] = 0; //U,V
+
+ //lower left
+ g[i++] = -0.5; g[i++] = -0.5; g[i++] = 0;
+ g[i++] = 0; g[i++] = 0; //U,V
+
+ //lower right
+ g[i++] = 0.5; g[i++] = -0.5; g[i++] = 0;
+ g[i++] = 0; g[i++] = 1; //U,V
+
+ //upper right
+ g[i++] = 0.5; g[i++] = 0.5; g[i++] = 0;
+ g[i++] = 1; g[i++] = 1; //U,V
+}
+
void ParticleEmitter::Update(float dTime)
{
m_age += dTime;
+ ++m_fLastD;
+ ++m_fLastI;
+
/* create particles until we meet the total number of
particles possible in terms of the age of the emitter */
while (((m_age-(m_particlesEmitted*m_emitDelay)) > m_emitDelay) && (m_emitDelay>0))
{
// LOG.Write("Emit");
++m_particlesEmitted; //always increment even if the maximum number of particles exist
- ActivateParticle();
+ ActivateParticle(m_age);
}
list< ParticleBase* >::iterator i = m_active.begin();
while ( i!=m_active.end() )
{
ParticleBase *p = *i;
- p->Update(dTime);
+ p->Update(m_age);
if ( !p->IsActive() )
{
m_active.erase(i++); //don't invalidate iterator before incrementing it
@@ -172,30 +175,24 @@
}
}
-void ParticleEmitter::ActivateParticle()
+void ParticleEmitter::ActivateParticle(float genTime)
{
if (!m_inactive.empty())
{
ParticleBase* p = m_inactive.front();
m_inactive.pop_front();
- p->Init();
+ p->Init(genTime);
p->Activate();
p->m_lifespan = m_particleMinLife;
p->m_lifespan += (rand()%(int(m_particleMaxLife*1000) - int(m_particleMinLife*1000)))/1000.0f;
p->m_rand1 = float(rand()%100000);
p->m_rand2 = float(rand()%100000);
-// +((rand()%((m_particleMaxLife*1000)-(m_particleMinLife*1000)))/1000.0f);
+ p->WriteToVBO();
- p->WriteAgeToVBO();
- p->WriteLifespanToVBO();
- p->WriteRand1ToVBO();
- p->WriteRand2ToVBO();
-
//add to the active list
-// printf("push %p\n", p);
m_active.push_back(p);
}
}
@@ -216,14 +213,15 @@
void ParticleEmitter::SetMaxParticleCount(uint16_t count)
{
- //3 floats for position
- //1 age, 1 lifespan, 2 random
- //7 floats total per particle
+ m_maxParticles = count;
- m_maxParticles = count;
- m_vertexData.Allocate(m_maxParticles*ParticleBase::STRIDE*4);
+ m_vertexDynamicData.Allocate(m_maxParticles*4*4);
+ m_geometryData.Allocate(m_maxParticles*4*5);
m_indexData.Allocate(m_maxParticles*4);
+ for (uint16_t i = 0; i < m_maxParticles*4*5; i+=(5*4))
+ InitGeometry(m_geometryData.Buffer()+i);
+
SAFE_DELETE_ARRAY(m_particles);
// if (GenerateParticlesClbk) m_particles = (*GenerateParticlesClbk)(m_maxParticles);
m_particles = new ParticleBase[m_maxParticles];
@@ -237,7 +235,7 @@
{
ParticleBase* p = m_particles+i;
p->m_emitter = this;
- p->m_particleVobData = m_vertexData.Buffer()+(ParticleBase::STRIDE*4*i);
+ p->m_particleDynamicData = m_vertexDynamicData.Buffer()+(4*4*i);
p->m_particleIndexData = m_indexData.Buffer() + (4*i);
p->m_particleIndexData[0]=p->m_particleIndexData[1]=p->m_particleIndexData[2]=p->m_particleIndexData[3]=i*4; //initial degenerate
p->Deactivate();
@@ -252,45 +250,80 @@
SetCulled(false);
}
+void ParticleEmitter::UpdateVBO()
+{
+ if ( ( m_iBegin > 0 ) || ( m_dBegin > 0 ))
+ {
+// LOG.Write( ssprintf("%d %d",m_fLastD,m_fLastI) );
+// LOG.Write( ssprintf("%p %p, %p %p, %d %d\n", m_dBegin, m_dEnd, m_iBegin, m_iEnd, (unsigned long)m_dEnd-(unsigned long)m_dBegin, (unsigned long)m_iEnd-(unsigned long)m_iBegin) );
+ }
+
+ if ( m_dBegin > 0 )
+ {
+ unsigned long l = (unsigned long)m_dEnd-(unsigned long)m_dBegin;
+ unsigned long s = (unsigned long)m_dBegin - (unsigned long)m_vertexDynamicData.Buffer();
+ GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_vertexDynamicData.LengthInBytes(), NULL, GL_DYNAMIC_DRAW_ARB) );
+ GLCALL( glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, s, l, m_dBegin));
+ m_fLastD = 0;
+ }
+ if ( m_iBegin > 0 )
+ {
+ unsigned long l = (unsigned long)m_iEnd-(unsigned long)m_iBegin;
+ unsigned long s = (unsigned long)m_iBegin - (unsigned long)m_indexData.Buffer();
+ GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_vertexDynamicData.LengthInBytes(), NULL, GL_DYNAMIC_DRAW_ARB) );
+ GLCALL( glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, s, l, m_iBegin));
+ m_fLastI = 0;
+ }
+
+ m_dBegin = m_dEnd = m_iBegin = m_iEnd = 0;
+}
+
void ParticleEmitter::Render(const MercuryMatrix& matrix)
{
+ ShaderAttribute sa;
+ sa.type = ShaderAttribute::TYPE_FLOAT;
+ sa.value.fFloat = m_age;
+ Shader::SetAttribute("EmitterTime", sa);
+
GLCALL( glPushAttrib(GL_ENABLE_BIT|GL_CURRENT_BIT) );
GLCALL( glDisable(GL_CULL_FACE) );
if (m_bufferID[0]==0)
{
- GLCALL( glGenBuffersARB(2, m_bufferID) );
+ GLCALL( glGenBuffersARB(3, m_bufferID) );
+
+ GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID[0]) ); //geometry VBO
+ GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_geometryData.LengthInBytes(), m_geometryData.Buffer(), GL_STATIC_DRAW_ARB) );
+
+ GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID[1]) ); //dynamic data (age and randoms)
+ GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_vertexDynamicData.LengthInBytes(), m_vertexDynamicData.Buffer(), GL_DYNAMIC_DRAW_ARB) );
+
+ GLCALL( glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_bufferID[2]) );
+ GLCALL( glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_indexData.LengthInBytes(), m_indexData.Buffer(), GL_DYNAMIC_DRAW_ARB) );
+
+ m_dBegin = m_dEnd = m_iBegin = m_iEnd = 0;
}
- GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID[0]) );
- GLCALL( glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_bufferID[1]) );
-// GLCALL( glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0) );
-
MercuryVBO::SetLastRendered(this);
- if (m_dirtyVBO&&0x1)
- {
- GLCALL( glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_vertexData.LengthInBytes(), m_vertexData.Buffer(), GL_STREAM_DRAW_ARB) );
- }
- if (m_dirtyVBO&&0x2)
- {
- GLCALL( glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_indexData.LengthInBytes(), m_indexData.Buffer(), GL_STREAM_DRAW_ARB) );
- }
- m_dirtyVBO = 0;
+ GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID[0]) ); //geometry VBO contains XYZUV
+ Texture::ApplyActiveTextures(5*sizeof(float), 3*sizeof(float));
+ GLCALL( glEnableClientState(GL_VERTEX_ARRAY) );
+ GLCALL( glVertexPointer(3, GL_FLOAT, 5*sizeof(float), BUFFER_OFFSET( 0*sizeof(float) ) ) );
+
+ GLCALL( glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferID[1]) ); //dynamic data (age and randoms)
+ GLCALL( glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_bufferID[2]) );
+
+ UpdateVBO();
+
GLCALL( glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT) );
//do render stuff here
- Texture::ApplyActiveTextures(ParticleBase::STRIDE*sizeof(float), 7*sizeof(float));
- GLCALL( glEnableClientState(GL_VERTEX_ARRAY) );
GLCALL( glEnableClientState( GL_COLOR_ARRAY ) ); //used for attributes
-// GLCALL( glDisableClientState( GL_NORMAL_ARRAY ) );
- GLCALL( glVertexPointer(3, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 0*sizeof(float) ) ) );
- GLCALL( glColorPointer(4, GL_FLOAT, ParticleBase::STRIDE*sizeof(float), BUFFER_OFFSET( 3*sizeof(float) ) ) );
+ GLCALL( glColorPointer(4, GL_FLOAT, 4*sizeof(float), BUFFER_OFFSET( 0*sizeof(float) ) ) );
-// GLCALL( glDrawArrays(GL_QUADS, 0, m_maxParticles*4) );
-// GLCALL( glDrawRangeElements( GL_QUADS, 0, m_maxParticles*4,m_maxParticles*4, GL_UNSIGNED_SHORT, NULL) );
GLCALL( glDrawElements(GL_QUADS,m_maxParticles*4,GL_UNSIGNED_SHORT,0) );
GLCALL( glPopClientAttrib() );
@@ -302,6 +335,24 @@
base::Render(matrix);
}
+void ParticleEmitter::SetDynamicUpdateRange(void* begin, void* end)
+{
+ m_dBegin = m_dBegin==0?begin:m_dBegin;
+ m_dEnd = m_dEnd==0?end:m_dEnd;
+
+ m_dBegin = begin<m_dBegin?begin:m_dBegin;
+ m_dEnd = end>m_dEnd?end:m_dEnd;
+}
+
+void ParticleEmitter::SetIndexUpdateRange(void* begin, void* end)
+{
+ m_iBegin = m_iBegin==0?begin:m_iBegin;
+ m_iEnd = m_iEnd==0?end:m_iEnd;
+
+ m_iBegin = begin<m_iBegin?begin:m_iBegin;
+ m_iEnd = end>m_iEnd?end:m_iEnd;
+}
+
uint32_t ParticleEmitter::ResetDrawnCount()
{
uint32_t t = m_particlesDrawn;
@@ -309,6 +360,7 @@
return t;
}
+
uint32_t ParticleEmitter::m_particlesDrawn = 0;
/****************************************************************************
Modified: Mercury2/modules/ParticleEmitter.h
===================================================================
--- Mercury2/modules/ParticleEmitter.h 2010-05-19 22:07:06 UTC (rev 743)
+++ Mercury2/modules/ParticleEmitter.h 2010-05-22 19:12:07 UTC (rev 744)
@@ -12,23 +12,16 @@
ParticleBase();
~ParticleBase();
- virtual void Init();
virtual void Update(float dTime);
-// virtual void RecursiveRender();
-
void Activate();
void Deactivate();
void WriteToVBO();
+
+ void Init(float time);
- inline bool IsActive() const { return m_age < m_lifespan; }
-
-// GENRTTI( ParticleBase );
+ inline bool IsActive() const { return m_currentTime < m_lifespan+m_startTime; }
private:
-// CLASS_HELPERS( MercuryNode );
-
- static const uint8_t STRIDE = 9;
-
void WriteAgeToVBO();
void WriteLifespanToVBO();
void WriteRand1ToVBO();
@@ -36,13 +29,11 @@
void WriteFloatToVertices(float v, uint8_t vertexIndex, uint8_t offset);
friend class ParticleEmitter;
-// ParticleBase *m_prev, *m_next;
- float m_age;
+ float m_startTime,m_currentTime;
float m_lifespan;
float m_rand1, m_rand2;
ParticleEmitter* m_emitter;
-// MercuryNode* m_particleGraph;
- float* m_particleVobData; //pointer to position in VBO
+ float* m_particleDynamicData; //pointer to position in VBO
uint16_t* m_particleIndexData; //pointer to position in index list
};
@@ -64,19 +55,17 @@
void SetMaxParticleCount(uint16_t count);
- inline void SetDirtyVertices() { m_dirtyVBO = m_dirtyVBO||0x1; }
- inline void SetDirtyIndices() { m_dirtyVBO = m_dirtyVBO||0x2; }
+ void SetDynamicUpdateRange(void* begin, void* end);
+ void SetIndexUpdateRange(void* begin, void* end);
static uint32_t ResetDrawnCount();
GENRTTI( ParticleEmitter );
private:
-// void DestroyParticles();
- void ActivateParticle();
+ void ActivateParticle(float genTime);
+ void InitGeometry(float* g);
+ void UpdateVBO();
-// void FillUnusedParticleList(ParticleBase* p, uint32_t i);
-// void InitNewParticles(ParticleBase* p, uint32_t i, uint16_t vobStep, float* vob);
-
CLASS_HELPERS( MercuryNode );
uint32_t m_maxParticles;
@@ -89,15 +78,17 @@
ParticleBase *m_particles;
Callback1R<uint32_t,ParticleBase*>* GenerateParticlesClbk;
- AlignedBuffer<float> m_vertexData;
+ AlignedBuffer<float> m_geometryData; //xyzuv, stride 5
+ AlignedBuffer<float> m_vertexDynamicData; //1 age, 1 lifespan, 2 random, stide 4
AlignedBuffer<uint16_t> m_indexData;
- unsigned int m_bufferID[2];
-// bool m_dirtyVBO;
- uint8_t m_dirtyVBO;
+ unsigned int m_bufferID[3];
+ unsigned int m_fLastD;
+ unsigned int m_fLastI;
+ void *m_dBegin, *m_dEnd; //pointers to area of the m_vertexDynamicData that changed
+ void *m_iBegin, *m_iEnd; //pointers to area of the m_indexData that changed
std::list< ParticleBase* > m_active, m_inactive;
-// MercuryNode* m_masterParticle;
static uint32_t m_particlesDrawn;
};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|