Surface Meshes
Surface meshes are one of the core structures in Polyscope. In addition to simply displaying the mesh, Polyscope can show any number of scalar, vector,color, and other kinds of quantities associated with the vertices/faces/edges/etc of the mesh.
Polyscope does not impose any requirements on the meshes visualized. They may be polygonal or nonmanifold. As always, try clicking on the vertices or faces of a mesh see the data associated with that mesh element.
Registering a surface mesh
Example: registering a surface mesh from libIGL
#include "polyscope/polyscope.h"
#include "polyscope/surface_mesh.h"
#include <igl/readOBJ.h>
// Initialize Polyscope
polyscope::init();
// Read the mesh
Eigen::MatrixXd meshV;
Eigen::MatrixXi meshF;
igl::readOBJ(filename, meshV, meshF);
// Register the mesh with Polyscope
polyscope::registerSurfaceMesh("input mesh", meshV, meshF);
// Show the GUI
polyscope::show();
Surface meshes are registered with Polyscope by passing the location of each vertex in the mesh, as well as the vertex indices for each face.
polyscope::registerSurfaceMesh(std::string name, const V& vertexPositions, const F& faceIndices)
Add a new surface mesh structure to Polyscope.
-
vertexPositions
is the vector array of 3D vertex locations. The type should be adaptable to an array offloat
-valued 3-vectors; this allows many common types to be used as input, includingEigen::MatrixXd
andstd::vector<std::array<double, 3>>
. The length will be the number of vertices. -
faceIndices
is the nested array of vertex indices for each face. The type should be adaptable to a nested array ofsize_t
; this allows many common types to be used as input, includingEigen::MatrixXi
andstd::vector<std::array<size_t, 3>>
. The outer length will be the number of faces. All indices should be valid 0-based indices in to the vertex list.
General nested lists can be used to create polygonal meshes of varying face degree, such as std::vector<std::vector<size_t>>
. Also, passing a fixed-size 2D array of indices will work just fine, like Eigen::MatrixXi
with Fx3
dimensions for a triangle mesh, or Fx4
for a quad mesh.
Note: the inner vector type of the vertex positions must be 3D dimensional, or you risk compiler errors, segfaults, or worse. If you want to register a 2D surface mesh, registerSurfaceMesh2D
exists with the same signature. See 2D data.
Element ordering
Polyscope quantities are ordered arrays of data, but not everyone can agree on the ordering of elements in a mesh. See indexing conventions.
The default ordering is probably the same as yours for data on vertices, faces, and corners. However, data on edges and halfedges is much more likely to require setting an ordering.
Updating a mesh
The locations of the vertices in a mesh can be updated with the member function updateVertexPositions(newPositions)
. All quantities will be preserved. Changing the connectivity or element counts in a mesh is not supported, you will need to register a new mesh (perhaps with the same name to overwrite).
void SurfaceMesh::updateVertexPositions(const V& newPositions)
Update the vertex positions in a surface mesh structure.
newPositions
is the vector array of 3D vertex locations. The type should be adaptable to an array offloat
-valued 3-vectors. The length must be equal to the current number of vertices.
Note: updateVertexPositions2D
exists with the same signature. See 2D data.
Picking
“Picking” refers to selecting and inspecting elements by clicking on the object in the scene. By default only mesh vertices and faces can be selected. Edges, corners, and halfedges, become selectable only once they are used by some quantity, for instance once a per-corner quantity is registered, then it becomes possible to click on corners.
If desired, you can manually override this behavior by calling SurfaceMesh::markEdgesAsUsed()
, to make the structure act as if edges are in use and make the pickable, etc. The same goes for SurfaceMesh::markCornersAsUsed()
and SurfaceMesh::markHalfedgesAsUsed()
. If you mark edges or halfedges as used, you much also set their element ordering as described in the indexing conventions.
Back face policies
The faces of a mesh are implicitly given an outward orientation by the order in which the vertices are listed. The standard convention, which Polyscope respects, is that a counter-clockwise ordering of vertices defines the “outward” direction. Faces which are viewed from behind are referred to as back faces; they can arise when a surface is viewed from the inside, or if a mesh is not properly oriented. Polyscope offers several options for how back faces are displayed.
BackFacePolicy::Identical
all faces are always rendered identically, whether viewed from the front or backBackFacePolicy::Different
back faces are shaded slightly darker, so they can be distinguished (this is the default)BackFacePolicy::Custom
back faces are shaded with a configurable colorBackFacePolicy::Cull
back faces are culled, and not rendered at all
The choice of these policies can be set as an option for each surface mesh structure, either in the GUI via [Options] -> [Back Face Policy]
or programmatically with the function below.
SurfaceMesh* SurfaceMesh::setBackFacePolicy(BackFacePolicy newPolicy)
Set the policy for rendering oppositely-oriented back faces.
newPolicy
is an enum giving the new policy, one ofBackFacePolicy::Identical
,BackFacePolicy::Different
,BackFacePolicy::Custom
, orBackFacePolicy::Cull
as described above
There is also a corresponding getBackFacePolicy()
.
SurfaceMesh* SurfaceMesh::setBackFaceColor(glm::vec3 val)
Set the color to be used for custom back face coloring. Has no effect unless the back face policy is BackFacePolicy::Custom
.
There is also a corresponding getBackFaceColor()
.
Options
See structure management for options common to all structures such as enabling/disabling, transforms, and transparency.
Parameter | Meaning | Getter | Setter | Persistent? |
---|---|---|---|---|
shade smooth | use smooth shading along faces or simple flat faces | bool isSmoothShade() |
setSmoothShade(bool isSmooth) |
yes |
surface color | the color of the mesh | glm::vec3 getSurfaceColor() |
setSurfaceColor(glm::vec3 val) |
yes |
edge color | the color of the edges of the mesh | glm::vec3 getEdgeColor() |
setEdgeColor(glm::vec3 val) |
yes |
edge width | how thick to draw mesh edges, use 0. to disable and 1. for reasonable edges |
double getEdgeWidth() |
setEdgeWidth(double val) |
yes |
material | what material to use | std::string getMaterial() |
setMaterial(std::string name) |
yes |
back face policy | what back face policy to use | BackFacePolicy getBackFacePolicy() |
setBackFacePolicy(BackFacePolicy newPolicy) |
yes |
back face color | back face color for the Custom policy |
BackFacePolicy getBackFaceColor() |
setBackFaceColor(glm::vec3 val) |
yes |
(All setters return this
to support chaining. Structure options return a generic structure pointer, so chain them last.)