### Mesh Info The LWMeshInfo structure describes the geometry of an object. You can get one of these from the Scene Objects and Object Info globals and from the access structure passed to the displacement handler `evaluate` function. What it contains can vary depending on how and when you obtain it. This structure is defined in the lwmeshes.h header file. Prior to LW9, polygon and vertex normals were not made available through this structure. It was common for plugins to compute those normals themselves. From LW9 onwards, the polygon and vertex normals are available through the meshinfo global. It is strongly encouraged that these functions be used. The way normals are defined may change in future.
       typedef size_t LWPntScanFunc (void *, LWPntID);
       typedef size_t LWPolScanFunc (void *, LWPolID);

       typedef struct st_LWMeshInfo {
          void         *priv;
          void         (*destroy)        (LWMeshInfoID);
          int          (*numPoints)      (LWMeshInfoID);
          int          (*numPolygons)    (LWMeshInfoID);
          size_t       (*scanPoints)     (LWMeshInfoID, LWPntScanFunc *, void *);
          size_t       (*scanPolys)      (LWMeshInfoID, LWPolScanFunc *, void *);
          void         (*pntBasePos)     (LWMeshInfoID, LWPntID, LWFVector);
          void         (*pntOtherPos)    (LWMeshInfoID, LWPntID, LWFVector);
          void *       (*pntVLookup)     (LWMeshInfoID, LWID, const char *);
          int          (*pntVSelect)     (LWMeshInfoID, void *);
          int          (*pntVGet)        (LWMeshInfoID, LWPntID, float *);
          LWID         (*polType)        (LWMeshInfoID, LWPolID);
          int          (*polSize)        (LWMeshInfoID, LWPolID);
          LWPntID      (*polVertex)      (LWMeshInfoID, LWPolID, int);
          const char * (*polTag)         (LWMeshInfoID, LWPolID, LWID);
          int          (*pntVPGet)       (LWMeshInfoID, LWPntID, LWPolID, float *);
          unsigned int (*polFlags)       (LWMeshInfoID, LWPolID);
          int          (*pntVIDGet)      (LWMeshInfoID, LWPntID, float *, void *);
          int          (*pntVPIDGet)     (LWMeshInfoID, LWPntID, LWPolID,
                                            float *, void *);
          int          (*polTypeFlags)   (LWMeshInfoID, LWPolID);
          int          (*polBaseNormal)  (LWMeshInfoID, LWPolID, LWFVector);
          int          (*polOtherNormal) (LWMeshInfoID, LWPolID, LWFVector);
          int          (*pntBaseNormal)  (LWMeshInfoID, LWPolID, LWPntID,
                                            LWFVector);
          int          (*pntOtherNormal) (LWMeshInfoID, LWPolID, LWPntID,
                                            LWFVector);
          LWMeshIteratorID (*createMeshIterator)  (LWMeshInfoID, int);
          void             (*destroyMeshIterator) (LWMeshInfoID, LWMeshIteratorID);
          void*            (*iterateMesh)         (LWMeshInfoID, LWMeshIteratorID);
          void             (*resetMeshIterator)   (LWMeshInfoID, LWMeshIteratorID);
          int              (*setMeshEvent) (LWMeshInfoID, LWMeshEventFunc *, void *);
       } LWMeshInfo;
