surface (lx_surface.hpp)

From The Foundry MODO SDK wiki
Jump to: navigation, search
There are security restrictions on this page


Surfaces

Surfaces are partitioned into groups of elementary geometric primitives (usually polygons). These groups are called bins and the process of partitioning a surface into bins is called binning. The surface segmentation is decided by the shader tree masking, so binning needs to be updated any time the masking configuration changes.

Surface Item Interfaces

ILxSurfaceItem

All item types that produce a surface can be queried for their ILxSurfaceItem interface.

GetSurface returns the ILxSurface object, 'morph' should be set if the client is intertested in the morphed surface.
Prepare adds the channels for the surface modifier and
Evaluate evaluates the surface.
(1) SDK: SurfaceItem::GetSurface, etc.
         LXxMETHOD(  LxResult,
 GetSurface) (
         LXtObjectID              self,
         LXtObjectID              chanRead,
         unsigned                 morph,
         void                   **ppvObj);
 
         LXxMETHOD( LxResult,
 Prepare) (
         LXtObjectID              self,
         LXtObjectID              eval,
         unsigned                *index);
 
         LXxMETHOD( LxResult,
 Evaluate) (
         LXtObjectID              self,
         LXtObjectID              attr,
         unsigned                 index,
         void                   **ppvObj);

(2) SDK: CLxUser_SurfaceItem::AllocSurf method
         bool
 AllocSurf (
         ILxUnknownID             chanRead,
         bool                     morph,
         CLxLoc_Surface          &surf)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (GetSurface (chanRead, morph ? 1 : 0, &obj)))
                 return false;
 
         return surf.take (obj);
 }
 
         bool
 AllocSurf (
         ILxUnknownID             attr,
         unsigned                 index,
         CLxLoc_Surface          &surf)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (Evaluate (attr, index, &obj)))
                 return false;
 
         return surf.take (obj);
 }

(3) SDK: LXa_SURFACEITEM, etc. defines
 #define LXa_SURFACEITEM "surfaceItem"
 #define LXu_SURFACEITEM "65EC0E0E-FFD7-48a3-9E20-62EA82EF4728"

Empty SurfaceItem Python user class.

(4) PY: empty SurfaceItem user class
 pass

ILxSurface

Surface objects have a number of properties that can be queried with the ILxBinnedSurface interface.

GetBBox returns the surface bounding box.
FrontBBox sets the front bounding box for that bin. The 'front' bounding box is formed by the geometry facing the viewer given by its position and direction vectors.
RayCast casts a ray on the surface.

The input is the rayInfo structure which holds the position & direction of the ray plus some optional settings. 'cull' must be true to cull hidden geometry, 'half' only raycasts the geoemtry in front of the viewer and 'vmapName' must be set to calculate the UVs (or other vmap values) at the hit point.

(5) SDK: LXtRayInfo struct
 LXtVector                pos;
 LXtVector                dir;
 unsigned                 cull;
 unsigned                 half;
 const char              *vmapName;
 LXtID4                   vmapType;

The output is the rayHIt stucture. pos & nrm are the position and normal vectors at the hit point. 'dist' is the distance along the ray, 'uvw' are the vmap values if 'vmap' is set in the input and 'bin' is the hit bin.

(6) SDK: LXtRayHit struct
 LXtVector                pos;
 LXtVector                nrm;
 LXtVector                uvw;
 double                   dist;
 void                    *bin;
 LXtPolygonID             polygon;

BinCount returns the number of bins on a surface.
BinByIndex returns the ILxSurfaceBin object by its index in the surface.
TagCount returns the number of string tags per tag type
TagByIndex returns the string tag interface given by its type and index in the list.
GLCount returns the number of GL polygons displayed by the surface.
(7) SDK: Surface::GetBBox, etc.
         LXxMETHOD(  LxResult,
 GetBBox) (
         LXtObjectID              self,
         LXtBBox                 *bbox);
 
         LXxMETHOD(  LxResult,
 FrontBBox) (
         LXtObjectID              self,
         const LXtVector          pos,
         const LXtVector          dir,
         LXtBBox                 *bbox);
 
         LXxMETHOD(  LxResult,
 RayCast) (
         LXtObjectID              self,
         const LXtRayInfo        *ray,
         LXtRayHit               *hit);
 
         LXxMETHOD(  LxResult,
 BinCount) (
         LXtObjectID              self,
         unsigned int            *count);
 
         LXxMETHOD( LxResult,
 BinByIndex) (
         LXtObjectID              self,
         unsigned int             index,
         void                   **ppvObj);
 
         LXxMETHOD(  LxResult,
 TagCount) (
         LXtObjectID              self,
         LXtID4                   type,
         unsigned int            *count);
 
         LXxMETHOD( LxResult,
 TagByIndex) (
         LXtObjectID              self,
         LXtID4                   type,
         unsigned int             index,
         const char              **stag);
 
         LXxMETHOD( LxResult,
 GLCount) (
         LXtObjectID              self,
         unsigned int            *count);

