ULRE/inc/hgl/graph/VertexBuffer.h

925 lines
31 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef HGL_VERTEX_BUFFER_OBJECT_INCLUDE
#define HGL_VERTEX_BUFFER_OBJECT_INCLUDE
#include<hgl/type/Color3f.h>
#include<hgl/type/Color4f.h>
#include<hgl/type/RectScope.h>
// #include<hgl/type/BaseString.h>
#include<hgl/graph/VertexBufferBase.h>
//#include<hgl/LogInfo.h>
#include<GLEWCore/glew.h>
namespace hgl
{
namespace graph
{
class VertexBufferControl;
/**
* 顶点属性数据实际模板
*/
template<typename T,int C> class VertexBuffer:public VertexBufferBase
{
protected:
T *mem_type; ///<符合当前类型的地址
T *access; ///<当前访问地址
T *start; ///<访问起始地址
public:
VertexBuffer(int _size,const T *_data=nullptr,uint level=GL_STATIC_DRAW):VertexBufferBase(level,C*_size*sizeof(T))
{
dc_num=C;
count=_size;
mem_type=(T *)GetData();
access=0;
start=0;
if(_data)
memcpy(mem_type,_data,bytes);
}
virtual ~VertexBuffer()=default;
int GetDataBytes()const
{
return sizeof(T);
}
void SetCount(int _count)
{
count=_count;
SetDataSize(_count*C*sizeof(T));
mem_type=(T *)GetData();
access=0;
start=0;
}
/**
* 取得数据区地址
* @param offset 从第几个数据开始访问
* @return 访问地址
*/
T *Get(int offset=0)
{
if(!mem_type||offset>=count)
{
// LOG_HINT(OS_TEXT("VertexBuffer::Get() out,offset:")+OSString(offset));
return(nullptr);
}
return mem_type+offset*C;
}
/**
* 开始访问数据区
* @param offset 从第几个数据开始访问
* @return 访问地址
*/
void *Begin(int offset=0)
{
if(access)
{
// LOG_HINT(OS_TEXT("VertexBuffer::Begin() access!=0,offset:")+OSString(offset));
return(nullptr);
}
access=Get(offset);
if(access)
start=access;
return access;
}
/**
* 结束访问
*/
void End()
{
ChangeVertexBuffer( ((char *)start )-((char *)mem_type),
((char *)access)-((char *)start),
start);
access=nullptr;
start=nullptr;
}
/**
* 写入指定数量的数据
* @param vp 数据指针
* @param number 数据数量
*/
bool WriteData(const T *vp,const int number)
{
if(!this->access||this->access+C*number>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer::Write(const T *,number) out,number:")+OSString(number));
return(false);
}
memcpy(access,vp,C*number*sizeof(T));
access+=C*number;
return(true);
}
};//class VertexBuffer
/**
* 一元数据缓冲区
*/
template<typename T> class VertexBuffer1:public VertexBuffer<T,1>
{
public:
using VertexBuffer<T,1>::VertexBuffer;
virtual ~VertexBuffer1()=default;
uint GetDataType()const;
bool Write(const T v1)
{
if(!this->access||this->access+1>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer1::Write(const T) out"));
return(false);
}
*this->access++=v1;
return(true);
}
/**
* 将一个值重复多次写入缓冲区
* @param v 值
* @param count 写入数量
*/
bool Write(const T v,const int count)
{
if(!this->access||this->access+count>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer1::Write(const T,")+OSString(count)+OS_TEXT(") out"));
return(false);
}
hgl_set(this->access,v,count);
this->access+=count;
return(true);
}
};//class VertexBuffer1
/**
* 二元数据缓冲区
*/
template<typename T> class VertexBuffer2:public VertexBuffer<T,2>
{
public:
using VertexBuffer<T,2>::VertexBuffer;
virtual ~VertexBuffer2()=default;
uint GetDataType()const;
bool Write(const T v1,const T v2)
{
if(!this->access||this->access+2>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer2::Write(const T ,const T) out"));
return(false);
}
*this->access++=v1;
*this->access++=v2;
return(true);
}
bool Write(const T *v)
{
if(!this->access||this->access+2>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer2::Write(T *) out"));
return(false);
}
*this->access++=*v++;
*this->access++=*v;
return(true);
}
bool Write(const Vector2f &v)
{
if(!this->access||this->access+2>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer2::Write(vec2 &) out"));
return(false);
}
*this->access++=v.x;
*this->access++=v.y;
return(true);
}
/**
* 将一个值重复多次写入缓冲区
* @param v 值
* @param count 写入数量
*/
bool Write(const Vector2f &v,const int count)
{
if(!this->access||this->access+(count<<1)>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer1::Write(const Vector2f &,")+OSString(count)+OS_TEXT(") out"));
return(false);
}
for(int i=0;i<count;i++)
{
*this->access++=v.x;
*this->access++=v.y;
}
return(true);
}
bool WriteLine(const T start_x,const T start_y,const T end_x,const T end_y)
{
if(!this->access||this->access+4>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer2::WriteLine(T,T,T,T) out"));
return(false);
}
*this->access++=start_x;
*this->access++=start_y;
*this->access++=end_x;
*this->access++=end_y;
return(true);
}
bool WriteLine(const Vector2f &start,const Vector2f &end)
{
if(!this->access||this->access+4>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer2::WriteLine(vec2,vec2) out"));
return(false);
}
*this->access++=start.x;
*this->access++=start.y;
*this->access++=end.x;
*this->access++=end.y;
return(true);
}
/**
* 写入2D三角形
*/
bool WriteTriangle(const Vector2f &v1,const Vector2f &v2,const Vector2f &v3)
{
if(!this->access||this->access+6>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer2::WriteTriangle(vec2,vec2,vec2) out"));
return(false);
}
*this->access++=v1.x;
*this->access++=v1.y;
*this->access++=v2.x;
*this->access++=v2.y;
*this->access++=v3.x;
*this->access++=v3.y;
return(true);
}
/**
* 写入2D三角形
*/
bool WriteTriangle(const Vector2f *v)
{
if(!this->access||this->access+6>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer2::WriteTriangle(vec2 *) out"));
return(false);
}
*this->access++=v->x;
*this->access++=v->y;
++v;
*this->access++=v->x;
*this->access++=v->y;
++v;
*this->access++=v->x;
*this->access++=v->y;
return(true);
}
/**
* 写入2D四边形坐标数据
*/
bool WriteQuad(const Vector2f &lt,const Vector2f &rt,const Vector2f &rb,const Vector2f &lb)
{
if(WriteTriangle(lt,lb,rb))
if(WriteTriangle(lt,rb,rt))
return(true);
// LOG_HINT(OS_TEXT("VertexBuffer2::WriteQuad(vec2 &,vec2 &,vec2 &,vec2 &) error"));
return(false);
}
/**
* 写入2D矩形两个三角形坐标数据
*/
bool WriteRect(const T left,const T top,const T width,const T height)
{
const Vector2f lt(left ,top);
const Vector2f rt(left+width,top);
const Vector2f rb(left+width,top+height);
const Vector2f lb(left ,top+height);
return WriteQuad(lt,rt,rb,lb);
}
};//class VertexBuffer2
/**
* 三元数据缓冲区
*/
template<typename T> class VertexBuffer3:public VertexBuffer<T,3>
{
public:
using VertexBuffer<T,3>::VertexBuffer;
virtual ~VertexBuffer3()=default;
uint GetDataType()const;
/**
* 计算绑定盒
* @param min_vertex 最小值坐标
* @param max_vertex 最大值坐标
*/
template<typename V>
void GetBoundingBox(V &min_vertex,V &max_vertex)
{
T *p=this->mem_type;
//先以corner为最小值,length为最大值求取最小最大值
min_vertex.x=*p++;
min_vertex.y=*p++;
min_vertex.z=*p++;
max_vertex=min_vertex;
for(int i=1;i<this->count;i++)
{
if(*p<min_vertex.x)min_vertex.x=*p;
if(*p>max_vertex.x)max_vertex.x=*p;
++p;
if(*p<min_vertex.y)min_vertex.y=*p;
if(*p>max_vertex.y)max_vertex.y=*p;
++p;
if(*p<min_vertex.z)min_vertex.z=*p;
if(*p>max_vertex.z)max_vertex.z=*p;
++p;
}
}
bool Write(const T v1,const T v2,const T v3)
{
if(!this->access||this->access+3>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::Write(T,T,T) out"));
return(false);
}
*this->access++=v1;
*this->access++=v2;
*this->access++=v3;
return(true);
}
bool Write(const T *v)
{
if(!this->access||this->access+3>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::Write(T *) out"));
return(false);
}
*this->access++=*v++;
*this->access++=*v++;
*this->access++=*v;
return(true);
}
bool Write(const Vector3f &v)
{
if(!this->access||this->access+3>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::Write(vec3 &) out"));
return(false);
}
*this->access++=v.x;
*this->access++=v.y;
*this->access++=v.z;
return(true);
}
bool Write(const Vector4f &v)
{
if(!this->access||this->access+3>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::Write(vec4 &) out"));
return(false);
}
*this->access++=v.x;
*this->access++=v.y;
*this->access++=v.z;
return(true);
}
/**
* 将一个值重复多次写入缓冲区
* @param v 值
* @param count 写入数量
*/
bool Write(const Vector3f &v,const int count)
{
if(!this->access||this->access+(count*3)>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::Write(const Vector3f,")+OSString(count)+OS_TEXT(") out"));
return(false);
}
for(int i=0;i<count;i++)
{
*this->access++=v.x;
*this->access++=v.y;
*this->access++=v.z;
}
return(true);
}
bool Write(const Color3f &v)
{
if(!this->access||this->access+3>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::Write(color3f &) out"));
return(false);
}
*this->access++=v.r;
*this->access++=v.g;
*this->access++=v.b;
return(true);
}
bool WriteLine(const T start_x,const T start_y,const T start_z,const T end_x,const T end_y,const T end_z)
{
if(!this->access||this->access+6>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::WriteLine(T,T,T,T,T,T) out"));
return(false);
}
*this->access++=start_x;
*this->access++=start_y;
*this->access++=start_z;
*this->access++=end_x;
*this->access++=end_y;
*this->access++=end_z;
return(true);
}
bool WriteLine(const Vector3f &start,const Vector3f &end)
{
if(!this->access||this->access+6>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::WriteLine(vec3,vec3) out"));
return(false);
}
*this->access++=start.x;
*this->access++=start.y;
*this->access++=start.z;
*this->access++=end.x;
*this->access++=end.y;
*this->access++=end.z;
return(true);
}
/**
* 写入3D三角形
*/
bool WriteTriangle(const Vector3f &v1,const Vector3f &v2,const Vector3f &v3)
{
if(!this->access||this->access+9>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::WriteTriangle(vec3,vec3,vec3) out"));
return(false);
}
*this->access++=v1.x;
*this->access++=v1.y;
*this->access++=v1.z;
*this->access++=v2.x;
*this->access++=v2.y;
*this->access++=v2.z;
*this->access++=v3.x;
*this->access++=v3.y;
*this->access++=v3.z;
return(true);
}
/**
* 写入3D三角形
*/
bool WriteTriangle(const Vector3f *v)
{
if(!this->access||this->access+9>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer3::WriteTriangle(vec3 *) out"));
return(false);
}
*this->access++=v->x;
*this->access++=v->y;
*this->access++=v->z;
++v;
*this->access++=v->x;
*this->access++=v->y;
*this->access++=v->z;
++v;
*this->access++=v->x;
*this->access++=v->y;
*this->access++=v->z;
return(true);
}
/**
* 写入3D四边形坐标数据
*/
bool WriteQuad(const Vector3f &lt,const Vector3f &rt,const Vector3f &rb,const Vector3f &lb)
{
if(WriteTriangle(lt,lb,rb))
if(WriteTriangle(lt,rb,rt))
return(true);
// LOG_HINT(OS_TEXT("VertexBuffer3::WriteQuad(vec3 &,vec3 &,vec3 &,vec3 &) error"));
return(false);
}
};//class VertexBuffer3
/**
* 四元数据缓冲区
*/
template<typename T> class VertexBuffer4:public VertexBuffer<T,4>
{
public:
using VertexBuffer<T,4>::VertexBuffer;
virtual ~VertexBuffer4()=default;
uint GetDataType()const;
/**
* 计算绑定盒
* @param min_vertex 最小值坐标
* @param max_vertex 最大值坐标
*/
template<typename V>
void GetBoundingBox(V &min_vertex,V &max_vertex)
{
T *p=this->mem_type;
//先以corner为最小值,length为最大值求取最小最大值
min_vertex.x=*p++;
min_vertex.y=*p++;
min_vertex.z=*p++;
max_vertex=min_vertex;
for(int i=1;i<this->count;i++)
{
if(*p<min_vertex.x)min_vertex.x=*p;
if(*p>max_vertex.x)max_vertex.x=*p;
++p;
if(*p<min_vertex.y)min_vertex.y=*p;
if(*p>max_vertex.y)max_vertex.y=*p;
++p;
if(*p<min_vertex.z)min_vertex.z=*p;
if(*p>max_vertex.z)max_vertex.z=*p;
++p;
}
}
bool Write(const T v1,const T v2,const T v3,const T v4)
{
if(!this->access||this->access+4>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::Write(T,T,T,T) out"));
return(false);
}
*this->access++=v1;
*this->access++=v2;
*this->access++=v3;
*this->access++=v4;
return(true);
}
bool Write(const T *v)
{
if(!this->access||this->access+4>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::Write(T *) out"));
return(false);
}
*this->access++=*v++;
*this->access++=*v++;
*this->access++=*v++;
*this->access++=*v;
return(true);
}
bool Write(const Vector4f &v)
{
if(!this->access||this->access+4>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::Write(color4 &) out"));
return(false);
}
*this->access++=v.x;
*this->access++=v.y;
*this->access++=v.z;
*this->access++=v.w;
return(true);
}
bool Write(const Color4f &v)
{
if(!this->access||this->access+4>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::Write(color4 &) out"));
return(false);
}
*this->access++=v.r;
*this->access++=v.g;
*this->access++=v.b;
*this->access++=v.a;
return(true);
}
/**
* 将一个值重复多次写入缓冲区
* @param v 值
* @param count 写入数量
*/
bool Write(const Vector4f &v,const int count)
{
if(!this->access||this->access+(count<<2)>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::Write(const Vector4f,")+OSString(count)+OS_TEXT(") out"));
return(false);
}
for(int i=0;i<count;i++)
{
*this->access++=v.x;
*this->access++=v.y;
*this->access++=v.z;
*this->access++=v.w;
}
return(true);
}
bool WriteLine(const T start_x,const T start_y,const T start_z,const T end_x,const T end_y,const T end_z)
{
if(!this->access||this->access+8>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::WriteLine(T,T,T,T,T,T) out"));
return(false);
}
*this->access++=start_x;
*this->access++=start_y;
*this->access++=start_z;
*this->access++=1.0f;
*this->access++=end_x;
*this->access++=end_y;
*this->access++=end_z;
*this->access++=1.0f;
return(true);
}
bool WriteLine(const Vector3f &start,const Vector3f &end)
{
if(!this->access||this->access+8>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::WriteLine(vec3,vec3) out"));
return(false);
}
*this->access++=start.x;
*this->access++=start.y;
*this->access++=start.z;
*this->access++=1.0f;
*this->access++=end.x;
*this->access++=end.y;
*this->access++=end.z;
*this->access++=1.0f;
return(true);
}
/**
* 写入3D三角形
*/
bool WriteTriangle(const Vector3f &v1,const Vector3f &v2,const Vector3f &v3)
{
if(!this->access||this->access+12>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::WriteTriangle(vec3,vec3,vec3) out"));
return(false);
}
*this->access++=v1.x;
*this->access++=v1.y;
*this->access++=v1.z;
*this->access++=1.0f;
*this->access++=v2.x;
*this->access++=v2.y;
*this->access++=v2.z;
*this->access++=1.0f;
*this->access++=v3.x;
*this->access++=v3.y;
*this->access++=v3.z;
*this->access++=1.0f;
return(true);
}
/**
* 写入3D三角形
*/
bool WriteTriangle(const Vector3f *v)
{
if(!this->access||this->access+12>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::WriteTriangle(vec3 *) out"));
return(false);
}
*this->access++=v->x;
*this->access++=v->y;
*this->access++=v->z;
*this->access++=1.0f;
++v;
*this->access++=v->x;
*this->access++=v->y;
*this->access++=v->z;
*this->access++=1.0f;
++v;
*this->access++=v->x;
*this->access++=v->y;
*this->access++=v->z;
*this->access++=1.0f;
return(true);
}
/**
* 写入2D矩形,注:这个函数会依次写入Left,Top,Width,Height四个值
*/
template<typename V>
bool WriteRectangle2D(const RectScope2<V> &rect)
{
if(!this->access||this->access+4>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::WriteRectangle2D(RectScope2 ) out"));
return(false);
}
*this->access++=rect.Left;
*this->access++=rect.Top;
*this->access++=rect.Width;
*this->access++=rect.Height;
return(true);
}
/**
* 写入2D矩形,注:这个函数会依次写入Left,Top,Width,Height四个值
*/
template<typename V>
bool WriteRectangle2D(const RectScope2<V> *rect,const int count)
{
if(!this->access||this->access+(4*count)>this->mem_end)
{
// LOG_HINT(OS_TEXT("VertexBuffer4::WriteRectangle2D(RectScope2 *,count) out"));
return(false);
}
for(int i=0;i<count;i++)
{
*this->access++=rect->Left;
*this->access++=rect->Top;
*this->access++=rect->Width;
*this->access++=rect->Height;
++rect;
}
return(true);
}
};//class VertexBuffer4
//缓冲区具体数据类型定义
typedef VertexBuffer1<int8 > VB1i8 ,VB1b; template<> inline uint VertexBuffer1<int8 >::GetDataType()const{return GL_BYTE; }
typedef VertexBuffer1<int16 > VB1i16 ,VB1s; template<> inline uint VertexBuffer1<int16 >::GetDataType()const{return GL_SHORT; }
typedef VertexBuffer1<int32 > VB1i32 ,VB1i; template<> inline uint VertexBuffer1<int32 >::GetDataType()const{return GL_INT; }
typedef VertexBuffer1<uint8 > VB1u8 ,VB1ub; template<> inline uint VertexBuffer1<uint8 >::GetDataType()const{return GL_UNSIGNED_BYTE; }
typedef VertexBuffer1<uint16> VB1u16 ,VB1us; template<> inline uint VertexBuffer1<uint16 >::GetDataType()const{return GL_UNSIGNED_SHORT;}
typedef VertexBuffer1<uint32> VB1u32 ,VB1ui; template<> inline uint VertexBuffer1<uint32 >::GetDataType()const{return GL_UNSIGNED_INT; }
typedef VertexBuffer1<float > VB1f; template<> inline uint VertexBuffer1<float >::GetDataType()const{return GL_FLOAT; }
typedef VertexBuffer1<double> VB1d; template<> inline uint VertexBuffer1<double >::GetDataType()const{return GL_DOUBLE; }
typedef VertexBuffer2<int8 > VB2i8 ,VB2b; template<> inline uint VertexBuffer2<int8 >::GetDataType()const{return GL_BYTE; }
typedef VertexBuffer2<int16 > VB2i16 ,VB2s; template<> inline uint VertexBuffer2<int16 >::GetDataType()const{return GL_SHORT; }
typedef VertexBuffer2<int32 > VB2i32 ,VB2i; template<> inline uint VertexBuffer2<int32 >::GetDataType()const{return GL_INT; }
typedef VertexBuffer2<uint8 > VB2u8 ,VB2ub; template<> inline uint VertexBuffer2<uint8 >::GetDataType()const{return GL_UNSIGNED_BYTE; }
typedef VertexBuffer2<uint16> VB2u16 ,VB2us; template<> inline uint VertexBuffer2<uint16 >::GetDataType()const{return GL_UNSIGNED_SHORT;}
typedef VertexBuffer2<uint32> VB2u32 ,VB2ui; template<> inline uint VertexBuffer2<uint32 >::GetDataType()const{return GL_UNSIGNED_INT; }
typedef VertexBuffer2<float > VB2f; template<> inline uint VertexBuffer2<float >::GetDataType()const{return GL_FLOAT; }
typedef VertexBuffer2<double> VB2d; template<> inline uint VertexBuffer2<double >::GetDataType()const{return GL_DOUBLE; }
typedef VertexBuffer3<int8 > VB3i8 ,VB3b; template<> inline uint VertexBuffer3<int8 >::GetDataType()const{return GL_BYTE; }
typedef VertexBuffer3<int16 > VB3i16 ,VB3s; template<> inline uint VertexBuffer3<int16 >::GetDataType()const{return GL_SHORT; }
typedef VertexBuffer3<int32 > VB3i32 ,VB3i; template<> inline uint VertexBuffer3<int32 >::GetDataType()const{return GL_INT; }
typedef VertexBuffer3<uint8 > VB3u8 ,VB3ub; template<> inline uint VertexBuffer3<uint8 >::GetDataType()const{return GL_UNSIGNED_BYTE; }
typedef VertexBuffer3<uint16> VB3u16 ,VB3us; template<> inline uint VertexBuffer3<uint16 >::GetDataType()const{return GL_UNSIGNED_SHORT;}
typedef VertexBuffer3<uint32> VB3u32 ,VB3ui; template<> inline uint VertexBuffer3<uint32 >::GetDataType()const{return GL_UNSIGNED_INT; }
typedef VertexBuffer3<float > VB3f; template<> inline uint VertexBuffer3<float >::GetDataType()const{return GL_FLOAT; }
typedef VertexBuffer3<double> VB3d; template<> inline uint VertexBuffer3<double >::GetDataType()const{return GL_DOUBLE; }
typedef VertexBuffer4<int8 > VB4i8 ,VB4b; template<> inline uint VertexBuffer4<int8 >::GetDataType()const{return GL_BYTE; }
typedef VertexBuffer4<int16 > VB4i16 ,VB4s; template<> inline uint VertexBuffer4<int16 >::GetDataType()const{return GL_SHORT; }
typedef VertexBuffer4<int32 > VB4i32 ,VB4i; template<> inline uint VertexBuffer4<int32 >::GetDataType()const{return GL_INT; }
typedef VertexBuffer4<uint8 > VB4u8 ,VB4ub; template<> inline uint VertexBuffer4<uint8 >::GetDataType()const{return GL_UNSIGNED_BYTE; }
typedef VertexBuffer4<uint16> VB4u16 ,VB4us; template<> inline uint VertexBuffer4<uint16 >::GetDataType()const{return GL_UNSIGNED_SHORT;}
typedef VertexBuffer4<uint32> VB4u32 ,VB4ui; template<> inline uint VertexBuffer4<uint32 >::GetDataType()const{return GL_UNSIGNED_INT; }
typedef VertexBuffer4<float > VB4f; template<> inline uint VertexBuffer4<float >::GetDataType()const{return GL_FLOAT; }
typedef VertexBuffer4<double> VB4d; template<> inline uint VertexBuffer4<double >::GetDataType()const{return GL_DOUBLE; }
}//namespace graph
}//namespace hgl
#endif//HGL_VERTEX_BUFFER_OBJECT_INCLUDE