Files
eepp/src/graphics/cvertexbuffervbo.cpp
2011-03-13 02:26:56 -03:00

320 lines
8.4 KiB
C++

#include "cvertexbuffervbo.hpp"
#include "glhelper.hpp"
#include "renderer/crenderergl3.hpp"
namespace EE { namespace Graphics {
cVertexBufferVBO::cVertexBufferVBO( const Uint32& VertexFlags, EE_DRAW_MODE DrawType, const Int32& ReserveVertexSize, const Int32& ReserveIndexSize, EE_VBO_USAGE_TYPE UsageType ) :
cVertexBuffer( VertexFlags, DrawType, ReserveVertexSize, ReserveIndexSize, UsageType ),
mCompiled( false ),
mBuffersSet( false ),
mTextured( false ),
mVAO( 0 ),
mElementHandle( 0 )
{
}
cVertexBufferVBO::~cVertexBufferVBO() {
for( Int32 i = 0; i < VERTEX_FLAGS_COUNT; i++ ) {
if( VERTEX_FLAG_QUERY( mVertexFlags, i ) ) {
glDeleteBuffersARB( 1,(GLuint *)&mArrayHandle[ i ] );
}
}
if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_USE_INDICES ) ) {
glDeleteBuffersARB( 1, (GLuint *)&mElementHandle );
}
#if !defined( EE_GLES2 ) && EE_PLATFORM != EE_PLATFORM_HAIKU
if ( GLv_3 == GLi->Version() ) {
glDeleteVertexArrays( 1, &mVAO );
}
#endif
}
void cVertexBufferVBO::Bind() {
if ( !mCompiled ) {
Compile();
if ( !mCompiled )
return;
}
SetVertexStates();
}
bool cVertexBufferVBO::Compile() {
if( mCompiled )
return false;
#if !defined( EE_GLES2 ) && EE_PLATFORM != EE_PLATFORM_HAIKU
if ( GLv_3 == GLi->Version() ) {
glGenVertexArrays( 1, &mVAO );
glBindVertexArray( mVAO );
}
#endif
GLenum usageType = GL_STATIC_DRAW;
if( mUsageType== VBO_USAGE_TYPE_DYNAMIC ) usageType = GL_DYNAMIC_DRAW;
else if( mUsageType== VBO_USAGE_TYPE_STREAM ) usageType = GL_STREAM_DRAW;
//Create the VBO vertex arrays
for( Int32 i = 0; i < VERTEX_FLAGS_COUNT; i++ ) {
if( VERTEX_FLAG_QUERY( mVertexFlags, i ) ) {
glGenBuffersARB( 1,(GLuint *)&mArrayHandle[ i ] );
glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[i] );
if ( mArrayHandle[i] ) {
if ( i != VERTEX_FLAG_COLOR )
glBufferDataARB( GL_ARRAY_BUFFER, mVertexArray[i].size() * sizeof(eeFloat), &( mVertexArray[i][0] ), usageType );
else
glBufferDataARB( GL_ARRAY_BUFFER, mColorArray.size(), &mColorArray[0], usageType );
} else {
return false;
}
}
}
glBindBuffer( GL_ARRAY_BUFFER, 0 );
//Create the VBO index array
if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_USE_INDICES ) ) {
glGenBuffersARB( 1, (GLuint *)&mElementHandle );
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, mElementHandle );
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER, GetIndexCount() * sizeof(Uint32), &mIndexArray[0], usageType );
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, 0 );
}
mCompiled = true;
mBuffersSet = false;
return true;
}
void cVertexBufferVBO::Draw() {
if ( !mCompiled )
return;
if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) {
#if !defined( EE_GLES2 ) && EE_PLATFORM != EE_PLATFORM_HAIKU
glBindVertexArray( mVAO );
#endif
if ( !mTextured ) {
GLi->Disable( GL_TEXTURE_2D );
}
}
if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_USE_INDICES ) ) {
Int32 lSize = mElemDraw;
if( mElemDraw < 0 )
lSize = GetIndexCount();
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, mElementHandle );
glDrawElements( mDrawType, lSize, GL_UNSIGNED_INT, (char*)NULL );
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, 0 );
} else {
glDrawArrays( mDrawType, 0, GetVertexCount() );
}
if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) {
if ( !mTextured ) {
GLi->Enable( GL_TEXTURE_2D );
}
}
}
void cVertexBufferVBO::SetVertexStates() {
GLint index;
#if !defined( EE_GLES2 ) && EE_PLATFORM != EE_PLATFORM_HAIKU
if ( GLv_3 == GLi->Version() ) {
if ( mBuffersSet ) {
return;
}
glBindVertexArray( mVAO );
}
#endif
/// POSITION
if ( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_POSITION ) ) {
GLi->EnableClientState( GL_VERTEX_ARRAY );
glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[ VERTEX_FLAG_POSITION ] );
#ifdef EE_GL3_ENABLED
if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) {
index = GLi->GetRendererGL3()->GetStateIndex( EEGL_VERTEX_ARRAY );
if ( -1 != index ) {
glVertexAttribPointerARB( index, eeVertexElements[ VERTEX_FLAG_POSITION ], GL_FLOAT, GL_FALSE, 0, 0 );
}
}
else
#endif
{
GLi->VertexPointer( eeVertexElements[ VERTEX_FLAG_POSITION ], GL_FLOAT, 0, (char*)NULL, 0 );
}
} else {
GLi->DisableClientState( GL_VERTEX_ARRAY );
}
/// COLOR
if ( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_COLOR ) ) {
GLi->EnableClientState( GL_COLOR_ARRAY );
glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[ VERTEX_FLAG_COLOR ] );
#ifdef EE_GL3_ENABLED
if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) {
index = GLi->GetRendererGL3()->GetStateIndex( EEGL_COLOR_ARRAY );
if ( -1 != index )
glVertexAttribPointerARB( index, eeVertexElements[ VERTEX_FLAG_COLOR ], GL_UNSIGNED_BYTE, GL_TRUE, 0, 0 );
}
else
#endif
{
GLi->ColorPointer( eeVertexElements[ VERTEX_FLAG_COLOR ], GL_UNSIGNED_BYTE, 0, (char*)NULL, 0 );
}
} else {
GLi->DisableClientState( GL_COLOR_ARRAY );
}
/// TEXTURES
if ( GLi->IsExtension( EEGL_ARB_multitexture ) ) {
for ( Int32 i = 0; i < EE_MAX_TEXTURE_UNITS; i++ ) {
if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_TEXTURE0 + i ) ) {
GLi->ClientActiveTexture( GL_TEXTURE0 + i );
GLi->EnableClientState( GL_TEXTURE_COORD_ARRAY );
glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[ VERTEX_FLAG_TEXTURE0 + i ] );
#ifdef EE_GL3_ENABLED
if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) {
index = GLi->GetRendererGL3()->GetStateIndex( EEGL_TEXTURE_COORD_ARRAY );
if ( -1 != index && 0 == i )
glVertexAttribPointerARB( index, eeVertexElements[ VERTEX_FLAG_TEXTURE0 + i ], GL_FLOAT, GL_FALSE, 0, 0 );
}
else
#endif
{
GLi->TexCoordPointer( eeVertexElements[ VERTEX_FLAG_TEXTURE0 + i ], GL_FLOAT, 0, (char*)NULL, 0 );
}
mTextured = true;
} else {
GLi->DisableClientState( GL_TEXTURE_COORD_ARRAY );
GLi->Disable( GL_TEXTURE_2D );
mTextured = false;
break;
}
}
} else {
if ( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_TEXTURE0 ) ) {
GLi->EnableClientState( GL_TEXTURE_COORD_ARRAY );
glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[ VERTEX_FLAG_TEXTURE0 ] );
#ifdef EE_GL3_ENABLED
if ( GLv_3 == GLi->Version() || GLv_ES2 == GLi->Version() ) {
index = GLi->GetRendererGL3()->GetStateIndex( EEGL_TEXTURE_COORD_ARRAY );
if ( -1 != index )
glVertexAttribPointerARB( index, eeVertexElements[ VERTEX_FLAG_TEXTURE0 ], GL_FLOAT, GL_FALSE, 0, 0 );
}
else
#endif
{
GLi->TexCoordPointer( eeVertexElements[ VERTEX_FLAG_TEXTURE0 ], GL_FLOAT, 0, (char*)NULL, 0 );
}
mTextured = true;
} else {
GLi->Disable( GL_TEXTURE_2D );
GLi->DisableClientState( GL_TEXTURE_COORD_ARRAY );
mTextured = false;
}
}
GLi->ActiveTexture( GL_TEXTURE0 );
GLi->ClientActiveTexture( GL_TEXTURE0 );
glBindBufferARB( GL_ARRAY_BUFFER, 0 );
mBuffersSet = true;
}
void cVertexBufferVBO::Update( const Uint32& Types, bool Indices ) {
GLenum usageType = GL_STATIC_DRAW;
if( mUsageType== VBO_USAGE_TYPE_DYNAMIC ) usageType = GL_DYNAMIC_DRAW;
else if( mUsageType== VBO_USAGE_TYPE_STREAM ) usageType = GL_STREAM_DRAW;
for( Int32 i = 0; i < VERTEX_FLAGS_COUNT; i++ ) {
if ( VERTEX_FLAG_QUERY( mVertexFlags, i ) && VERTEX_FLAG_QUERY( Types, i ) ) {
glBindBufferARB( GL_ARRAY_BUFFER, mArrayHandle[i] );
if ( mArrayHandle[i] ) {
if ( i != VERTEX_FLAG_COLOR )
glBufferDataARB( GL_ARRAY_BUFFER, mVertexArray[i].size() * sizeof(eeFloat), &( mVertexArray[i][0] ), usageType );
else
glBufferDataARB( GL_ARRAY_BUFFER, mColorArray.size(), &mColorArray[0], usageType );
}
}
}
glBindBuffer( GL_ARRAY_BUFFER, 0 );
if( VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_USE_INDICES ) && Indices ) {
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, mElementHandle );
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER, GetIndexCount() * sizeof(Uint32), &mIndexArray[0], usageType );
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, 0 );
}
mBuffersSet = false;
}
void cVertexBufferVBO::Reload() {
mCompiled = false;
mBuffersSet = false;
Compile();
}
void cVertexBufferVBO::Unbind() {
#ifdef EE_GL3_ENABLED
if ( GLv_3 == GLi->Version() ) {
GLi->GetRendererGL3()->BindGlobalVAO();
}
else
#endif
{
if( !VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_POSITION ) ) {
GLi->EnableClientState( GL_VERTEX_ARRAY );
}
if( !VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_COLOR ) ) {
GLi->EnableClientState( GL_COLOR_ARRAY );
}
if( !VERTEX_FLAG_QUERY( mVertexFlags, VERTEX_FLAG_TEXTURE0 ) ) {
GLi->Enable( GL_TEXTURE_2D );
GLi->EnableClientState( GL_TEXTURE_COORD_ARRAY );
}
}
}
}}