(8) SDK: CLxUser_Surface::GetBin method
         bool
 GetBin (
         unsigned                 index,
         CLxLoc_SurfaceBin       &bin)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (BinByIndex (index, &obj)))
                 return false;
 
         return bin.take (obj);
 }

(9) SDK: LXa_SURFACE, etc. defines
 #define LXa_SURFACE     "surface"
 #define LXu_SURFACE     "75006BDB-93F7-4a41-8B8C-E710D80D3F1A"

Empty Surface Python user class.

(10) PY: empty Surface user class
 pass

ILxSurfaceBin

Finally we have surface bins which represents a segment of the surface with the same tags and thus the same shader.

GetBBox sets the bounding box for that bin
FrontBBox sets the front bounding box for that bin. The 'front' bounding box is formed by the geometry facing the viewer given by its position and direction vectors.

The surface bin object should also present an ILxStringTags interface to get the polygon tags on the bin for shader tree masking, and an ILxTableauSurface interface to allow the surface to be sampled into a triangle soup.

(11) SDK: SurfaceBin::GetBBox, etc.
         LXxMETHOD(  LxResult,
 GetBBox) (
         LXtObjectID              self,
         LXtBBox                 *bbox);
 
         LXxMETHOD(  LxResult,
 FrontBBox) (
         LXtObjectID              self,
         const LXtVector          pos,
         const LXtVector          dir,
         LXtBBox                 *bbox);

(12) SDK: empty SurfaceBin User Class

(13) SDK: LXa_SURFACEBIN, etc. defines
 #define LXa_SURFACEBIN  "surfaceBin"
 #define LXu_SURFACEBIN  "48B534C1-7B7C-4147-ADBC-154850898E7F"

Empty SurfaceBin Python user class.

(14) PY: empty SurfaceBin user class
 pass

Curves

Any item can present itself as a group of curves. The bounding box and count of curves can be read from the root object, and curve accessors can be allocated for each one by index.

(15) SDK: CurveGroup::GetBBox, etc.
         LXxMETHOD(  LxResult,
 GetBBox) (
         LXtObjectID              self,
         LXtBBox                 *bbox);
 
         LXxMETHOD(  LxResult,
 Count) (
         LXtObjectID              self,
         unsigned                *count);
 
         LXxMETHOD(  LxResult,
 ByIndex) (
         LXtObjectID              self,
         unsigned                 index,
         void                   **ppvObj);

(16) SDK: empty CurveGroup User Class

Empty CurveGroup Python user class.

(17) PY: empty CurveGroup user class
 pass

The curve accessor allows the client to read the attributes and shape of the curve. It also has StringTag interface for bin tags. The bounding box and length are gross features.

(18) SDK: Curve::GetBBox, etc.
         LXxMETHOD(  LxResult,
 GetBBox) (
         LXtObjectID              self,
         LXtBBox                 *bbox);
 
         LXxMETHOD(  double,
 Length) (
         LXtObjectID              self);

If the curve is piecewise cubic, the spline segments can be read as Bezier control points. If the curve is not a spline then Count() returns NOTFOUND.

(19) SDK: Curve::SplineCount, etc.
         LXxMETHOD(  LxResult,
 SplineCount) (
         LXtObjectID              self,
         unsigned                *count);
 
         LXxMETHOD(  LxResult,
 SplineByIndex) (
         LXtObjectID              self,
         unsigned                 index,
         LXtVector                b0,
         LXtVector                b1,
         LXtVector                b2,
         LXtVector                b3);

Curves can also be parameteric. In that case they aren't made of splines, but we want to know aproximately how many bends they have in case we need to sample it and capture the shape. A bend is a flex in the curve, and we're counting how many of them there are relative to the parameterization. For piecewise cubic curves this is twice the number of splines.

