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: ILxSurfaceItem interface
         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) User Class: SurfaceItem 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: Declarations
 #define LXa_SURFACEITEM "surfaceItem"
 #define LXu_SURFACEITEM "65EC0E0E-FFD7-48a3-9E20-62EA82EF4728"

Empty SurfaceItem Python user class.

(4) PY: SurfaceItem method
 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: ILxSurface interface
         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) User Class: Surface method
         bool
 GetBin (
         unsigned                 index,
         CLxLoc_SurfaceBin       &bin)
 {
         LXtObjectID              obj;
 
         if (LXx_FAIL (BinByIndex (index, &obj)))
                 return false;
 
         return bin.take (obj);
 }

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

Empty Surface Python user class.

(10) PY: Surface method
 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: ILxSurfaceBin interface
         LXxMETHOD(  LxResult,
 GetBBox) (
         LXtObjectID              self,
         LXtBBox                 *bbox);
 
         LXxMETHOD(  LxResult,
 FrontBBox) (
         LXtObjectID              self,
         const LXtVector          pos,
         const LXtVector          dir,
         LXtBBox                 *bbox);

(12) User Class: SurfaceBin method

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

Empty SurfaceBin Python user class.

(14) PY: SurfaceBin method
 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: ILxCurveGroup interface
         LXxMETHOD(  LxResult,
 GetBBox) (
         LXtObjectID              self,
         LXtBBox                 *bbox);
 
         LXxMETHOD(  LxResult,
 Count) (
         LXtObjectID              self,
         unsigned                *count);
 
         LXxMETHOD(  LxResult,
 ByIndex) (
         LXtObjectID              self,
         unsigned                 index,
         void                   **ppvObj);

(16) User Class: CurveGroup method

Empty CurveGroup Python user class.

(17) PY: CurveGroup method
 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: ILxCurve interface
         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: ILxCurve interface
         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: ILxCurve interface
         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: ILxCurve interface
         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: ILxCurve interface
         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: ILxCurve interface
         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: ILxCurve interface
         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: ILxCurve interface
         LXxMETHOD(  LxResult,
 WalkByAngle) (
         LXtObjectID              self,
         double                   start,
         double                   end,
         double                   angle,
         LXtObjectID              visitor);

(26) User Class: Curve method

Empty Curve Python user class.

(27) PY: Curve method
 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: Declarations
 #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: ILxCurve1 interface
         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);