From 9b83919815f6a6ce5d73da1c28483970d0ca5589 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 3 Feb 2021 14:22:28 -0600 Subject: added dev/MinGfx/ --- dev/MinGfx/src/mesh.cc | 651 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 651 insertions(+) create mode 100644 dev/MinGfx/src/mesh.cc (limited to 'dev/MinGfx/src/mesh.cc') diff --git a/dev/MinGfx/src/mesh.cc b/dev/MinGfx/src/mesh.cc new file mode 100644 index 0000000..dd967fa --- /dev/null +++ b/dev/MinGfx/src/mesh.cc @@ -0,0 +1,651 @@ +/* + Copyright (c) 2017,2018 Regents of the University of Minnesota. + All Rights Reserved. + See corresponding header file for details. + */ + +#include "mesh.h" + +#include "matrix4.h" +#include "opengl_headers.h" + +#include +#include + +namespace mingfx { + +#define MAX_TEX_ATTRIBS 5 + + +Mesh::Mesh() : gpu_dirty_(true), vertex_buffer_(0), vertex_array_(0), element_buffer_(0), bvh_dirty_(true) { +} + +Mesh::Mesh(const Mesh &other) { + verts_ = other.verts_; + norms_ = other.norms_; + colors_ = other.colors_; + tex_coords_ = other.tex_coords_; + indices_ = other.indices_; + gpu_dirty_ = true; + bvh_dirty_ = true; +} + +Mesh::~Mesh() { +} + +int Mesh::AddTriangle(Point3 v1, Point3 v2, Point3 v3) { + gpu_dirty_ = true; + bvh_dirty_ = true; + + verts_.push_back(v1[0]); + verts_.push_back(v1[1]); + verts_.push_back(v1[2]); + + verts_.push_back(v2[0]); + verts_.push_back(v2[1]); + verts_.push_back(v2[2]); + + verts_.push_back(v3[0]); + verts_.push_back(v3[1]); + verts_.push_back(v3[2]); + + return num_triangles()-1; +} + +void Mesh::UpdateTriangle(int triangle_id, Point3 v1, Point3 v2, Point3 v3) { + gpu_dirty_ = true; + bvh_dirty_ = true; + + int index = triangle_id * 9; + verts_[(size_t)index + 0] = v1[0]; + verts_[(size_t)index + 1] = v1[1]; + verts_[(size_t)index + 2] = v1[2]; + + verts_[(size_t)index + 3] = v2[0]; + verts_[(size_t)index + 4] = v2[1]; + verts_[(size_t)index + 5] = v2[2]; + + verts_[(size_t)index + 6] = v3[0]; + verts_[(size_t)index + 7] = v3[1]; + verts_[(size_t)index + 8] = v3[2]; +} + + +void Mesh::SetNormals(int triangle_id, Vector3 n1, Vector3 n2, Vector3 n3) { + gpu_dirty_ = true; + + if (triangle_id >= num_triangles()) { + std::cerr << "Mesh::SetNormals() -- warning: cannot set normals for non-existant triangle with ID=" << triangle_id << ". Make sure the triangle has been added first." << std::endl; + return; + } + + int requiredSize = (triangle_id+1)*9; + if (norms_.size() < requiredSize) { + norms_.resize(requiredSize); + } + int index = triangle_id * 9; + norms_[(size_t)index + 0] = n1[0]; + norms_[(size_t)index + 1] = n1[1]; + norms_[(size_t)index + 2] = n1[2]; + + norms_[(size_t)index + 3] = n2[0]; + norms_[(size_t)index + 4] = n2[1]; + norms_[(size_t)index + 5] = n2[2]; + + norms_[(size_t)index + 6] = n3[0]; + norms_[(size_t)index + 7] = n3[1]; + norms_[(size_t)index + 8] = n3[2]; +} + +void Mesh::SetColors(int triangle_id, Color c1, Color c2, Color c3) { + gpu_dirty_ = true; + + if (triangle_id >= num_triangles()) { + std::cerr << "Mesh::SetColors() -- warning: cannot set colors for non-existant triangle with ID=" << triangle_id << ". Make sure the triangle has been added first." << std::endl; + return; + } + + int requiredSize = (triangle_id+1)*12; + if (colors_.size() < requiredSize) { + colors_.resize(requiredSize); + } + int index = triangle_id * 12; + colors_[(size_t)index + 0] = c1[0]; + colors_[(size_t)index + 1] = c1[1]; + colors_[(size_t)index + 2] = c1[2]; + colors_[(size_t)index + 3] = c1[3]; + + colors_[(size_t)index + 4] = c2[0]; + colors_[(size_t)index + 5] = c2[1]; + colors_[(size_t)index + 6] = c2[2]; + colors_[(size_t)index + 7] = c2[3]; + + colors_[(size_t)index + 8] = c3[0]; + colors_[(size_t)index + 9] = c3[1]; + colors_[(size_t)index + 10] = c3[2]; + colors_[(size_t)index + 11] = c3[3]; +} + +void Mesh::SetTexCoords(int triangle_id, int textureUnit, Point2 uv1, Point2 uv2, Point2 uv3) { + gpu_dirty_ = true; + + if (triangle_id >= num_triangles()) { + std::cerr << "Mesh::SetTexCoords() -- warning: cannot set texture coordinates for non-existant triangle with ID=" << triangle_id << ". Make sure the triangle has been added first." << std::endl; + return; + } + + // resize as needed based on the number of textureUnits used + if (tex_coords_.size() < (size_t)textureUnit+1) { + tex_coords_.resize((size_t)textureUnit+1); + } + + // resize the textureUnit-specific array based on the number of triangles + int requiredSize = (triangle_id+1)*6; + if (tex_coords_[textureUnit].size() < requiredSize) { + tex_coords_[textureUnit].resize(requiredSize); + } + int index = triangle_id * 6; + tex_coords_[textureUnit][(size_t)index + 0] = uv1[0]; + tex_coords_[textureUnit][(size_t)index + 1] = uv1[1]; + + tex_coords_[textureUnit][(size_t)index + 2] = uv2[0]; + tex_coords_[textureUnit][(size_t)index + 3] = uv2[1]; + + tex_coords_[textureUnit][(size_t)index + 4] = uv3[0]; + tex_coords_[textureUnit][(size_t)index + 5] = uv3[1]; +} + + +void Mesh::SetVertices(const std::vector &verts) { + gpu_dirty_ = true; + bvh_dirty_ = true; + + verts_.clear(); + for (int i=0; i &norms) { + gpu_dirty_ = true; + norms_.clear(); + for (int i=0; i &colors) { + gpu_dirty_ = true; + colors_.clear(); + for (int i=0; i &tex_coords) { + gpu_dirty_ = true; + // resize as needed based on the number of textureUnits used + if (tex_coords_.size() < (size_t)texture_unit+1) { + tex_coords_.resize((size_t)texture_unit+1); + } + tex_coords_[texture_unit].clear(); + for (int i=0; i indices) { + gpu_dirty_ = true; + bvh_dirty_ = true; + + indices_.clear(); + for (int i=0; i &xforms) { + gpu_dirty_ = true; + instance_xforms_.clear(); + for (int i=0; i texCoordsMemSize; + std::vector texCoordsMemOffset; + for (int i = 0; i < std::min((int)tex_coords_.size(),(int)MAX_TEX_ATTRIBS); i++) { + texCoordsMemSize.push_back(tex_coords_[i].size() * sizeof(float)); + texCoordsMemOffset.push_back(totalMemSize); + totalMemSize += texCoordsMemSize[i]; + } + + GLsizeiptr instanceXformsMemSize = instance_xforms_.size() * sizeof(float); + GLsizeiptr instanceXformsMemOffset = totalMemSize; + totalMemSize += instanceXformsMemSize; + + + glGenBuffers(1, &vertex_buffer_); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); + glBufferData(GL_ARRAY_BUFFER, totalMemSize, NULL, GL_STATIC_DRAW); + + glBufferSubData(GL_ARRAY_BUFFER, vertsMemOffset, vertsMemSize, &verts_[0]); + if (norms_.size() > 0) { + glBufferSubData(GL_ARRAY_BUFFER, normsMemOffset, normsMemSize, &norms_[0]); + } + if (colors_.size() > 0) { + glBufferSubData(GL_ARRAY_BUFFER, colorsMemOffset, colorsMemSize, &colors_[0]); + } + for (int i=0; i 0) { + glBufferSubData(GL_ARRAY_BUFFER, instanceXformsMemOffset, instanceXformsMemSize, &instance_xforms_[0]); + } + glGenVertexArrays(1, &vertex_array_); + glBindVertexArray(vertex_array_); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); + + // 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 (optional) + attribID = 1; + if (norms_.size()) { + nComponents = 3; + glEnableVertexAttribArray(attribID); + glVertexAttribPointer(attribID, nComponents, GL_FLOAT, GL_TRUE, nComponents*sizeof(GLfloat), (char*)0 + normsMemOffset); + } + else { + glDisableVertexAttribArray(attribID); + } + + // attribute 2 = colors (optional) + attribID = 2; + if (colors_.size()) { + nComponents = 4; + glEnableVertexAttribArray(attribID); + glVertexAttribPointer(attribID, nComponents, GL_FLOAT, GL_TRUE, nComponents*sizeof(GLfloat), (char*)0 + colorsMemOffset); + } + else { + glDisableVertexAttribArray(attribID); + } + + // attribute(s) 3 to 7 = texture coordinates (optional) + nComponents = 2; + for (int i=0; i vertices; + std::vector normals; + std::vector texCoords; + + while (file) { + std::string line; + do + getline(file, line); + while (file && (line.length() == 0 || line[0] == '#')); + std::stringstream linestream(line); + std::string keyword; + linestream >> keyword; + if (keyword == "v") { + Point3 vertex; + linestream >> vertex[0] >> vertex[1] >> vertex[2]; + vertices.push_back(vertex); + } else if (keyword == "vn") { + Vector3 normal; + linestream >> normal[0] >> normal[1] >> normal[2]; + normals.push_back(normal); + } else if (keyword == "vt") { + Point2 texCoord; + linestream >> texCoord[0] >> texCoord[1]; + texCoords.push_back(texCoord); + } else if (keyword == "f") { + std::vector polygon; + std::string word; + while (linestream >> word) { + std::stringstream wstream(word); + int v; + wstream >> v; + polygon.push_back(v-1); // In OBJ files, indices start from 1 + } + for (int i = 2; i < polygon.size(); i++) { + //triangles.push_back(ivec3(polygon[0], polygon[i-1], polygon[i])); + int i1 = polygon[0]; + int i2 = polygon[(size_t)i-1]; + int i3 = polygon[i]; + //int t = AddTriangle(vertices[i1], vertices[i2], vertices[i3]); + //if (normals.size()) { + // SetNormals(t, normals[i1], normals[i2], normals[i3]); + //} + //if (texCoords.size()) { + // SetTexCoords(t, 0, texCoords[i1], texCoords[i2], texCoords[i3]); + //} + + indices_.push_back(i1); + indices_.push_back(i2); + indices_.push_back(i3); + } + } + } + + gpu_dirty_ = true; + std::vector verts, norms, uvs; + for (int i=0;i Mesh::read_triangle_indices_data(int triangle_id) const { + std::vector tri; + int i = 3*triangle_id; + if (indices_.size()) { + // indexed faces mode + tri.push_back(indices_[(size_t)i+0]); + tri.push_back(indices_[(size_t)i+1]); + tri.push_back(indices_[(size_t)i+2]); + } + else { + // ordered faces mode + tri.push_back(i); + tri.push_back(i+1); + tri.push_back(i+2); + } + return tri; +} + + +void Mesh::CalcPerFaceNormals() { + std::vector norms(num_vertices()); + for (int i=0; i indices = read_triangle_indices_data(i); + Point3 a = read_vertex_data(indices[0]); + Point3 b = read_vertex_data(indices[1]); + Point3 c = read_vertex_data(indices[2]); + Vector3 n = Vector3::Cross(b-a, c-a).ToUnit(); + norms[indices[0]] = n; + norms[indices[1]] = n; + norms[indices[2]] = n; + } + SetNormals(norms); +} + + +void Mesh::CalcPerVertexNormals() { + std::vector norms(num_vertices()); + for (int i=0; i indices = read_triangle_indices_data(i); + Point3 a = read_vertex_data(indices[0]); + Point3 b = read_vertex_data(indices[1]); + Point3 c = read_vertex_data(indices[2]); + Vector3 n = Vector3::Cross(b-a, c-a); + norms[indices[0]] = norms[indices[0]] + n; + norms[indices[1]] = norms[indices[1]] + n; + norms[indices[2]] = norms[indices[2]] + n; + } + + for (int i=0; i