Hey, glad to hear you're playing around with the libs...
It's actually very straightforward to manipulate individual vertices or faces. The TriangleMesh class has 2 child classes TriangleMesh.Vertex and TriangleMesh.Face. You simply get a face out from the list and then manipulate it.
- Face f = mesh.faces.get(0); // get 1st face
Each face has a reference to its 3 vertices: f.a, f.b and f.c. Each one of these is of type Vertex, a class which extends the more generic Vec3D. To transform any of them, you can make use of (almost) all features, Vec3D has to offer... But be aware that for a usual surface mesh each vertex will most likely be shared by several faces...
So for example, to translate the vertices of a single face in space, do this:
- Vec3D offset=new Vec3D(0,0,100);
- Face f = mesh.faces.get(faceID);
- f.a.addSelf(offset);
- f.b.addSelf(offset);
- f.c.addSelf(offset);
This code would move all 3 face vertices 100 units along the Z axis, but technically, this is not a proper extrusion. To do this properly, you'll need to create additional faces for the 3 sides of the face to be extruded, then remove the original face and re-create it at the translated position. The following demo does all this and also allows you to manipulate the extrusion:
- /**
- * Mesh face extrusion with toxiclibs-0019 or later
- *
- * Usage:
- * f - toggle filled/wireframe display
- * a/d - move extruded face along X axis
- * w/s - moved face along Y
- * z/x - move face along Z
- */
- import toxi.processing.*;
- import toxi.geom.*;
- import toxi.geom.mesh.*;
- import toxi.geom.mesh.TriangleMesh.Face;
- TriangleMesh mesh;
- boolean isFilled = true;
- ToxiclibsSupport gfx;
- void setup() {
- size(640, 480, P3D);
- gfx = new ToxiclibsSupport(this);
- // create a mesh from the axis-aligned bounding box (AABB)
- mesh = new AABB(new Vec3D(), 100).toMesh();
- // get first face/triangle of mesh
- Face f = mesh.faces.get(0);
- // extrude along positive Z axis and shrink to 25% of original size
- // shrinking is done by moving vertices towards centroid of the face
- // before extruding
- float shrink=0.25;
- Vec3D centroid = new Triangle(f.a, f.b, f.c).computeCentroid();
- Vec3D extrude = new Vec3D(0, 0, 100);
- Vec3D a = f.a.interpolateTo(centroid, 1-shrink).add(extrude);
- Vec3D b = f.b.interpolateTo(centroid, 1-shrink).add(extrude);
- Vec3D c = f.c.interpolateTo(centroid, 1-shrink).add(extrude);
- // begin by adding new side faces:
- // side A
- mesh.addFace(f.a, a, f.c);
- mesh.addFace(a, c, f.c);
- // side B
- mesh.addFace(f.a, b, a);
- mesh.addFace(f.a, f.b, b);
- // side C
- mesh.addFace(f.c, c, f.b);
- mesh.addFace(c, b, f.b);
- // remove original face
- mesh.faces.remove(0);
- // add new face as cap
- mesh.addFace(a, b, c);
- // update normals (for shading)
- mesh.computeVertexNormals();
- }
- void draw() {
- background(0);
- lights();
- camera(width / 2 - mouseX, height / 2 - mouseY, 400, 0, 0, 0, 0, 1, 0);
- if (!isFilled) {
- noFill();
- stroke(255);
- gfx.mesh(mesh, false, 10);
- }
- else {
- fill(255);
- stroke(255);
- gfx.mesh(mesh, true, 10);
- }
- }
- void keyPressed() {
- if (key == 'f') {
- isFilled = !isFilled;
- }
- Vec3D offset = new Vec3D();
- if (key == 'a') {
- offset.x = -1;
- }
- if (key == 'd') {
- offset.x = 1;
- }
- if (key == 'w') {
- offset.y = -1;
- }
- if (key == 's') {
- offset.y = 1;
- }
- if (key == 'z') {
- offset.z = -1;
- }
- if (key == 'x') {
- offset.z = 1;
- }
- Face f = mesh.faces.get(mesh.faces.size() - 1);
- translateFace(f, offset);
- }
- void translateFace(Face f, Vec3D offset) {
- f.a.addSelf(offset);
- f.b.addSelf(offset);
- f.c.addSelf(offset);
- mesh.computeFaceNormals();
- mesh.computeVertexNormals();
- }
Hope that helps! The release (0020) will also contain a new mesh structure called Winged-Edge mesh (WETriangleMesh) which will also provide connectivity information for each vertex, see some demos of what you can do with that on my flickr and openprocessing pages: