289 lines
8.0 KiB
C++
289 lines
8.0 KiB
C++
// vertexobject.cpp
|
|
//
|
|
// Copyright (C) 2019, the Celestia Development Team
|
|
//
|
|
// VBO/VAO wrappper class. Currently GL2/GL2+VAO only.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
|
|
#include "vertexobject.h"
|
|
|
|
using namespace celestia;
|
|
|
|
namespace celgl
|
|
{
|
|
VertexObject::VertexObject(GLenum bufferType) :
|
|
m_bufferType(bufferType)
|
|
{
|
|
}
|
|
|
|
VertexObject::VertexObject(GLenum bufferType, GLsizeiptr bufferSize, GLenum streamType) :
|
|
m_bufferType(bufferType),
|
|
m_bufferSize(bufferSize),
|
|
m_streamType(streamType)
|
|
{
|
|
}
|
|
|
|
VertexObject::~VertexObject()
|
|
{
|
|
delete m_attribParams;
|
|
|
|
if (m_vaoId != 0 && gl::ARB_vertex_array_object)
|
|
glDeleteVertexArrays(1, &m_vaoId);
|
|
|
|
if (m_vboId != 0)
|
|
glDeleteBuffers(1, &m_vboId);
|
|
}
|
|
|
|
void VertexObject::bind() noexcept
|
|
{
|
|
if ((m_state & State::Initialize) != 0)
|
|
{
|
|
if (gl::ARB_vertex_array_object)
|
|
{
|
|
glGenVertexArrays(1, &m_vaoId);
|
|
glBindVertexArray(m_vaoId);
|
|
}
|
|
glGenBuffers(1, &m_vboId);
|
|
glBindBuffer(m_bufferType, m_vboId);
|
|
}
|
|
else
|
|
{
|
|
if (gl::ARB_vertex_array_object)
|
|
{
|
|
glBindVertexArray(m_vaoId);
|
|
if ((m_state & State::Update) != 0)
|
|
glBindBuffer(m_bufferType, m_vboId);
|
|
}
|
|
else
|
|
{
|
|
glBindBuffer(m_bufferType, m_vboId);
|
|
enableAttribArrays();
|
|
}
|
|
}
|
|
}
|
|
|
|
void VertexObject::bindWritable() noexcept
|
|
{
|
|
m_state |= State::Update;
|
|
bind();
|
|
}
|
|
|
|
void VertexObject::unbind() noexcept
|
|
{
|
|
if (gl::ARB_vertex_array_object)
|
|
{
|
|
if ((m_state & (State::Initialize | State::Update)) != 0)
|
|
glBindBuffer(m_bufferType, 0);
|
|
glBindVertexArray(0);
|
|
}
|
|
else
|
|
{
|
|
disableAttribArrays();
|
|
glBindBuffer(m_bufferType, 0);
|
|
}
|
|
m_state = State::NormalState;
|
|
}
|
|
|
|
bool VertexObject::allocate(const void* data) noexcept
|
|
{
|
|
glBufferData(m_bufferType, m_bufferSize, data, m_streamType);
|
|
return glGetError() != GL_NO_ERROR;
|
|
}
|
|
|
|
bool VertexObject::allocate(GLsizeiptr bufferSize, const void* data) noexcept
|
|
{
|
|
m_bufferSize = bufferSize;
|
|
return allocate(data);
|
|
}
|
|
|
|
bool VertexObject::allocate(GLenum bufferType, GLsizeiptr bufferSize, const void* data, GLenum streamType) noexcept
|
|
{
|
|
m_bufferType = bufferType;
|
|
m_bufferSize = bufferSize;
|
|
m_streamType = streamType;
|
|
return allocate(data);
|
|
}
|
|
|
|
bool VertexObject::setBufferData(const void* data, GLintptr offset, GLsizeiptr size) noexcept
|
|
{
|
|
glBufferSubData(m_bufferType, offset, size == 0 ? m_bufferSize : size, data);
|
|
return glGetError() != GL_NO_ERROR;
|
|
}
|
|
|
|
void VertexObject::draw(GLenum primitive, GLsizei count, GLint first) noexcept
|
|
{
|
|
if ((m_state & State::Initialize) != 0)
|
|
enableAttribArrays();
|
|
|
|
glDrawArrays(primitive, first, count);
|
|
}
|
|
|
|
void VertexObject::enableAttribArrays() noexcept
|
|
{
|
|
glBindBuffer(m_bufferType, m_vboId);
|
|
|
|
if (m_attrIndexes & AttrType::Vertices)
|
|
{
|
|
const auto& p = m_params[0];
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(p.count, p.type, p.stride, (GLvoid*) p.offset);
|
|
}
|
|
|
|
if (m_attrIndexes & AttrType::Normal)
|
|
{
|
|
const auto& p = m_params[1];
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glNormalPointer(p.type, p.stride, (GLvoid*) p.offset);
|
|
}
|
|
|
|
if (m_attrIndexes & AttrType::Color)
|
|
{
|
|
const auto& p = m_params[2];
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
glColorPointer(p.count, p.type, p.stride, (GLvoid*) p.offset);
|
|
}
|
|
|
|
if (m_attrIndexes & AttrType::Index)
|
|
{
|
|
const auto& p = m_params[3];
|
|
glEnableClientState(GL_INDEX_ARRAY);
|
|
glIndexPointer(p.type, p.stride, (GLvoid*) p.offset);
|
|
}
|
|
|
|
if (m_attrIndexes & AttrType::Texture)
|
|
{
|
|
const auto& p = m_params[4];
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(p.count, p.type, p.stride, (GLvoid*) p.offset);
|
|
}
|
|
|
|
if (m_attrIndexes & AttrType::EdgeFlag)
|
|
{
|
|
const auto& p = m_params[5];
|
|
glEnableClientState(GL_EDGE_FLAG_ARRAY);
|
|
glEdgeFlagPointer(p.stride, (GLvoid*) p.offset);
|
|
}
|
|
|
|
if (m_attrIndexes & AttrType::Tangent)
|
|
{
|
|
const auto& p = m_params[6];
|
|
glEnableVertexAttribArray(6);
|
|
glVertexAttribPointer(6, p.count, p.type, p.normalized, p.stride, (GLvoid*) p.offset);
|
|
}
|
|
|
|
if (m_attrIndexes & AttrType::PointSize)
|
|
{
|
|
const auto& p = m_params[7];
|
|
glEnableVertexAttribArray(7);
|
|
glVertexAttribPointer(7, p.count, p.type, p.normalized, p.stride, (GLvoid*) p.offset);
|
|
}
|
|
|
|
if (m_attribParams != nullptr)
|
|
{
|
|
for (const auto& t : *m_attribParams)
|
|
{
|
|
auto n = t.first;
|
|
auto& p = t.second;
|
|
glEnableVertexAttribArray(n);
|
|
glVertexAttribPointer(n, p.count, p.type, p.normalized, p.stride, (GLvoid*) p.offset);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VertexObject::disableAttribArrays() noexcept
|
|
{
|
|
if (m_attrIndexes & AttrType::Vertices)
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
if (m_attrIndexes & AttrType::Normal)
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
|
|
if (m_attrIndexes & AttrType::Color)
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
if (m_attrIndexes & AttrType::Index)
|
|
glDisableClientState(GL_INDEX_ARRAY);
|
|
|
|
if (m_attrIndexes & AttrType::Texture)
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
if (m_attrIndexes & AttrType::EdgeFlag)
|
|
glDisableClientState(GL_EDGE_FLAG_ARRAY);
|
|
|
|
if (m_attrIndexes & AttrType::Tangent)
|
|
glDisableVertexAttribArray(6);
|
|
|
|
if (m_attrIndexes & AttrType::PointSize)
|
|
glDisableVertexAttribArray(7);
|
|
|
|
if (m_attribParams != nullptr)
|
|
{
|
|
for (const auto& t : *m_attribParams)
|
|
glDisableVertexAttribArray(t.first);
|
|
}
|
|
|
|
glBindBuffer(m_bufferType, 0);
|
|
}
|
|
|
|
void VertexObject::setVertices(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) noexcept
|
|
{
|
|
m_attrIndexes |= AttrType::Vertices;
|
|
m_params[0] = { offset, stride, count, type, normalized };
|
|
}
|
|
|
|
void VertexObject::setNormals(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) noexcept
|
|
{
|
|
m_attrIndexes |= AttrType::Normal;
|
|
m_params[1] = { offset, stride, count, type, normalized };
|
|
}
|
|
|
|
void VertexObject::setColors(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) noexcept
|
|
{
|
|
m_attrIndexes |= AttrType::Color;
|
|
m_params[2] = { offset, stride, count, type, normalized };
|
|
}
|
|
|
|
void VertexObject::setIndexes(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) noexcept
|
|
{
|
|
m_attrIndexes |= AttrType::Index;
|
|
m_params[3] = { offset, stride, count, type, normalized };
|
|
}
|
|
|
|
void VertexObject::setTextureCoords(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) noexcept
|
|
{
|
|
m_attrIndexes |= AttrType::Texture;
|
|
m_params[4] = { offset, stride, count, type, normalized };
|
|
}
|
|
|
|
void VertexObject::setEdgeFlags(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) noexcept
|
|
{
|
|
m_attrIndexes |= AttrType::EdgeFlag;
|
|
m_params[5] = { offset, stride, count, type, normalized };
|
|
}
|
|
|
|
void VertexObject::setTangents(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) noexcept
|
|
{
|
|
m_attrIndexes |= AttrType::Tangent;
|
|
m_params[6] = { offset, stride, count, type, normalized };
|
|
}
|
|
|
|
void VertexObject::setPointSizes(GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset) noexcept
|
|
{
|
|
m_attrIndexes |= AttrType::PointSize;
|
|
m_params[7] = { offset, stride, count, type, normalized };
|
|
}
|
|
|
|
void VertexObject::setVertexAttrib(GLint location, GLint count, GLenum type, bool normalized, GLsizei stride, GLsizeiptr offset)
|
|
{
|
|
if (m_attribParams == nullptr)
|
|
m_attribParams = new std::map<GLint, PtrParams>;
|
|
|
|
PtrParams p = { offset, stride, count, type, normalized };
|
|
(*m_attribParams)[location] = p;
|
|
}
|
|
}; // namespace
|