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

189 lines
6.5 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 <openspace/util/blockplaneintersectiongeometry.h>
#include <ghoul/logging/logmanager.h>
#include <algorithm>
namespace {
constexpr const char* _loggerCat = "BlockPlaneIntersectionGeometry";
} // namespace
namespace openspace {
BlockPlaneIntersectionGeometry::BlockPlaneIntersectionGeometry(glm::vec3 blockSize,
glm::vec3 planeNormal,
float planeDistance)
: _size(blockSize)
, _normal(planeNormal)
, _planeDistance(planeDistance)
{}
BlockPlaneIntersectionGeometry::~BlockPlaneIntersectionGeometry() {
glDeleteBuffers(1, &_vBufferId);
glDeleteVertexArrays(1, &_vaoId);
}
void BlockPlaneIntersectionGeometry::setBlockSize(glm::vec3 size) {
_size = std::move(size);
updateVertices();
}
void BlockPlaneIntersectionGeometry::setPlane(glm::vec3 normal, float distance) {
_normal = glm::normalize(normal);
_planeDistance = distance;
updateVertices();
}
void BlockPlaneIntersectionGeometry::updateVertices() {
_vertices.clear();
const int cornersInLines[24] = {
0, 1,
1, 5,
5, 4,
4, 0,
2, 3,
3, 7,
7, 6,
6, 2,
0, 2,
1, 3,
5, 7,
4, 6
};
const glm::vec3 halfSize = _size * 0.5f;
glm::vec3 intersections[12];
std::fill(std::begin(intersections), std::end(intersections), glm::vec3(0.f));
int nIntersections = 0;
for (int i = 0; i < 12; i++) {
int iCorner0 = cornersInLines[i * 2];
int iCorner1 = cornersInLines[i * 2 + 1];
glm::vec3 corner0 = glm::vec3(
iCorner0 % 2,
(iCorner0 / 2) % 2,
iCorner0 / 4
) - halfSize;
glm::vec3 corner1 = glm::vec3(
iCorner1 % 2,
(iCorner1 / 2) % 2,
iCorner1 / 4
) - halfSize;
glm::vec3 line = corner1 - corner0;
float t = (_planeDistance - glm::dot(corner0, _normal)) / glm::dot(line, _normal);
if (t >= 0.0 && t <= 1.0) {
intersections[nIntersections++] = corner0 + t * line;
}
}
// Gotta love intersections
if (nIntersections <3) {
return;
}
// Construct vectors vectors (vectors1 .. vectorsN) between the N points
std::vector<std::pair<int, float>> angles(nIntersections - 1);
glm::vec3 vector1 = glm::normalize(intersections[1] - intersections[0]);
angles[0] = std::pair<int, float>(1, 0.0f);
for (int i = 2; i < nIntersections; i++) {
glm::vec3 vectorI = glm::normalize(intersections[i] - intersections[0]);
float sinA = glm::dot(glm::cross(vector1, vectorI), _normal);
float cosA = glm::dot(vector1, vectorI);
angles[i - 1] = { i, glm::sign(sinA) * (1.f - cosA) };
}
// Sort the vectors by angle in the plane
std::sort(angles.begin(), angles.end(),
[](const std::pair<int, float>& a, const std::pair<int, float>& b) -> bool {
return a.second < b.second;
}
);
_vertices.push_back(intersections[0].x);
_vertices.push_back(intersections[0].y);
_vertices.push_back(intersections[0].z);
//_vertices.push_back(_w);
for (int i = 0; i < nIntersections - 1; i++) {
int j = angles[i].first;
_vertices.push_back(intersections[j].x);
_vertices.push_back(intersections[j].y);
_vertices.push_back(intersections[j].z);
//_vertices.push_back(_w);
}
// First VAO setup
glBindVertexArray(_vaoId);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferId);
glBufferData(
GL_ARRAY_BUFFER,
_vertices.size() * sizeof(GLfloat),
_vertices.data(),
GL_STATIC_DRAW
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
glBindVertexArray(0);
}
bool BlockPlaneIntersectionGeometry::initialize() {
if (_vaoId == 0) {
glGenVertexArrays(1, &_vaoId);
}
if (_vBufferId == 0) {
glGenBuffers(1, &_vBufferId);
if (_vBufferId == 0) {
LERROR("Could not create vertex buffer");
return false;
}
}
updateVertices();
return true;
}
void BlockPlaneIntersectionGeometry::render() {
glBindVertexArray(_vaoId);
//glDisable(GL_CULL_FACE);
glDrawArrays(GL_TRIANGLE_FAN, 0, static_cast<GLsizei>(_vertices.size() / 3));
//glEnable(GL_CULL_FACE);
}
} // namespace openspace