Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 21 Oct 2009
Offline Last Active Dec 07 2013 02:17 PM

#4879209 Indoor rendering

Posted by xynapse on 01 November 2011 - 05:30 AM

As promissed i'm back with the results.

We went the Portal way, and thus a level designer places portals manually as faces, describing each portals visibility in terms of a sector it sees.

Each room is made of separate object, so when portal is placed we define which object it sees.

Posted Image

The engine itself, checks for portal that is seen in the frustum (by testing portals AABB and the frustum) and generates a list of sectors visible for the camera.

Posted Image

I think this would satisfy the requirements for this project.

Now i need to 'cut' the frustum to the portal size when iterating through.

Will of course come back after this gets implemented.

#4869716 RTS Game - The terrain approach

Posted by xynapse on 06 October 2011 - 03:16 AM

As promised i'm back with the news and a source code listing - so someone might find it useful.

First of all i'll drop the terrain class here so we all know what i am talking about.


namespace XYNAPSE

	// --[  Struct  ]---------------------------------------------------------------
	//  - Class 	:  
	//  - Prototype : struct tTerrainCell
	//  - Purpose   : This holds index buffer data per cell
	// -----------------------------------------------------------------------------
	struct tTerrainCell
		GLuint m_uiIBO;
		int       m_iIndexesCount;
		// more to come.

	class CTerrain 

			bool Create(const std::string& strFileName,  int iWidth,  int iHeight);
			void Destroy();
			void Render(const CMatrix4x4& mViewMatrix,const CMatrix4x4& mProjectionMatrix);
			void Update(const CVector3& vOriginPosition);
			int m_iHeight;
			int m_iWidth;
			int m_iVertexCount;
			int hLOD;

 			std::vector<XYN_vbo_vert>   m_vVertices;
			std::vector<tTerrainCell>   m_vCells;

			GLuint	     m_uiVAO;
			GLuint	     m_uiVBOVertices; 
			GLuint	     m_usIndices;
			CMatrix4x4     m_matModel;

			XYNAPSE::CShader	*m_pShader;

			BYTE hHeightField[1024][1024];



