/***************************************************************************************** * * * 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 #include #include 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> angles(nIntersections - 1); glm::vec3 vector1 = glm::normalize(intersections[1] - intersections[0]); angles[0] = std::pair(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& a, const std::pair& 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(_vertices.size() / 3)); //glEnable(GL_CULL_FACE); } } // namespace openspace