(20) SDK: Curve::BendCount
         LXxMETHOD(  unsigned,
 BendCount) (
         LXtObjectID              self);

Points along the curve are read by setting the parameter for the curve to a value between 0 and 1. The parameter can also be set by the fraction of the curve's total length.

(21) SDK: Curve::Param, etc.
         LXxMETHOD(  double,
 Param) (
         LXtObjectID              self);
 
         LXxMETHOD(  LxResult,
 SetParam) (
         LXtObjectID              self,
         double                   param);
 
         LXxMETHOD(  double,
 LenFraction) (
         LXtObjectID              self);
 
         LXxMETHOD(  LxResult,
 SetLenFraction) (
         LXtObjectID              self,
         double                   frac);

The position and tangent can then be read. The position is in world coordinates and the tangent is the rate of change relative to the parameter.

(22) SDK: Curve::Position, etc.
         LXxMETHOD(  LxResult,
 Position) (
         LXtObjectID              self,
         LXtVector                pos);
 
         LXxMETHOD(  LxResult,
 Tangent) (
         LXtObjectID              self,
         LXtVector                tan);

This finds the closest point on the curve at the probe position. Results are returned as the parameter value, the position on the curve, and the normal to the curve in the direction of the probe.

(23) SDK: Curve::Closest
         LXxMETHOD(  LxResult,
 Closest) (
         LXtObjectID              self,
         const LXtVector          probe,
         double                  *param,
         LXtVector                pos,
         LXtVector                norm);

This returns LXe_TRUE or LXe_FALSE, depending on whether the curve is closed or not.

(24) SDK: Curve::IsClosed
         LXxMETHOD(  LxResult,
 IsClosed) (
         LXtObjectID              self);

Walking the Curve

Sometimes, it can be useful to walk a curve from a start point to an end point, based on an angle. Samples will be placed along the curve where the angle deviation from the last sample is greater than the threshold angle.

(25) SDK: Curve::WalkByAngle
         LXxMETHOD(  LxResult,
 WalkByAngle) (
         LXtObjectID              self,
         double                   start,
         double                   end,
         double                   angle,
         LXtObjectID              visitor);

(26) SDK: empty Curve User Class

Empty Curve Python user class.

(27) PY: empty Curve user class
 pass

Items declare that they can provide curves with a package tag giving the name of the curve channel. Read in an evaluated context, this will be an ValueReference object channel holding the curve group object.

(28) SDK: LXu_CURVEGROUP, etc. defines
 #define LXu_CURVEGROUP          "20F1B298-84E2-4DA2-BA66-8883B4B0D7FF" 
 #define LXsPKG_CURVES_CHANNEL   "curveGroup.channel"
 
 #define LXu_CURVE               "1A832950-B71E-4BCB-8D56-46ECE4F5BC3F"
 #define LXa_CURVE               "curve2"

ILxCurve1 (Legacy Interface)

This interface was retired in modo 901, and was replaced with an updated one that added a few more methods.

(29) SDK: Curve1::GetBBox, etc.
         LXxMETHOD(  LxResult,
 GetBBox) (
         LXtObjectID              self,
         LXtBBox                 *bbox);
 
         LXxMETHOD(  double,
 Length) (
         LXtObjectID              self);
 
         LXxMETHOD(  LxResult,
 SplineCount) (
         LXtObjectID              self,
         unsigned                *count);
 
         LXxMETHOD(  LxResult,
 SplineByIndex) (
         LXtObjectID              self,
         unsigned                 index,
         LXtVector                b0,
         LXtVector                b1,
         LXtVector                b2,
         LXtVector                b3);
 
         LXxMETHOD(  unsigned,
 BendCount) (
         LXtObjectID              self);
 
         LXxMETHOD(  double,
 Param) (
         LXtObjectID              self);
 
         LXxMETHOD(  LxResult,
 SetParam) (
         LXtObjectID              self,
         double                   param);
 
         LXxMETHOD(  LxResult,
 SetLenFraction) (
         LXtObjectID              self,
         double                   frac);
 
         LXxMETHOD(  LxResult,
 Position) (
         LXtObjectID              self,
         LXtVector                pos);
 
         LXxMETHOD(  LxResult,
 Tangent) (
         LXtObjectID              self,
         LXtVector                tan);
 
         LXxMETHOD(  LxResult,
 Closest) (
         LXtObjectID              self,
         const LXtVector          probe,
         double                  *param,
         LXtVector                pos,
         LXtVector                norm);