Terrain.cpp ( creation / render methods )

	// --[  Method  ]---------------------------------------------------------------
	//  - Class 	: CTerrain
	//  - Prototype : bool CTerrain::Create(const std::string& strFileName,  int iWidth,  int iHeight)
	//  - Purpose   : This reads in the height data from a raw file and splits the map into defined cells
	//			  	The cell size is called: iTerrainSplitCellSize
	//			  	We generate ONE single VBO that holds vertexes for the whole map
	//			  	And separate per-cell IBOs 
	//			  	So after loading we get:
	//			  	Index buffers = ( m_iHeight / iTerrainSplitCellSize ) * ( m_iWidth / iTerrainSplitCellSize )
	//			  	Vertex buffer = 1
	// -----------------------------------------------------------------------------
	bool CTerrain::Create(const std::string& strFileName,  int iWidth,  int iHeight)
		XYNAPSE::CLogger::Instance()->Write(XLOGEVENT_LOCATION,"Loading \"%s\" terrain file, width=%i height=%i.",strFileName.data(),iWidth,iHeight);

		// Load the heights to a byte array
		// If fp failed, return false.
		m_iHeight = iHeight;
		m_iWidth = iWidth;	
		FILE *fp=NULL;
		fp = fopen(strFileName.data(), "rb");
			XYNAPSE::CLogger::Instance()->Write(XLOGEVENT_LOCATION,"ERROR, Couldn't load \"%s\" terrain file, file not found.",strFileName.data());
			return false;
		// Sanity check
		size_t result;
		result = fread(hHeightField, 1, m_iWidth * m_iHeight, fp);
		if(result != (m_iWidth * m_iHeight) )
				return false;
		// Ok time to split the terrain into iTerrainSplitCellSize cells
		// Here we define the Cell Size
		int iTerrainSplitCellSize		=	16;	
		int iCellsAfterSplittingHeight	=	m_iHeight/iTerrainSplitCellSize;
		int iCellsAfterSplittingWidth	=	m_iWidth/iTerrainSplitCellSize;
		// Generate Vertex buffer
		for(int x=0;x<m_iWidth;x++)
			for(int z=0;z<m_iHeight;z++)

					     	XYN_vbo_vert newVertexData;

		// Generate separate IBO's for each cell
		for(int iCellX=0;iCellX<iCellsAfterSplittingWidth;iCellX++)
			for(int iCellZ=0;iCellZ<iCellsAfterSplittingHeight;iCellZ++)
	     		int iCellXEnd=(iCellX*iTerrainSplitCellSize)+iTerrainSplitCellSize;
				int iCellZEnd=(iCellZ*iTerrainSplitCellSize)+iTerrainSplitCellSize;
				std::vector<unsigned short> vIndices;

				for(int x=iCellX*iTerrainSplitCellSize; x < ( iCellXEnd  ); x++) 
					for(int z=iCellZ*iTerrainSplitCellSize; z < ( iCellZEnd ); z++) 
						vIndices.push_back( x * m_iWidth + z );
						vIndices.push_back( (x + 1) * m_iWidth + z);

				// Create new Cell objet
				tTerrainCell newCell;
				// Store the number of indexes for this cell	
				// Generate the IBO
				glGenBuffers( 1, &newCell.m_uiIBO);					
				glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newCell.m_uiIBO );	
				glBufferData( GL_ELEMENT_ARRAY_BUFFER,  sizeof(unsigned short) * vIndices.size(), &vIndices[0], GL_STATIC_DRAW );
				glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );	

				// Push back newly created cell to our list
				// Pop some debug note
				XYNAPSE::CLogger::Instance()->Write(XLOGEVENT_LOCATION,"Terrain debug: Cell[%i][%i] Indexes: %i\n",iCellX,iCellZ,vIndices.size());
		// Generate the VBO for the whole mesh
		glGenBuffers(1, &m_uiVBOVertices); 
		glBindBuffer(GL_ARRAY_BUFFER, m_uiVBOVertices); 
		glBufferData(GL_ARRAY_BUFFER, m_vVertices.size() * sizeof(XYN_vbo_vert), &m_vVertices[0], GL_STATIC_DRAW_ARB); 
 		glBindBuffer( GL_ARRAY_BUFFER, 0 );	
		// Set the Model matrix to 0,0,0
		// Create terrain shader for rendering tests purposes
		m_pShader	=	new XYNAPSE::CShader;
			return false;

		// All clear!
		return true;

	// --[  Method  ]---------------------------------------------------------------
	//  - Class 	: CTerrain
	//  - Prototype : void CTerrain::Render(const CMatrix4x4& mViewMatrix,const CMatrix4x4& mProjectionMatrix) 
	//  - Purpose   : Renders visible cells of the terrain that were previously 
	//			  	calculated by Update method.
	// -----------------------------------------------------------------------------
	void CTerrain::Render(const CMatrix4x4& mViewMatrix,const CMatrix4x4& mProjectionMatrix) 
		// Turn the shader on
		// Inject matrices to the shader
		m_pShader->SetMatrix4x4(m_pShader->getUniform("m_Model"),		m_matModel); 
		m_pShader->SetMatrix4x4(m_pShader->getUniform("m_View"),			mViewMatrix); 
		m_pShader->SetMatrix4x4(m_pShader->getUniform("m_Projection"),	mProjectionMatrix); 
		// Bind the VBO
		glBindBuffer(GL_ARRAY_BUFFER, m_uiVBOVertices);

		//Setup the VertexPosition
		glVertexAttribPointer(0, 3, GL_FLOAT,GL_FALSE,sizeof(XYN_vbo_vert),(char*)0);				

		//Setup the VertexNormal
		glVertexAttribPointer(1, 3, GL_FLOAT,GL_FALSE,sizeof(XYN_vbo_vert),BUFFER_OFFSET(sizeof(GLfloat)*5));

		//Setup the VertexTexCoord
		glVertexAttribPointer(2, 2, GL_FLOAT,GL_FALSE,sizeof(XYN_vbo_vert),BUFFER_OFFSET(sizeof(GLfloat)*3));     

		//Setup the VertexTangent
		glVertexAttribPointer(3, 4, GL_FLOAT,GL_FALSE,sizeof(XYN_vbo_vert),BUFFER_OFFSET(sizeof(GLfloat)*8)); 

		// Bind the selected Cell IBO
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vCells[0].m_uiIBO);
		// Draw Triangle strip

		// Boil out with the bindings
		glBindBuffer( GL_ARRAY_BUFFER, 0 );	

		// Turn the shader off


This works as it is intended to, the index buffers consist of a :

<XYNAPSE::CTerrain::Create> [2011/10/6 10:43:31] Terrain debug: Cell[0][0] Indexes: 512

512 entries for 16x16 Cell.

Rendering with strips looks promising too

Posted Image

The next thing i want to ask is the data-holding approach.

Having in mind a map like 256x256 would create :

<XYNAPSE::CTerrain::Create> [2011/10/6 11:12:15] Terrain debug: Cells created: 256

256 Index buffers.

- Now is this something that i should be worried about in future ( for example when speaking of a map like 2048 x 2048 ) ?

#4820927 Effects / Materials - Management

Posted by xynapse on 08 June 2011 - 07:31 AM

bluntman, great stuff, that's clear but i would like to have a closer look on your implementation as it looks very well prepared ( PM sent :) )

My effects manager is a class that takes care of the whole 'post processing' stuff and it is finally complete.
The name can be confusing, but it's working v.well. Effects can be managed within scripts, and the only thing left now is Materials management.
The approach i was thinking about is to have a global engine MaterialsManager class holding a list of loaded materials within.

When an object is to be loaded - it calls materialsmanager to load/parse a material file and stores a pointer to struct held in materialsmanager list.

Now when render kicks in, model calls:





// m_Model->material - pointer to a materialsmanager list entry  

EffectsManager in action.

Posted Image

Posted Image

Posted Image