2021-11-12 20:03:04 +01:00
|
|
|
#include "VertexStream.hpp"
|
|
|
|
#include "Error.hpp"
|
|
|
|
#include "Utils.hpp"
|
|
|
|
|
|
|
|
#include <glrage_gl/Utils.hpp>
|
|
|
|
#include <glrage_util/Logger.hpp>
|
|
|
|
|
|
|
|
namespace glrage {
|
|
|
|
namespace cif {
|
|
|
|
|
|
|
|
VertexStream::VertexStream()
|
|
|
|
: m_vertexBuffer(GL_ARRAY_BUFFER)
|
|
|
|
{
|
|
|
|
// bind vertex buffer
|
|
|
|
m_vertexBuffer.bind();
|
|
|
|
|
|
|
|
// define vertex formats
|
|
|
|
m_vtcFormat.bind();
|
|
|
|
m_vtcFormat.attribute(0, 3, GL_FLOAT, GL_FALSE, 40, 0);
|
|
|
|
m_vtcFormat.attribute(1, 3, GL_FLOAT, GL_FALSE, 40, 12);
|
|
|
|
m_vtcFormat.attribute(2, 4, GL_FLOAT, GL_FALSE, 40, 24);
|
|
|
|
|
|
|
|
gl::Utils::checkError(__FUNCTION__);
|
|
|
|
}
|
|
|
|
|
2021-11-14 23:59:19 +01:00
|
|
|
void VertexStream::setDelayer(std::function<BOOL(C3D_VTCF*)> delayer)
|
2021-11-12 20:03:04 +01:00
|
|
|
{
|
|
|
|
m_delayer = delayer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexStream::addPrimStrip(C3D_VSTRIP vertStrip, C3D_UINT32 numVert)
|
|
|
|
{
|
|
|
|
// note: strips are converted to lists, since they can't be properly batched
|
|
|
|
// otherwise
|
|
|
|
switch (m_vertexType) {
|
|
|
|
case C3D_EV_VTCF: {
|
|
|
|
auto vStripVtcf = reinterpret_cast<C3D_VTCF*>(vertStrip);
|
|
|
|
|
2021-11-14 23:44:59 +01:00
|
|
|
if (m_primType != C3D_EPRIM_TRI) {
|
2021-11-14 23:59:19 +01:00
|
|
|
throw Error(
|
|
|
|
"Unsupported prim type: " + std::to_string(m_primType),
|
2021-11-14 23:44:59 +01:00
|
|
|
C3D_EC_NOTIMPYET);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numVert <= 2) {
|
2021-11-12 20:03:04 +01:00
|
|
|
for (C3D_UINT32 i = 0; i < numVert; i++) {
|
|
|
|
m_vtcBuffer.push_back(vStripVtcf[i]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (C3D_UINT32 i = 2; i < numVert; i++) {
|
|
|
|
if (!m_delayer(&vStripVtcf[i - 2])) {
|
|
|
|
m_vtcBuffer.push_back(vStripVtcf[i - 2]);
|
|
|
|
m_vtcBuffer.push_back(vStripVtcf[i - 1]);
|
|
|
|
m_vtcBuffer.push_back(vStripVtcf[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw Error("Unsupported vertex type: " +
|
2021-11-14 23:59:19 +01:00
|
|
|
std::string(C3D_EVERTEX_NAMES[m_vertexType]),
|
2021-11-12 20:03:04 +01:00
|
|
|
C3D_EC_NOTIMPYET);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexStream::addPrimList(C3D_VLIST vertList, C3D_UINT32 numVert)
|
|
|
|
{
|
|
|
|
switch (m_vertexType) {
|
|
|
|
case C3D_EV_VTCF: {
|
|
|
|
// copy vertices to vertex vector buffer, then to the vertex buffer
|
|
|
|
// (OpenGL can't handle arrays of pointers)
|
|
|
|
auto vListVtcf = reinterpret_cast<C3D_VTCF**>(vertList);
|
|
|
|
|
|
|
|
if (m_primType == C3D_EPRIM_QUAD) {
|
|
|
|
// triangulate quads
|
|
|
|
for (C3D_UINT32 i = 0; i < numVert; i += 4) {
|
|
|
|
m_vtcBuffer.push_back(*vListVtcf[i + 0]);
|
|
|
|
m_vtcBuffer.push_back(*vListVtcf[i + 1]);
|
|
|
|
m_vtcBuffer.push_back(*vListVtcf[i + 3]);
|
|
|
|
|
|
|
|
m_vtcBuffer.push_back(*vListVtcf[i + 1]);
|
|
|
|
m_vtcBuffer.push_back(*vListVtcf[i + 2]);
|
|
|
|
m_vtcBuffer.push_back(*vListVtcf[i + 3]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// direct copy
|
|
|
|
for (C3D_UINT32 i = 0; i < numVert; i++) {
|
|
|
|
m_vtcBuffer.push_back(*vListVtcf[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw Error("Unsupported vertex type: " +
|
2021-11-14 23:59:19 +01:00
|
|
|
std::string(C3D_EVERTEX_NAMES[m_vertexType]),
|
2021-11-12 20:03:04 +01:00
|
|
|
C3D_EC_NOTIMPYET);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexStream::renderPrims(std::vector<C3D_VTCF> prims)
|
|
|
|
{
|
|
|
|
// bind vertex format
|
|
|
|
m_vtcFormat.bind();
|
|
|
|
|
|
|
|
// resize GPU buffer if required
|
|
|
|
size_t vertexBufferSize = sizeof(C3D_VTCF) * prims.size();
|
|
|
|
if (vertexBufferSize > m_vertexBufferSize) {
|
2021-11-14 23:59:19 +01:00
|
|
|
LOG_INFO("Vertex buffer resize: %d -> %d",
|
|
|
|
m_vertexBufferSize,
|
2021-11-12 20:03:04 +01:00
|
|
|
vertexBufferSize);
|
|
|
|
m_vertexBuffer.data(vertexBufferSize, nullptr, GL_STREAM_DRAW);
|
|
|
|
m_vertexBufferSize = vertexBufferSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
// upload vertices
|
|
|
|
m_vertexBuffer.subData(0, vertexBufferSize, &prims[0]);
|
|
|
|
|
|
|
|
// draw vertices
|
|
|
|
glDrawArrays(GLCIF_PRIM_MODES[m_primType], 0, prims.size());
|
|
|
|
|
|
|
|
// check for errors
|
|
|
|
gl::Utils::checkError(__FUNCTION__);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexStream::renderPending()
|
|
|
|
{
|
|
|
|
// only render if there's something to render
|
|
|
|
if (m_vtcBuffer.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderPrims(m_vtcBuffer);
|
|
|
|
|
|
|
|
// mark buffer as empty
|
|
|
|
m_vtcBuffer.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
C3D_EVERTEX VertexStream::vertexType()
|
|
|
|
{
|
|
|
|
return m_vertexType;
|
|
|
|
}
|
|
|
|
|
|
|
|
C3D_EPRIM VertexStream::primType()
|
|
|
|
{
|
|
|
|
return m_primType;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexStream::primType(C3D_EPRIM primType)
|
|
|
|
{
|
|
|
|
m_primType = primType;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexStream::vertexType(C3D_EVERTEX vertexType)
|
|
|
|
{
|
|
|
|
m_vertexType = vertexType;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexStream::bind()
|
|
|
|
{
|
|
|
|
m_vertexBuffer.bind();
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace cif
|
|
|
|
} // namespace glrage
|