AGL
A graphics library
|
Base class for meshes. More...
#include <mesh.h>
Public Member Functions | |
virtual void | render () const =0 |
Draw this mesh. More... | |
GLuint | vao () const |
Return the vertex array object corresponding to this mesh. | |
bool | hasUV () const |
Return whether this mesh has UV coordinates defined. | |
bool | isDynamic () const |
Query whether or not this is a dynamic mesh. More... | |
Protected Types | |
enum | VertexAttribute { INDEX = 0, POSITION, NORMAL, UV, TANGENT, NUM_ATTRIBUTES } |
Protected Member Functions | |
int | numVertices () const |
Get the number of vertices. | |
void | setVertexData (VertexAttribute type, int vertexId, const glm::vec4 &data) |
Set vertex properties. More... | |
glm::vec4 | vertexData (VertexAttribute type, int vertexId) const |
Get vertex properties. More... | |
virtual void | setIsDynamic (bool on) |
Set whether or not this is a dynamic mesh. More... | |
virtual void | init ()=0 |
Override init to specifiy vertex data for the mesh. More... | |
void | initBuffers (std::vector< GLfloat > *points, std::vector< GLfloat > *normals, std::vector< GLfloat > *texCoords=nullptr, std::vector< GLfloat > *tangents=nullptr) |
Call initBuffers from init() to set the data for this mesh. More... | |
virtual void | deleteBuffers () |
Protected Attributes | |
GLuint | _nVerts = 0 |
GLuint | _vao = 0 |
bool | _hasUV = false |
bool | _isDynamic = false |
bool | _initialized = false |
std::vector< GLuint > | _buffers |
std::vector< GLfloat > | _data [5] |
Base class for meshes.
|
protectedpure virtual |
Override init to specifiy vertex data for the mesh.
init() will be called automatically the first time render() is called. Overridden implementations of init() should call initBuffers.
Implemented in agl::Torus, agl::Teapot, agl::Cylinder, agl::Plane, agl::Capsule, agl::Cube, agl::Pyramid, and agl::Sphere.
|
protected |
Call initBuffers from init() to set the data for this mesh.
|
inline |
Query whether or not this is a dynamic mesh.
Dynamic meshes can change vertex quantities (e.g. position, normal, etc.) at runtime. Dynamic meshes require more memory and are generally slower. Meshes are static (e.g. assumed not to change) by default.
To create a dynamic mesh, subclass this class and set _isDynamic to true in the constructor.
// Copyright 2020, Savvy Sine, Aline Normoyle #include "agl/window.h" #include "agl/mesh/plane.h" using glm::vec2; using glm::vec4; using glm::vec3; class UndulateMesh : public agl::Plane { public: UndulateMesh(int xsize, int ysize) : Plane(1, 1, xsize, ysize) { setIsDynamic(true); init(); // initialize the mesh rather than wait for first frame } void update(float elapsedTime) { for (int i = 0; i < numVertices(); i++) { vec3 p = vec3(vertexData(POSITION, i)); setVertexData(POSITION, i, vec4(position(p, elapsedTime), 0)); setVertexData(NORMAL, i, vec4(normal(p, elapsedTime), 0)); } } vec3 position(const vec3& p, float t) { float angle = t; float frequency = 7.0; float amplitude = 0.05; float heightFn = (angle + frequency * p[0] * frequency * p[2]); float y = amplitude * sin(heightFn); return vec3(p.x, y, p.z); } vec3 normal(const vec3& p, float t) { float eps = 0.001; vec3 x = position(p+vec3(eps, 0, 0), t) - position(p-vec3(eps, 0, 0), t); vec3 z = position(p+vec3(0, 0, eps), t) - position(p-vec3(0, 0, eps), t); vec3 y = glm::cross(z, x); return normalize(y); } }; class MyWindow : public agl::Window { public: void setup() { perspective(glm::radians(30.0), 1, 0.1, 100); renderer.setUniform("Material.specular", vec3(1.0, 0.2, 0.8)); renderer.setUniform("Material.ambient", vec3(0.3, 0.0, 0.2)); } void draw() { _mesh.update(elapsedTime()); renderer.rotate(kPI * 0.2, vec3(1, 0, 0)); renderer.mesh(_mesh); } UndulateMesh _mesh = UndulateMesh(100, 100); }; int main() { MyWindow window; window.run(); }
|
pure virtual |
Draw this mesh.
Typically, users do not need to call this function. It is called from Renderer.
Implemented in agl::LineMesh, agl::PointMesh, and agl::TriangleMesh.
|
protectedvirtual |
Set whether or not this is a dynamic mesh.
Dynamic meshes can change vertex quantities (e.g. position, normal, etc.) at runtime. Dynamic meshes require more memory and are generally slower. Meshes are static (e.g. assumed not to change) by default.
To create a dynamic mesh, subclass this class and call setIsDynamic(true) in the constructor. setIsDynamic must be called before the mesh is initialized and cannot be changed afterwards.
// Copyright 2020, Savvy Sine, Aline Normoyle #include "agl/window.h" #include "agl/mesh/plane.h" using glm::vec2; using glm::vec4; using glm::vec3; class UndulateMesh : public agl::Plane { public: UndulateMesh(int xsize, int ysize) : Plane(1, 1, xsize, ysize) { setIsDynamic(true); init(); // initialize the mesh rather than wait for first frame } void update(float elapsedTime) { for (int i = 0; i < numVertices(); i++) { vec3 p = vec3(vertexData(POSITION, i)); setVertexData(POSITION, i, vec4(position(p, elapsedTime), 0)); setVertexData(NORMAL, i, vec4(normal(p, elapsedTime), 0)); } } vec3 position(const vec3& p, float t) { float angle = t; float frequency = 7.0; float amplitude = 0.05; float heightFn = (angle + frequency * p[0] * frequency * p[2]); float y = amplitude * sin(heightFn); return vec3(p.x, y, p.z); } vec3 normal(const vec3& p, float t) { float eps = 0.001; vec3 x = position(p+vec3(eps, 0, 0), t) - position(p-vec3(eps, 0, 0), t); vec3 z = position(p+vec3(0, 0, eps), t) - position(p-vec3(0, 0, eps), t); vec3 y = glm::cross(z, x); return normalize(y); } }; class MyWindow : public agl::Window { public: void setup() { perspective(glm::radians(30.0), 1, 0.1, 100); renderer.setUniform("Material.specular", vec3(1.0, 0.2, 0.8)); renderer.setUniform("Material.ambient", vec3(0.3, 0.0, 0.2)); } void draw() { _mesh.update(elapsedTime()); renderer.rotate(kPI * 0.2, vec3(1, 0, 0)); renderer.mesh(_mesh); } UndulateMesh _mesh = UndulateMesh(100, 100); }; int main() { MyWindow window; window.run(); }
|
protected |
Set vertex properties.
type | A supported vertex attribute, such as POSITION, NORMAL, etc |
vertexId | The id of the vertex (should be between 0 and numVertices) |
data | The data to set |
This function only works for dynamic meshes. This function takes a vec4 but depending on the vertex attribute only a subset of the given values will be used, depending on the data set during initialization. For example, texture coordinates typically only need two coordinates and so only the first xy values of data will be used.
// Copyright 2020, Savvy Sine, Aline Normoyle #include "agl/window.h" #include "agl/mesh/plane.h" using glm::vec2; using glm::vec4; using glm::vec3; class UndulateMesh : public agl::Plane { public: UndulateMesh(int xsize, int ysize) : Plane(1, 1, xsize, ysize) { setIsDynamic(true); init(); // initialize the mesh rather than wait for first frame } void update(float elapsedTime) { for (int i = 0; i < numVertices(); i++) { vec3 p = vec3(vertexData(POSITION, i)); setVertexData(POSITION, i, vec4(position(p, elapsedTime), 0)); setVertexData(NORMAL, i, vec4(normal(p, elapsedTime), 0)); } } vec3 position(const vec3& p, float t) { float angle = t; float frequency = 7.0; float amplitude = 0.05; float heightFn = (angle + frequency * p[0] * frequency * p[2]); float y = amplitude * sin(heightFn); return vec3(p.x, y, p.z); } vec3 normal(const vec3& p, float t) { float eps = 0.001; vec3 x = position(p+vec3(eps, 0, 0), t) - position(p-vec3(eps, 0, 0), t); vec3 z = position(p+vec3(0, 0, eps), t) - position(p-vec3(0, 0, eps), t); vec3 y = glm::cross(z, x); return normalize(y); } }; class MyWindow : public agl::Window { public: void setup() { perspective(glm::radians(30.0), 1, 0.1, 100); renderer.setUniform("Material.specular", vec3(1.0, 0.2, 0.8)); renderer.setUniform("Material.ambient", vec3(0.3, 0.0, 0.2)); } void draw() { _mesh.update(elapsedTime()); renderer.rotate(kPI * 0.2, vec3(1, 0, 0)); renderer.mesh(_mesh); } UndulateMesh _mesh = UndulateMesh(100, 100); }; int main() { MyWindow window; window.run(); }
|
protected |
Get vertex properties.
type | A supported vertex attribute, such as POSITION, NORMAL, etc |
vertexId | The id of the vertex (should be between 0 and numVertices) |
This function only works for dynamic meshes. This function takes a vec4 but depending on the vertex attribute only a subset of the given values will be used, depending on the data set during initialization. For example, texture coordinates typically only need two coordinates and so only the first xy values of data will be used.
// Copyright 2020, Savvy Sine, Aline Normoyle #include "agl/window.h" #include "agl/mesh/plane.h" using glm::vec2; using glm::vec4; using glm::vec3; class UndulateMesh : public agl::Plane { public: UndulateMesh(int xsize, int ysize) : Plane(1, 1, xsize, ysize) { setIsDynamic(true); init(); // initialize the mesh rather than wait for first frame } void update(float elapsedTime) { for (int i = 0; i < numVertices(); i++) { vec3 p = vec3(vertexData(POSITION, i)); setVertexData(POSITION, i, vec4(position(p, elapsedTime), 0)); setVertexData(NORMAL, i, vec4(normal(p, elapsedTime), 0)); } } vec3 position(const vec3& p, float t) { float angle = t; float frequency = 7.0; float amplitude = 0.05; float heightFn = (angle + frequency * p[0] * frequency * p[2]); float y = amplitude * sin(heightFn); return vec3(p.x, y, p.z); } vec3 normal(const vec3& p, float t) { float eps = 0.001; vec3 x = position(p+vec3(eps, 0, 0), t) - position(p-vec3(eps, 0, 0), t); vec3 z = position(p+vec3(0, 0, eps), t) - position(p-vec3(0, 0, eps), t); vec3 y = glm::cross(z, x); return normalize(y); } }; class MyWindow : public agl::Window { public: void setup() { perspective(glm::radians(30.0), 1, 0.1, 100); renderer.setUniform("Material.specular", vec3(1.0, 0.2, 0.8)); renderer.setUniform("Material.ambient", vec3(0.3, 0.0, 0.2)); } void draw() { _mesh.update(elapsedTime()); renderer.rotate(kPI * 0.2, vec3(1, 0, 0)); renderer.mesh(_mesh); } UndulateMesh _mesh = UndulateMesh(100, 100); }; int main() { MyWindow window; window.run(); }