`priv` An opaque pointer to private data used internally by the mesh info functions. `destroy( meshinfo )` Frees resources allocated by the process that created this LWMeshInfo. Call this when you're finished with the mesh info. Note that this field may be NULL, indicating that you shouldn't attempt to free the mesh info. Test the value of this field before trying to use it. `npts = numPoints( meshinfo )` Returns the number of points in the object. If the object contains dynamically created geometry, e.g. subdivision patches or metaballs, this number may include both the control points and the points created by subdividing. `npols = numPolygons( meshinfo )` Returns the number of polygons in the object, which may include polygons created by subdividing. `result = scanPoints( meshinfo, pointscan_func, mydata )` Enumerate the points in the object. The callback you supply is called for each point in the object. The `mydata` argument is passed to the callback and can be anything it might require. Enumeration stops if your callback returns a non-zero value, and this value is then returned by `scanPoints`. Otherwise it returns 0. LW8.2: 64-bit compatibility by returning size_t; `result = scanPolys( meshinfo, polyscan_func, mydata )` Enumerate the polygons in the object. LW8.2: 64-bit compatibility by returning size_t; `pntBasePos( meshinfo, point, pos )` Get the base, or initial, position of a point. `pntOtherPos( meshinfo, point, pos )` Get an alternate position for the point. This may be the same as the base position or it may be the position of the point after some transformation. The nature of the alternate position depends on how the mesh info was created. `vmap = pntVLookup( meshinfo, vmap_type, vmap_name )` Select a vertex map for reading by `pntVGet`. The vmap is given by its four-character identifier and its name string. The function returns a pointer that can be used later in `pntVSelect` to quickly select this vmap again. The pointer is NULL if no vmap was found with the given ID and name. The Scene Objects global allows you to examine the vmap database and retrieve the names of existing vmaps of a given type. `dim = pntVSelect( meshinfo, vmap )` Select a vmap for reading vectors. The vmap is identified by a pointer returned by `pntVLookup`. The function returns the vmap's dimension (the number of values per point). `ismapped = pntVGet( meshinfo, point, val )` Read the vmap vector for a point. The vector is read from the vmap selected by a previous call to `pntVSelect`. If the point is mapped (has a vmap value in the selected vmap), the `val` array is filled with the vmap vector for the point, and `pntVGet` returns true. The `val` array must have at least as many elements as the number returned by `pntVSelect`. See also `pntVIDGet`. `type = polType( meshinfo, polygon )` Returns the type of a polygon. "Polygon" here refers to a number of different kinds of geometric atoms, including things like curves and bones. The polygon type codes are an extensible set of four-character identifiers. The header file `lwmeshes.h` defines the most common ones: `LWPOLTYPE_FACE` - face `LWPOLTYPE_CURV` - higher order curve `LWPOLTYPE_PTCH` - subdivision control cage polygon `LWPOLTYPE_MBAL` - metaball `LWPOLTYPE_BONE` - bone Do not assume that these are the only polygon types in existence. Restricting an operation to work only on particular polygon types is discouraged. For example, if an operation can only be applied to polygons that are renderable, do not filter out all polygons whose type is face. Instead, use the `polTypeFlags()` meshinfo function to check for the `LWGPTF_SURFACE` flag. `nvert = polSize( meshinfo, polygon )` Returns the number of vertices belonging to the polygon. `point = polVertex( meshinfo, polygon, vert_index )` Returns the point ID for a polygon vertex. Vertex indexes range from 0 to `nvert` - 1. `tagname = polTag( meshinfo, polygon, tagID )` Returns the tag string of the given type associated with the polygon. A null string pointer means that the polygon does not have a tag of that type. `lwmeshes.h` defines the most common polygon tags. `LWPTAG_SURF` The name of the surface applied to the polygon. `LWPTAG_PART` The name of the polygon group the polygon belongs to. `ismapped = pntVPGet( meshinfo, point, polygon, val )` Like `pntVGet`, but reads the per-polygon, or discontinuous, vmap vector for a polygon vertex. See also `pntVPIDGet`. `flags = polFlags( meshinfo, polygon )` Returns the flags associated with the polygon. the `EDPF_CCSTART` and `EDDF_CCEND` bits determine whether the first and last points in `LWPOLTYPE_CURV` polygons are control points rather than actual vertices. (The constants for these flags are defined in lwmeshedt.h.) `ismapped = pntVIDGet( meshinfo, point, val, vmap ) ismapped = pntVPIDGet( meshinfo, point, polygon, val, vmap )` Like `pntVGet` and `pntVPGet`, but these take the vertex map ID as an additional argument, so that it isn't necessary to first call `pntVSelect` to select the vertex map. This is important when your plug-in might be running in multiple threads, since the thread may change between the `pntVSelect` call and the `pntVGet` or `pntVPGet` calls. `flags = polTypeFlags( meshinfo, polygon )` (LW9.0+) Returns the polytype flags of the polytype associated with the polygon. See the polygon handler documentation for a list and explanation of the flags. `hasnormal = polBaseNormal( meshinfo, polygon, normal )` (LW9.0+) Get the base normal of a polygon. Returns 1 if the polygon has a valid normal, 0 otherwise. `hasnormal = polOtherNormal( meshinfo, polygon, normal )` (LW9.0+) Get the alternate normal of a polygon. Returns 1 if the polygon has a valid normal, 0 otherwise. `hasnormal = pntBaseNormal( meshinfo, polygon, point, normal )` (LW9.0+) Get the base normal of a vertex. If the polygon ID is defined, the normal will be calculated taking surface smoothness parameters and the surrounding polygons into account. If the polygon ID is not defined (0), an averaged normal of the surrounding polygons is computed. Returns 1 if the vertex has a valid normal, returns 2 if the normal is not smoothed, 0 for an invalid normal. `hasnormal= pntOtherNormal( meshinfo, polygon, point, normal )` (LW9.0+) Get the alternate normal of a vertex. If the polygon ID is defined, the normal will be calculated taking surface smoothness parameters and the surrounding polygons into account. If the polygon ID is not defined (0), an averaged normal of the surrounding polygons is computed. Returns 1 if the vertex has a valid normal, returns 2 if the normal is not smoothed, 0 for an invalid normal. `iterator= createMeshIterator( meshinfo, type )` (LW9.0+) Create a new mesh iterator of a given type. The iterator can be used to enumerate all the elements of the given type of a mesh. The type is one of: `LWMESHITER_POLYGON` - an iterator over all polygons of the mesh `LWMESHITER_POINT` - an iterator over all vertices of the mesh `destroyMeshIterator( meshinfo, iterator )` (LW9.0+) Destroy an iterator of the mesh. All iterators that are created for the mesh must be destroyed when no longer needed. `element = iterateMesh( meshinfo, iterator )` (LW9.0+) Return the next element of the mesh iterator. The type of the returned element depends on the iterator type: `LWMESHITER_POLYGON` - returns an LWPolID `LWMESHITER_POINT` - returns an LWPntID If there is no next element, NULL is returned. `resetMeshIterator( meshinfo, iterator )` (LW9.0+) Resets an iterator of the mesh. A subsequent call of `iterateMesh()` will return the first element. `result = setMeshEvent( meshinfo, eventFunc, userData )` (LW9.2.1+) Sets a callback for mesh event notifications. When something happens to the mesh, the `eventFunc` function is called with `userData` as its first argument. If the function is set to NULL, the callback on the mesh previously associated with the `userData` is removed. The `userData` is used to uniquely identify the owner of a callback, and should not be NULL, so that more than one callback can be set on a mesh. The result is zero if the operation failed, non-zero otherwise. Event Callback The `setMeshEvent` function lets you set a callback that will be called when certain things happen to a mesh:
       typedef int (*LWMeshEventFunc) (void* userData, LWMeshInfoID mesh,
          LWMeshEvent event, void* eventData);
`userData` is what was passed to `setMeshEvent` function. The `eventData` depends on the event. The following events are currently defined:
       LWMESHEVNT_DESTROY
The `DESTROY` event occurs when the mesh is destroyed by LightWave®. No event data is associated with this event. Reasons for the mesh being destroyed include, but is not limited to, the user changing the subdivision level of a mesh, changing the subdivision order, deletion of a mesh, or any other operation that may change the structure of the mesh. Note that it is unwise to attempt to re-acquire the mesh of an object during the event. Wait until the plugin's `evaluate`, `newTime` or similar is called. Otherwise the object is likely to not have a valid mesh. Example The SceneScan sample uses an LWMeshInfo obtained from the Object Info global to build arrays of points and polygons for an object, including vmap and surface data. See the `getObjectDB` function in `objectdb.c`.