summaryrefslogtreecommitdiffstats
path: root/dev/a5-artrender/edge_mesh.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dev/a5-artrender/edge_mesh.cc')
-rw-r--r--dev/a5-artrender/edge_mesh.cc231
1 files changed, 231 insertions, 0 deletions
diff --git a/dev/a5-artrender/edge_mesh.cc b/dev/a5-artrender/edge_mesh.cc
new file mode 100644
index 0000000..f2ad66b
--- /dev/null
+++ b/dev/a5-artrender/edge_mesh.cc
@@ -0,0 +1,231 @@
+/** CSci-4611 Assignment 5: Art Render
+ */
+
+#include "edge_mesh.h"
+
+EdgeMesh::EdgeMesh() : gpuDirty_(true), vertexBuffer_(0), vertexArray_(0), elementBuffer_(0)
+{
+
+}
+
+EdgeMesh::~EdgeMesh() {
+}
+
+
+
+void EdgeMesh::CreateFromMesh(const Mesh &mesh) {
+
+ // temp data holders for use while constructing the mesh in an indexed primitives mode
+ std::vector<Point3> vertices; // vertex positions
+ std::vector<Vector3> normals; // vertex normals
+ std::vector<Vector3> leftNormals, rightNormals; // normals of adj. faces
+ std::vector< std::vector<unsigned int> > triangles; // fin triangles
+
+ for (int t = 0; t < mesh.num_triangles(); t++) {
+ std::vector<unsigned int> tri = mesh.read_triangle_indices_data(t);
+ Point3 a = mesh.read_vertex_data(tri[0]);
+ Point3 b = mesh.read_vertex_data(tri[1]);
+ Point3 c = mesh.read_vertex_data(tri[2]);
+ Vector3 e1 = b-a;
+ e1.Normalize();
+ Vector3 e2 = c-a;
+ e2.Normalize();
+ Vector3 n = e1.Cross(e2);
+
+ //Vector3 n = ((b-a).cross(c-a)).to_unit();
+ //std::cout << n << std::endl;
+ addEdge(&vertices, &normals, &leftNormals, &rightNormals, &triangles, mesh, tri[0], tri[1], n);
+ addEdge(&vertices, &normals, &leftNormals, &rightNormals, &triangles, mesh, tri[1], tri[2], n);
+ addEdge(&vertices, &normals, &leftNormals, &rightNormals, &triangles, mesh, tri[2], tri[0], n);
+ }
+
+ // now transfer data to the member variable data holders
+ for (int i=0; i<vertices.size(); i++) {
+ verts_.push_back(vertices[i][0]);
+ verts_.push_back(vertices[i][1]);
+ verts_.push_back(vertices[i][2]);
+ norms_.push_back(normals[i][0]);
+ norms_.push_back(normals[i][1]);
+ norms_.push_back(normals[i][2]);
+ leftNorms_.push_back(leftNormals[i][0]);
+ leftNorms_.push_back(leftNormals[i][1]);
+ leftNorms_.push_back(leftNormals[i][2]);
+ rightNorms_.push_back(rightNormals[i][0]);
+ rightNorms_.push_back(rightNormals[i][1]);
+ rightNorms_.push_back(rightNormals[i][2]);
+ }
+
+ for (int i=0; i<triangles.size(); i++) {
+ indices_.push_back(triangles[i][0]);
+ indices_.push_back(triangles[i][1]);
+ indices_.push_back(triangles[i][2]);
+ }
+ gpuDirty_ = true;
+}
+
+
+void EdgeMesh::addEdge(std::vector<Point3> *vertices,
+ std::vector<Vector3> *normals,
+ std::vector<Vector3> *leftNormals,
+ std::vector<Vector3> *rightNormals,
+ std::vector< std::vector<unsigned int> > *triangles,
+ const Mesh &mesh, int v0, int v1, Vector3 n)
+{
+ // edgeMap contains the index of the first of four consecutive vertices
+ // that form the quad fin
+
+ EdgeMap::iterator it = edgeMap.find(std::make_pair(v1, v0));
+ if (it != edgeMap.end()) { // found
+ int v = it->second;
+ (*rightNormals)[(size_t)v+0]
+ = (*rightNormals)[(size_t)v+1]
+ = (*rightNormals)[(size_t)v+2]
+ = (*rightNormals)[(size_t)v+3]
+ = n;
+ }
+ else {
+ int v = (int)vertices->size();
+ edgeMap[std::make_pair(v0, v1)] = v;
+
+ vertices->push_back(mesh.read_vertex_data(v0));
+ vertices->push_back(mesh.read_vertex_data(v0));
+ vertices->push_back(mesh.read_vertex_data(v1));
+ vertices->push_back(mesh.read_vertex_data(v1));
+
+ normals->push_back(Vector3());
+ normals->push_back(mesh.read_normal_data(v0));
+ normals->push_back(Vector3());
+ normals->push_back(mesh.read_normal_data(v1));
+
+ leftNormals->push_back(n);
+ leftNormals->push_back(n);
+ leftNormals->push_back(n);
+ leftNormals->push_back(n);
+
+ rightNormals->push_back(-n);
+ rightNormals->push_back(-n);
+ rightNormals->push_back(-n);
+ rightNormals->push_back(-n);
+
+ std::vector<unsigned int> tri1;
+ tri1.push_back(v+0);
+ tri1.push_back(v+2);
+ tri1.push_back(v+3);
+ triangles->push_back(tri1);
+
+ std::vector<unsigned int> tri2;
+ tri2.push_back(v+0);
+ tri2.push_back(v+3);
+ tri2.push_back(v+1);
+ triangles->push_back(tri2);
+ }
+}
+
+
+
+void EdgeMesh::UpdateGPUMemory() {
+ if (gpuDirty_) {
+ // sanity check -- for each attribute that is added make sure the number
+ // of triangles is equal to the number of tris in the verts array.
+ if (norms_.size() / 3 != num_vertices()) {
+ std::cerr << "EdgeMesh::UpdateGPUMemory() -- warning: the number of per vertex normals in the mesh is not equal to the number vertices in the mesh. (N = " << norms_.size() / 3 << ", V = " << num_vertices() << ")" << std::endl;
+ }
+ if (leftNorms_.size() / 3 != num_vertices()) {
+ std::cerr << "EdgeMesh::UpdateGPUMemory() -- warning: the number of per vertex left-normals in the mesh is not equal to the number vertices in the mesh. (LN = " << leftNorms_.size() / 3 << ", V = " << num_vertices() << ")" << std::endl;
+ }
+ if (rightNorms_.size() / 3 != num_vertices()) {
+ std::cerr << "EdgeMesh::UpdateGPUMemory() -- warning: the number of per vertex right-normals in the mesh is not equal to the number vertices in the mesh. (RN = " << rightNorms_.size() / 3 << ", V = " << num_vertices() << ")" << std::endl;
+ }
+
+ GLsizeiptr totalMemSize = 0;
+
+ GLsizeiptr vertsMemSize = verts_.size() * sizeof(float);
+ GLsizeiptr vertsMemOffset = 0;
+ totalMemSize += vertsMemSize;
+
+ GLsizeiptr normsMemSize = norms_.size() * sizeof(float);
+ GLsizeiptr normsMemOffset = totalMemSize;
+ totalMemSize += normsMemSize;
+
+ GLsizeiptr leftNormsMemSize = leftNorms_.size() * sizeof(float);
+ GLsizeiptr leftNormsMemOffset = totalMemSize;
+ totalMemSize += leftNormsMemSize;
+
+ GLsizeiptr rightNormsMemSize = rightNorms_.size() * sizeof(float);
+ GLsizeiptr rightNormsMemOffset = totalMemSize;
+ totalMemSize += rightNormsMemSize;
+
+ glGenBuffers(1, &vertexBuffer_);
+ glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer_);
+ glBufferData(GL_ARRAY_BUFFER, totalMemSize, NULL, GL_STATIC_DRAW);
+
+ glBufferSubData(GL_ARRAY_BUFFER, vertsMemOffset, vertsMemSize, &verts_[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, normsMemOffset, normsMemSize, &norms_[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, leftNormsMemOffset, leftNormsMemSize, &leftNorms_[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, rightNormsMemOffset, rightNormsMemSize, &rightNorms_[0]);
+
+ glGenVertexArrays(1, &vertexArray_);
+ glBindVertexArray(vertexArray_);
+ glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer_);
+
+ // attribute 0 = vertices (required)
+ int attribID = 0;
+ int nComponents = 3;
+ glEnableVertexAttribArray(attribID);
+ glVertexAttribPointer(attribID, nComponents, GL_FLOAT, GL_FALSE, nComponents*sizeof(GLfloat), (char*)0 + vertsMemOffset);
+
+ // attribute 1 = normals (required)
+ attribID = 1;
+ nComponents = 3;
+ glEnableVertexAttribArray(attribID);
+ glVertexAttribPointer(attribID, nComponents, GL_FLOAT, GL_TRUE, nComponents*sizeof(GLfloat), (char*)0 + normsMemOffset);
+
+ // attribute 2 = left normals (required)
+ attribID = 2;
+ nComponents = 3;
+ glEnableVertexAttribArray(attribID);
+ glVertexAttribPointer(attribID, nComponents, GL_FLOAT, GL_TRUE, nComponents*sizeof(GLfloat), (char*)0 + leftNormsMemOffset);
+
+ // attribute 3 = right normals (required)
+ attribID = 3;
+ nComponents = 3;
+ glEnableVertexAttribArray(attribID);
+ glVertexAttribPointer(attribID, nComponents, GL_FLOAT, GL_TRUE, nComponents*sizeof(GLfloat), (char*)0 + rightNormsMemOffset);
+
+ glBindVertexArray(0);
+
+
+ glGenBuffers(1, &elementBuffer_);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer_);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_.size() * sizeof(unsigned int), &indices_[0], GL_STATIC_DRAW);
+
+
+ gpuDirty_ = false;
+ }
+}
+
+
+void EdgeMesh::Draw() {
+ if (gpuDirty_) {
+ UpdateGPUMemory();
+ }
+
+ // set defaults to pass to shaders any for optional attribs
+ glVertexAttrib3f(1, 0.0, 0.0, 1.0); // normal = +Z
+ glVertexAttrib3f(2, 0.0, 0.0, 1.0); // left-normal = +Z
+ glVertexAttrib3f(3, 0.0, 0.0, 1.0); // right-normal = +Z
+
+ glBindVertexArray(vertexArray_);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer_);
+ glDrawElements(GL_TRIANGLES, (GLsizei)indices_.size(), GL_UNSIGNED_INT, (void*)0);
+ glBindVertexArray(0);
+}
+
+
+int EdgeMesh::num_vertices() const {
+ return (int)verts_.size()/3;
+}
+
+int EdgeMesh::num_triangles() const {
+ return (int)indices_.size()/3;
+}