9
9
* Biological Structures at Stanford, funded under the NIH Roadmap for *
10
10
* Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11
11
* *
12
- * Portions copyright (c) 2008-12 Stanford University and the Authors. *
12
+ * Portions copyright (c) 2008-13 Stanford University and the Authors. *
13
13
* Authors: Peter Eastman *
14
14
* Contributors: Michael Sherman *
15
15
* *
@@ -39,10 +39,11 @@ class PolygonalMeshImpl;
39
39
extern template class PIMPLHandle <PolygonalMesh, PolygonalMeshImpl, true >;
40
40
#endif
41
41
42
- /* * This class provides a description of a mesh made of polygonal faces. Its
43
- primary purpose is for loading geometry from files, which can then be used for
44
- visualization or collision detection. For example, the following lines load
45
- a mesh from a Wavefront OBJ file, then create a DecorativeMesh from it.
42
+ /* * This class provides a description of a mesh made of polygonal faces (not
43
+ limited to triangles). Its primary purpose is for loading geometry from files,
44
+ which can then be used for visualization or collision detection. For example,
45
+ the following lines load a mesh from a Wavefront OBJ file, then create a
46
+ DecorativeMesh from it.
46
47
@code
47
48
PolygonalMesh mesh;
48
49
std::ifstream file;
@@ -53,84 +54,162 @@ a mesh from a Wavefront OBJ file, then create a DecorativeMesh from it.
53
54
@endcode
54
55
You can also read a polygon mesh from a VTK PolyData (.vtp) file.
55
56
56
- We expect this to be a large object so give it shared (reference) semantics; that is,
57
- the copy constructor and copy assignment default to shallow copies (both handles
58
- will refer to the same data). If you want to make a deep (non-shared) copy of a
59
- PolygonalMesh, use the copyAssign() method provided by the PIMPLHandle base class.
60
- **/
57
+ You can also build meshes programmatically, and some static methods are provided
58
+ here for generating some common shapes.
59
+
60
+ The mesh has its own local frame and vertex locations are given in that
61
+ frame. You can scale and transform the vertices relative to that frame
62
+ (changing the values stored in the mesh) but more commonly the mesh will be
63
+ placed on a body relative to that body's frame, meaning you can re-use the
64
+ same mesh in various places.
65
+
66
+ We expect this to be a large object so give it shared (reference) semantics;
67
+ that is, the copy constructor and copy assignment default to shallow copies
68
+ (both handles will refer to the same data). If you want to make a deep
69
+ (non-shared) copy of a PolygonalMesh, use the copyAssign() method provided by
70
+ the PIMPLHandle base class. **/
61
71
class SimTK_SimTKCOMMON_EXPORT PolygonalMesh
62
72
: public PIMPLHandle<PolygonalMesh, PolygonalMeshImpl, true > {
63
73
public:
64
- /* *
65
- * Create a PolygonalMesh, which initially contains no vertices or faces.
66
- */
74
+ /* * Create an empty %PolygonalMesh, with no vertices or faces. **/
67
75
PolygonalMesh () {}
68
76
69
- /* *
70
- * Get the number of faces in the mesh.
71
- */
77
+ /* * TODO: Create a sphere-shaped mesh. **/
78
+ static PolygonalMesh createSphereMesh (Real radius, int resolution);
79
+
80
+ /* * Create a brick-shaped mesh. A brick is a rectangular solid (a box)
81
+ centered at and aligned with the mesh local frame. Note that its size is
82
+ given with \e half dimensions. By default you will just get two mesh faces
83
+ along the longest edge of the brick, with all other edges roughly the same
84
+ size. You can control the mesh density with the \a resolution parameter.
85
+
86
+ @param halfDims
87
+ The half-dimensions of the brick. The extreme vertices are at
88
+ -halfDims and +halfDims, so the brick is centered around the mesh
89
+ local frame.
90
+ @param resolution
91
+ Control for how dense a mesh to produce. For this shape, \a resolution
92
+ is interpreted as the number of extra vertices to insert in the
93
+ \e longest edge of the brick. Extra vertices are inserted into the
94
+ shorter edges if needed to keep the edge lengths approximately
95
+ uniform for every mesh face. \a resolution=0 gives only
96
+ vertices at the corners; the default is 1 meaning that the longest
97
+ edge is split once.
98
+ @return A %PolygonalMesh representing a brick of the requested size.
99
+
100
+ <h3>Controlling the mesh density:</h3>
101
+ If you want a brick mesh where all the edges in the mesh are roughly the
102
+ same length, say \c wantEdgeLength, set \a resolution like this:
103
+ @code
104
+ Real wantEdgeLength = ...;
105
+ Vec3 halfDims = ...;
106
+ int resolution = (int)(max(halfDims)/wantEdgeLength + 0.5);
107
+ @endcode
108
+
109
+ If you want a brick mesh where all the edges are roughly the same length
110
+ as the shortest edge of the brick, just set
111
+ <code>wantEdgeLength=min(halfDims)</code> in the above calculation. **/
112
+ static PolygonalMesh createBrickMesh (const Vec3& halfDims,
113
+ int resolution = 1 );
114
+
115
+ /* * Create a cylinder-shaped mesh, with the long axis in a given
116
+ direction. By default you'll get a 12 sided polygon as the base and
117
+ elements of roughly similar dimension along the edges. You can control the
118
+ mesh density with the \a resolution parameter.
119
+
120
+ @param axis
121
+ The central axis direction of the cylinder, in the mesh local frame.
122
+ This can be provided using the constants XAxis, YAxis, or ZAxis, or
123
+ you can provide a unit vector in any direction.
124
+ @param radius
125
+ The cylinder radius.
126
+ @param halfLength
127
+ Half the length of the cylinder along its axis. The bases are at
128
+ -halfLength and +halfLength along the \a axis, so the cylinder is
129
+ centered around the mesh local frame origin.
130
+ @param resolution
131
+ Control for how dense a mesh to produce (see below for details).
132
+ @return A %PolygonalMesh representing a cylinder of the requested dimensions
133
+ and orientation.
134
+
135
+ <h3>Controlling the mesh density:</h3>
136
+ At resolution 0 the base is a hexagon with six triangular faces, and the
137
+ tube is meshed with quad faces that are about as long
138
+ as the diameter of the base. Resolution 1 (the default) makes the base
139
+ a 12-sided polygon and introduces an intermediate 12-sided polygon of
140
+ have the diameter. There will be triangles in the center still, but
141
+ quad faces between the polygons. The length of the tube faces will be
142
+ reduced to match. Higher resolutions refine the mesh similarly. **/
143
+ static PolygonalMesh createCylinderMesh (const UnitVec3& axis,
144
+ Real radius,
145
+ Real halfLength,
146
+ int resolution=1 );
147
+
148
+ /* * Restore this %PolygonalMesh to its default-constructed state, meaning
149
+ that it will contain no vertices or faces after this call. **/
150
+ void clear ();
151
+
152
+ /* * Get the number of faces in the mesh. **/
72
153
int getNumFaces () const ;
73
- /* *
74
- * Get the number of vertices in the mesh.
75
- */
154
+ /* * Get the number of vertices in the mesh. **/
76
155
int getNumVertices () const ;
77
- /* *
78
- * Get the position of a vertex in the mesh.
79
- *
80
- * @param vertex the index of the vertex to get
81
- * @return the position of the specified vertex
82
- */
156
+
157
+ /* * Get the position of a vertex in the mesh.
158
+ @param vertex The index of the vertex (as returned by addVertex()).
159
+ @return The position of the specified vertex, measured and expressed in
160
+ the mesh local frame. **/
83
161
const Vec3& getVertexPosition (int vertex) const ;
84
- /* *
85
- * Get the number of vertices that make up a face.
86
- *
87
- * @param face the index of the face
88
- */
162
+ /* * Get the number of vertices that make up a particular face.
163
+ @param face The index of the face (as returned by addFace()). **/
89
164
int getNumVerticesForFace (int face) const ;
90
- /* *
91
- * Get the index of one of the vertices of a face.
92
- *
93
- * @param face the index of the face
94
- * @param vertex the index of the vertex within the face
95
- * (from 0, 1, or 2 for a triangular face, etc.)
96
- * @return the index of the specified vertex
97
- */
165
+ /* * Get the index of one of the vertices of a face.
166
+ @param face The index of the face (as returned by addFace()).
167
+ @param vertex The index of the vertex within the face (from 0, 1, or 2
168
+ for a triangular face, etc.) These are ordered the same
169
+ way as when the face was defined.
170
+ @return The index of the specified vertex. **/
98
171
int getFaceVertex (int face, int vertex) const ;
99
- /* *
100
- * Add a vertex to the mesh.
101
- *
102
- * @param position the position of the vertex to add
103
- * @return the index of the newly added vertex
104
- */
172
+
173
+ /* * Add a vertex to the mesh.
174
+ @param position The position of the vertex to add, measured and
175
+ expressed in the mesh local frame.
176
+ @return The index of the newly added vertex. **/
105
177
int addVertex (const Vec3& position);
106
- /* *
107
- * Add a face to the mesh.
108
- *
109
- * @param vertices indices of the vertices which make up the new face
110
- * @return the index of the newly added face
111
- */
178
+
179
+ /* * Add a face to the mesh. Note that the ordering of the vertices defines
180
+ the outward normal for the face; they must be counterclockwise around the
181
+ desired normal.
182
+
183
+ @param vertices Indices of the vertices which make up the new face, in
184
+ counterclockwise order with respect to the face normal.
185
+ @return The index of the newly added face. **/
112
186
int addFace (const Array_<int >& vertices);
113
- /* *
114
- * Scale a mesh by multiplying every vertex by a fixed value.
115
- */
116
- void scaleMesh (Real scale);
117
- /* *
118
- * Transform a mesh by applying a Transform to every vertex.
119
- */
120
- void transformMesh (const Transform& transform);
121
- /* *
122
- * Load a Wavefront OBJ file, adding the vertices and faces it contains
123
- * to this mesh.
124
- *
125
- * @param file an input stream from which to load the file contents
126
- */
187
+
188
+ /* * Scale a mesh by multiplying every vertex by a fixed value. Note that
189
+ this permanently modifies the vertex locations within the mesh. Since the
190
+ vertices are measured in the mesh local frame, scaling will appear to
191
+ occur around the mesh origin (that is, the origin will remain where it
192
+ was while everything else changes.
193
+ @param scale The scale factor. Can be any value except zero.
194
+ @return A reference to this now-scaled mesh object. **/
195
+ PolygonalMesh& scaleMesh (Real scale);
196
+
197
+ /* * %Transform a mesh by applying the given Transform to every vertex,
198
+ leaving the mesh permanently changed. This has the effect of replacing the
199
+ mesh local frame M with a new frame A.
200
+ @param X_AM The transform giving the pose of the mesh local frame in
201
+ the new frame A. Every vertex v_M becomes v_A=X_AM*v_M.
202
+ @return A reference to this now-transformed mesh object. **/
203
+ PolygonalMesh& transformMesh (const Transform& X_AM);
204
+
205
+ /* * Load a Wavefront OBJ file, adding the vertices and faces it contains
206
+ to this mesh.
207
+ @param file An input stream from which to load the file contents. **/
127
208
void loadObjFile (std::istream& file);
128
- /* *
129
- * Load a VTK PolyData (.vtp) file, adding the vertices and faces it
130
- * contains to this mesh.
131
- *
132
- * @param pathname the name of a .vtp file
133
- */
209
+
210
+ /* * Load a VTK PolyData (.vtp) file, adding the vertices and faces it
211
+ contains to this mesh.
212
+ @param pathname The name of a .vtp file. **/
134
213
void loadVtpFile (const String& pathname);
135
214
136
215
private:
0 commit comments