Files
OpenSpace/modules/globebrowsing/src/skirtedgrid.cpp
Alexander Bock d7d279ea16 Happy new year
2022-01-01 12:32:55 +01:00

182 lines
7.0 KiB
C++

/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/src/skirtedgrid.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
namespace {
size_t numElements(int xSegments, int ySegments) {
return 3 * 2 * xSegments * ySegments;
}
size_t numVertices(int xSegments, int ySegments) {
return (xSegments + 1) * (ySegments + 1);
}
void validate([[maybe_unused]] int xSegments, [[maybe_unused]] int ySegments) {
ghoul_assert(
xSegments > 0 && ySegments > 0,
"Resolution must be at least 1x1. (" + std::to_string(xSegments) + ", " +
std::to_string(ySegments) + ")"
);
}
std::vector<GLushort> createElements(int xSegments, int ySegments) {
validate(xSegments, ySegments);
std::vector<GLushort> elements;
elements.reserve(numElements(xSegments + 2, ySegments + 2));
for (int y = 0; y < ySegments + 2; y++) {
for (int x = 0; x < xSegments + 2; x++) {
// x v01---v11 x ..
// | / |
// x v00---v10 x ..
//
// x x x x ..
// : : : :
const GLuint v00 = (y + 0) * (xSegments + 2 + 1) + x + 0;
const GLuint v10 = (y + 0) * (xSegments + 2 + 1) + x + 1;
const GLuint v01 = (y + 1) * (xSegments + 2 + 1) + x + 0;
const GLuint v11 = (y + 1) * (xSegments + 2 + 1) + x + 1;
// add upper triangle
elements.push_back(static_cast<GLushort>(v00));
elements.push_back(static_cast<GLushort>(v10));
elements.push_back(static_cast<GLushort>(v11));
// add lower triangle
elements.push_back(static_cast<GLushort>(v00));
elements.push_back(static_cast<GLushort>(v11));
elements.push_back(static_cast<GLushort>(v01));
}
}
return elements;
}
std::vector<glm::vec2> createTextureCoordinates(int xSegments, int ySegments) {
validate(xSegments, ySegments);
std::vector<glm::vec2> textureCoordinates;
textureCoordinates.reserve(numVertices(xSegments + 2, ySegments + 2));
for (int y = -1; y < ySegments + 2; y++) {
for (int x = -1; x < xSegments + 2; x++) {
textureCoordinates.emplace_back(
glm::clamp(
static_cast<float>(x) / static_cast<float>(xSegments),
0.f - 1.f / (2.f * xSegments),
1.f + 1.f / (2.f * xSegments)
),
glm::clamp(
static_cast<float>(y) / static_cast<float>(ySegments),
0.f - 1.f / (2.f * ySegments),
1.f + 1.f / (2.f * ySegments)
)
);
}
}
return textureCoordinates;
}
} // namespace
namespace openspace::globebrowsing {
SkirtedGrid::SkirtedGrid(unsigned int xSeg, unsigned int ySeg)
: xSegments(xSeg)
, ySegments(ySeg)
, _elementSize(static_cast<GLsizei>(numElements(xSegments + 2, ySegments + 2)))
{}
void SkirtedGrid::initializeGL() {
std::vector<GLushort> elementData = createElements(xSegments, ySegments);
struct Vertex {
GLfloat texture[2];
};
std::vector<glm::vec2> textures = createTextureCoordinates(xSegments, ySegments);
std::vector<Vertex> vertexData(textures.size());
for (size_t i = 0; i < textures.size(); ++i) {
vertexData[i].texture[0] = textures[i][0];
vertexData[i].texture[1] = textures[i][1];
}
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vertexBufferID);
glGenBuffers(1, &_elementBufferID);
// First VAO setup
glBindVertexArray(_vaoID);
// Vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glBufferData(GL_ARRAY_BUFFER,
vertexData.size() * sizeof(Vertex),
vertexData.data(),
GL_STATIC_DRAW
);
// Textures at location 1
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
// Element buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _elementBufferID);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
elementData.size() * sizeof(GLushort),
elementData.data(),
GL_STATIC_DRAW
);
glBindVertexArray(0);
ghoul_assert(
static_cast<int>(elementData.size()) == _elementSize,
"Wrong element size. The correct number is assumed in the render method"
);
}
void SkirtedGrid::deinitializeGL() {
glDeleteBuffers(1, &_vertexBufferID);
glDeleteBuffers(1, &_elementBufferID);
glDeleteVertexArrays(1, &_vaoID);
}
void SkirtedGrid::drawUsingActiveProgram() const {
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _elementBufferID);
glDrawElements(GL_TRIANGLES, _elementSize, GL_UNSIGNED_SHORT, nullptr);
glBindVertexArray(0);
}
} // namespace openspace::globebrowsing