summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSebastian Park <SebPark03@gmail.com>2024-05-10 00:12:48 -0400
committerSebastian Park <SebPark03@gmail.com>2024-05-10 00:12:48 -0400
commit7a61605e57d96bf5c699c9c759288376b8c94eac (patch)
treee541a717bb727f607a4d3357396b12a2ad039f08 /src
parent99c588d4da2ca044df8276b7efbd9d27c19c8352 (diff)
Add simpleshape.
Diffstat (limited to 'src')
-rw-r--r--src/graphics/simpleshape.cpp272
-rw-r--r--src/graphics/simpleshape.h89
2 files changed, 361 insertions, 0 deletions
diff --git a/src/graphics/simpleshape.cpp b/src/graphics/simpleshape.cpp
new file mode 100644
index 0000000..567dab3
--- /dev/null
+++ b/src/graphics/simpleshape.cpp
@@ -0,0 +1,272 @@
+#include "simpleshape.h"
+
+#include <iostream>
+#include "graphics/shader.h"
+
+using namespace Eigen;
+using namespace std;
+
+// ================== Constructor
+
+SimpleShape::SimpleShape() :
+ m_surfaceVao(),
+ m_surfaceVbo(),
+ m_surfaceIbo(),
+ m_numSurfaceVertices(),
+ m_verticesSize(),
+ m_red(),
+ m_blue(),
+ m_green(),
+ m_alpha(),
+ m_faces(),
+ m_vertices(),
+ m_anchors(),
+ m_modelMatrix(Matrix4f::Identity()),
+ lastSelected(-1)
+{}
+
+// ================== Initialization and Updating
+
+void SimpleShape::init(const vector<Vector3f> &vertices, const vector<Vector3i> &triangles)
+{
+ m_vertices.clear();
+ copy(vertices.begin(), vertices.end(), back_inserter(m_vertices));
+
+ vector<Vector3f> verts;
+ vector<Vector3f> normals;
+ vector<Vector3f> colors;
+ vector<Vector3i> faces;
+ faces.reserve(triangles.size());
+
+ for (int s = 0; s < triangles.size() * 3; s+=3) faces.push_back(Vector3i(s, s + 1, s + 2));
+ updateMesh(triangles, vertices, verts, normals, colors);
+
+ glGenBuffers(1, &m_surfaceVbo);
+ glGenBuffers(1, &m_surfaceIbo);
+ glGenVertexArrays(1, &m_surfaceVao);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_surfaceVbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * ((verts.size() * 3) + (normals.size() * 3) + (colors.size() * 3)), nullptr, GL_DYNAMIC_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * verts.size() * 3, static_cast<const void *>(verts.data()));
+ glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * verts.size() * 3, sizeof(float) * normals.size() * 3, static_cast<const void *>(normals.data()));
+ glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * ((verts.size() * 3) + (normals.size() * 3)), sizeof(float) * colors.size() * 3, static_cast<const void *>(colors.data()));
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceIbo);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 3 * faces.size(), static_cast<const void *>(faces.data()), GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindVertexArray(m_surfaceVao);
+ glBindBuffer(GL_ARRAY_BUFFER, m_surfaceVbo);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, static_cast<GLvoid *>(0));
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<GLvoid *>(sizeof(float) * verts.size() * 3));
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<GLvoid *>(sizeof(float) * (verts.size() * 3 + colors.size() * 3)));
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceIbo);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ m_numSurfaceVertices = faces.size() * 3;
+ m_verticesSize = vertices.size();
+ m_faces = triangles;
+ m_red = 0.5f + 0.5f * rand() / ((float) RAND_MAX);
+ m_blue = 0.5f + 0.5f * rand() / ((float) RAND_MAX);
+ m_green = 0.5f + 0.5f * rand() / ((float) RAND_MAX);
+ m_alpha = 1.0f;
+}
+
+void SimpleShape::setVertices(const vector<Vector3f> &vertices)
+{
+ m_vertices.clear();
+ copy(vertices.begin(), vertices.end(), back_inserter(m_vertices));
+
+ vector<Vector3f> verts;
+ vector<Vector3f> normals;
+ vector<Vector3f> colors;
+
+ updateMesh(m_faces, vertices, verts, normals, colors);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_surfaceVbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * ((verts.size() * 3) + (normals.size() * 3) + (colors.size() * 3)), nullptr, GL_DYNAMIC_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * verts.size() * 3, static_cast<const void *>(verts.data()));
+ glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * verts.size() * 3, sizeof(float) * normals.size() * 3, static_cast<const void *>(normals.data()));
+ glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * ((verts.size() * 3) + (normals.size() * 3)), sizeof(float) * colors.size() * 3, static_cast<const void *>(colors.data()));
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+// ================== Model Matrix
+
+void SimpleShape::setModelMatrix(const Affine3f &model) { m_modelMatrix = model.matrix(); }
+
+// ================== General Graphics Stuff
+
+void SimpleShape::draw(Shader *shader, GLenum mode)
+{
+ Eigen::Matrix3f m3 = m_modelMatrix.topLeftCorner(3, 3);
+ Eigen::Matrix3f inverseTransposeModel = m3.inverse().transpose();
+
+ switch(mode) {
+ case GL_TRIANGLES:
+ {
+ shader->setUniform("wire", 0);
+ shader->setUniform("model", m_modelMatrix);
+ shader->setUniform("inverseTransposeModel", inverseTransposeModel);
+ shader->setUniform("red", m_red);
+ shader->setUniform("green", m_green);
+ shader->setUniform("blue", m_blue);
+ shader->setUniform("alpha", m_alpha);
+ glBindVertexArray(m_surfaceVao);
+ glDrawElements(mode, m_numSurfaceVertices, GL_UNSIGNED_INT, reinterpret_cast<GLvoid *>(0));
+ glBindVertexArray(0);
+ break;
+ }
+ case GL_POINTS:
+ {
+ shader->setUniform("model", m_modelMatrix);
+ shader->setUniform("inverseTransposeModel", inverseTransposeModel);
+ glBindVertexArray(m_surfaceVao);
+ glDrawElements(mode, m_numSurfaceVertices, GL_UNSIGNED_INT, reinterpret_cast<GLvoid *>(0));
+ glBindVertexArray(0);
+ break;
+ }
+ }
+}
+
+SelectMode SimpleShape::select(Shader *shader, int closest_vertex)
+{
+ if (closest_vertex == -1) return SelectMode::None;
+
+ bool vertexIsNowSelected = m_anchors.find(closest_vertex) == m_anchors.end();
+
+ if (vertexIsNowSelected) {
+ m_anchors.insert(closest_vertex);
+ } else {
+ m_anchors.erase(closest_vertex);
+ }
+
+ selectHelper();
+
+ return vertexIsNowSelected ? SelectMode::Anchor : SelectMode::Unanchor;
+}
+
+bool SimpleShape::selectWithSpecifiedMode(Shader *shader, int closest_vertex, SelectMode mode)
+{
+ switch (mode) {
+ case SelectMode::None: {
+ return false;
+ }
+ case SelectMode::Anchor: {
+ if (m_anchors.find(closest_vertex) != m_anchors.end()) return false;
+ m_anchors.insert(closest_vertex);
+ break;
+ }
+ case SelectMode::Unanchor: {
+ if (m_anchors.find(closest_vertex) == m_anchors.end()) return false;
+ m_anchors.erase(closest_vertex);
+ break;
+ }
+ }
+
+ selectHelper();
+
+ return true;
+}
+
+int SimpleShape::getClosestVertex(Vector3f start, Vector3f ray, float threshold)
+{
+ int closest_vertex = -1;
+ int i = 0;
+ float dist = numeric_limits<float>::max();
+ ParametrizedLine line = ParametrizedLine<float, 3>::Through(start, start + ray);
+
+ for (const Vector3f &v : m_vertices) {
+ float d = line.distance(v);
+ if (d<dist) {
+ dist = d;
+ closest_vertex = i;
+ }
+ ++i;
+ }
+
+ if (dist >= threshold) closest_vertex = -1;
+
+ return closest_vertex;
+}
+
+bool SimpleShape::getAnchorPos(int lastSelected,
+ Eigen::Vector3f& pos,
+ Eigen::Vector3f ray,
+ Eigen::Vector3f start)
+{
+ bool isAnchor = m_anchors.find(lastSelected) != m_anchors.end();
+ if (isAnchor) {
+ Eigen::Vector3f oldPos = m_vertices[lastSelected];
+ Eigen::ParametrizedLine line = ParametrizedLine<float, 3>::Through(start, start+ray);
+ pos = line.projection(oldPos);
+ }
+ return isAnchor;
+}
+
+// ================== Accessors
+
+const vector<Vector3f> &SimpleShape::getVertices() { return m_vertices; }
+const vector<Vector3i> &SimpleShape::getFaces() { return m_faces; }
+const unordered_set<int> &SimpleShape::getAnchors() { return m_anchors; }
+
+// ================== Helpers
+
+void SimpleShape::selectHelper()
+{
+ vector<Vector3f> verts;
+ vector<Vector3f> normals;
+ vector<Vector3f> colors;
+ updateMesh(m_faces, m_vertices, verts, normals, colors);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_surfaceVbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * ((verts.size() * 3) + (normals.size() * 3) + (colors.size() * 3)), nullptr, GL_DYNAMIC_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * verts.size() * 3, static_cast<const void *>(verts.data()));
+ glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * verts.size() * 3, sizeof(float) * normals.size() * 3, static_cast<const void *>(normals.data()));
+ glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * ((verts.size() * 3) + (normals.size() * 3)), sizeof(float) * colors.size() * 3, static_cast<const void *>(colors.data()));
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+Vector3f SimpleShape::getNormal(const Vector3i& face)
+{
+ Vector3f& v1 = m_vertices[face[0]];
+ Vector3f& v2 = m_vertices[face[1]];
+ Vector3f& v3 = m_vertices[face[2]];
+ Vector3f e1 = v2 - v1;
+ Vector3f e2 = v3 - v1;
+ Vector3f n = e1.cross(e2);
+ return n.normalized();
+}
+
+void SimpleShape::updateMesh(const std::vector<Eigen::Vector3i> &faces,
+ const std::vector<Eigen::Vector3f> &vertices,
+ std::vector<Eigen::Vector3f>& verts,
+ std::vector<Eigen::Vector3f>& normals,
+ std::vector<Eigen::Vector3f>& colors)
+{
+ verts.reserve(faces.size() * 3);
+ normals.reserve(faces.size() * 3);
+
+ for (const Eigen::Vector3i& face : faces) {
+ Vector3f n = getNormal(face);
+
+ for (auto& v: {face[0], face[1], face[2]}) {
+ normals.push_back(n);
+ verts.push_back(vertices[v]);
+
+ if (m_anchors.find(v) == m_anchors.end()) {
+ colors.push_back(Vector3f(1,0,0));
+ } else {
+ colors.push_back(Vector3f(0, 1 - m_green, 1 - m_blue));
+ }
+ }
+ }
+}
+
diff --git a/src/graphics/simpleshape.h b/src/graphics/simpleshape.h
new file mode 100644
index 0000000..03db726
--- /dev/null
+++ b/src/graphics/simpleshape.h
@@ -0,0 +1,89 @@
+#pragma once
+
+#include <GL/glew.h>
+#include <set>
+#include <vector>
+#include <unordered_set>
+
+#define EIGEN_DONT_VECTORIZE
+#define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
+//#include "Eigen/StdVector"
+//EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Matrix2f)
+//EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Matrix3f)
+//EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Matrix3i)
+#include "Eigen/Dense"
+
+enum SelectMode
+{
+ None = 0,
+ Anchor = 1,
+ Unanchor = 2
+};
+
+
+
+
+struct Edge{
+ std::pair<int, int> ij;
+ float weight = 0.f;
+ std::set<int> opposite_two;
+};
+
+struct Cell{
+ int center_index = 0; // this is i
+ std::set<int> neighbor_js; // this is neighboring j's
+ std::set<int> edge_ids; // this is ids if ij edges in edge vector
+};
+
+
+class Shader;
+
+class SimpleShape
+{
+public:
+ SimpleShape();
+
+ void init(const std::vector<Eigen::Vector3f> &vertices, const std::vector<Eigen::Vector3i> &triangles);
+ void setVertices(const std::vector<Eigen::Vector3f> &vertices);
+
+ void setModelMatrix(const Eigen::Affine3f &model);
+
+ void draw(Shader *shader, GLenum mode);
+ SelectMode select(Shader *shader, int vertex);
+ bool selectWithSpecifiedMode(Shader *shader, int vertex, SelectMode mode);
+ int getClosestVertex(Eigen::Vector3f start, Eigen::Vector3f ray, float threshold);
+ bool getAnchorPos(int lastSelected, Eigen::Vector3f& pos, Eigen::Vector3f ray, Eigen::Vector3f start);
+
+ const std::vector<Eigen::Vector3f>& getVertices();
+ const std::vector<Eigen::Vector3i>& getFaces();
+ const std::unordered_set<int>& getAnchors();
+
+private:
+ GLuint m_surfaceVao;
+ GLuint m_surfaceVbo;
+ GLuint m_surfaceIbo;
+
+ unsigned int m_numSurfaceVertices;
+ unsigned int m_verticesSize;
+ float m_red;
+ float m_blue;
+ float m_green;
+ float m_alpha;
+
+ std::vector<Eigen::Vector3i> m_faces;
+ std::vector<Eigen::Vector3f> m_vertices;
+ std::unordered_set<int> m_anchors;
+
+ Eigen::Matrix4f m_modelMatrix;
+ int lastSelected = -1;
+
+ // Helpers
+
+ void selectHelper();
+ Eigen::Vector3f getNormal(const Eigen::Vector3i& face);
+ void updateMesh(const std::vector<Eigen::Vector3i> &triangles,
+ const std::vector<Eigen::Vector3f> &vertices,
+ std::vector<Eigen::Vector3f>& verts,
+ std::vector<Eigen::Vector3f>& normals,
+ std::vector<Eigen::Vector3f>& colors);
+};