Tableau (lx-tableau.hpp)
Contents
- 1 Tableau
- 1.1 (1) SDK: Tableau::Time, etc.
- 1.2 (2) SDK: Tableau::Channels
- 1.3 (3) SDK: LXiTBX_CHANS_T0, etc. defines
- 1.4 (4) SDK: Tableau::Visible
- 1.5 (5) SDK: Tableau::FindShader
- 1.6 (6) SDK: Tableau::InstanceItem
- 1.7 (7) SDK: Tableau::Update, etc.
- 1.8 (8) SDK: LXiTBX_SURF_ADD, etc. defines
- 1.9 (9) SDK: LXiTBX_INST_ADD, etc. defines
- 1.10 (10) SDK: Tableau::AddInstanceItem
- 1.11 (11) SDK: Tableau::AddInstanceableElement
- 1.12 (12) SDK: LXu_TABLEAU define
- 1.13 (13) SDK: CLxUser_Tableau::Time0 method
- 1.14 (14) PY: empty Tableau user class
- 1.15 3D Elements
- 1.15.1 (15) SDK Common: Element methods
- 1.15.2 (16) SDK: Types
- 1.15.3 (17) SDK: LXe_INFINITE_BOUND define
- 1.15.4 (18) SDK Common: Element methods
- 1.15.5 (19) SDK: LXiTBLX_BASEFEATURE, etc. defines
- 1.15.6 (20) SDK: ILxTableauElement interface
- 1.15.7 (21) SDK: empty TableauElement User Class
- 1.15.8 (22) PY: empty TableauElement user class
- 1.15.9 (23) SDK: LXu_TABLEAUELEMENT, etc. defines
- 1.15.10 Surfaces
- 1.15.10.1 (24) SDK: TableauSurface::Sample
- 1.15.10.2 (25) SDK: TableauSurface::Padding
- 1.15.10.3 (26) SDK: TableauSurface::SegmentBox
- 1.15.10.4 (27) SDK: LXeTBLXSURF_ADAPTIVE define
- 1.15.10.5 (28) SDK: empty TableauSurface User Class
- 1.15.10.6 (29) PY: empty TableauSurface user class
- 1.15.10.7 (30) SDK: TriangleSoup::TestBox, etc.
- 1.15.10.8 (31) SDK: LXiTBLX_SEG_POINT, etc. defines
- 1.15.10.9 (32) SDK: TriangleSoup::Vertex, etc.
- 1.15.10.10 (33) SDK: TriangleSoup::Connect
- 1.15.10.11 (34) PY: empty TriangleSoup user class
- 1.15.10.12 (35) SDK: LXiTBLX_CONNECT_QUAD, etc. defines
- 1.15.10.13 (36) SDK: CLxUser_TriangleSoup::Quad method
- 1.15.10.14 (37) SDK: LXu_TABLEAUSURFACE, etc. defines
- 1.15.11 Volumes
- 1.15.12 Lights
- 1.15.12.1 (42) SDK: TableauLight::Sample, etc.
- 1.15.12.2 (43) PY: empty TableauLight user class
- 1.15.12.3 (44) SDK: LightSample::Vertex
- 1.15.12.4 (45) SDK: LXu_TABLEAULIGHT, etc. defines
- 1.15.12.5 (46) PY: empty LightSample user class
- 1.15.12.6 (47) SDK: LXpLightQuality struct
- 1.15.12.7 (48) SDK: LXpLightShadowing struct
- 1.15.12.8 (49) SDK: LXpLightSource struct
- 1.15.12.9 (50) SDK: LXpLightColor struct
- 1.15.12.10 (51) SDK: LXsP_LGT_QUALITY, etc. defines
- 1.15.12.11 (52) SDK: LXs_FX_LIGHTCOLOR, etc. defines
- 1.15.12.12 (53) SDK: LXs_FX_VOLSCATTER, etc. defines
- 1.15.13 Proxies
- 1.15.14 Instances
- 1.15.14.1 (57) SDK: TableauInstance::Properties
- 1.15.14.2 (58) SDK: TableauInstance::GetTransform
- 1.15.14.3 (59) SDK: TableauInstance::GetDissolve
- 1.15.14.4 (60) SDK: TableauInstance::ParticleDescription, etc.
- 1.15.14.5 (61) SDK: LXu_TABLEAUINSTANCE, etc. defines
- 1.15.14.6 (62) SDK: empty TableauInstance User Class
- 1.15.14.7 (63) PY: empty TableauInstance user class
- 1.16 Shaders
- 1.17 Environment
- 1.17.1 (70) SDK: LXpCameraRay struct
- 1.17.2 (71) SDK: LXpEnvInfiniteColor struct
- 1.17.3 (72) SDK: LXpEnvVisibility struct
- 1.17.4 (73) SDK: LXpEnvShape struct
- 1.17.5 (74) SDK: LXpEnvFog struct
- 1.17.6 (75) SDK: LXpGlobalLighting struct
- 1.17.7 (76) SDK: LXpGlobalDisplacement struct
- 1.17.8 (77) SDK: LXpGlobalIndirect struct
- 1.17.9 (78) SDK: LXpGlobalCaustics struct
- 1.17.10 (79) SDK: LXpGlobalRendering struct
- 1.17.11 (80) SDK: LXsP_CAM_RAY, etc. defines
- 1.18 Camera
- 1.19 Filters
- 1.20 Item Interface
- 1.20.1 (90) SDK: LXfTBLX_PREVIEW_UPDATE_NONE, etc. defines
- 1.20.2 (91) SDK: LXiTBXELT_SURFACE, etc. defines
- 1.20.3 (92) SDK: TableauSource::Elements, etc.
- 1.20.4 (93) SDK: LXu_TABLEAUSOURCE define
- 1.20.5 (94) PY: empty TableauSource user class
- 1.20.6 (95) SDK: LXu_INSTANCEABLE, etc. defines
- 1.20.7 (96) SDK: Instanceable::Compare
- 1.20.8 (97) SDK: Instanceable::AddElements
- 1.20.9 (98) SDK: Instanceable::GetSurface
- 1.21 Tableau Service
- 1.22 Nodal Service
- 1.23 Tableau Event Translator
Tableau
A Tableau is a snapshot of the 3D scene, partially frozen in time and suitable for rendering. It consists of a collection of various types of elements such as surfaces, volumes, lights, and filters which all contribute to the final rendered appearance. A tableau is created by traversing the item database.
Tableaus have a start time and duration interval, and method for adding new elements or instances of existing elements. This interface is provided mainly so clients can add elements to populate the tableau, so this does not give full access.
(1) SDK: Tableau::Time, etc.
LXxMETHOD( LxResult, Time) ( LXtObjectID self, float *t0, float *interval); LXxMETHOD( LxResult, AddElement) ( LXtObjectID self, LXtObjectID element, LXtObjectID shader); LXxMETHOD( LxResult, AddInstance) ( LXtObjectID self, LXtObjectID inst, LXtObjectID element, LXtObjectID shader);
Get a ChannelRead object for subframe times: 'type' is 0,1,2 for t0, t1 and frame time.
(2) SDK: Tableau::Channels
LXxMETHOD( LxResult, Channels) ( LXtObjectID self, unsigned type, void **ppvObj);
(3) SDK: LXiTBX_CHANS_T0, etc. defines
#define LXiTBX_CHANS_T0 0 #define LXiTBX_CHANS_T1 1 #define LXiTBX_CHANS_FRAME 2
Returns LXe_TRUE for items that are visible in this tableau.
(4) SDK: Tableau::Visible
LXxMETHOD ( LxResult, Visible) ( LXtObjectID self, LXtObjectID item);
Get a tableau shader given an item and string tags for material tags.
(5) SDK: Tableau::FindShader
LXxMETHOD( LxResult, FindShader) ( LXtObjectID self, LXtObjectID item, LXtObjectID tags, void **ppvObj);
Return a peek of the item currently being instanced.
(6) SDK: Tableau::InstanceItem
LXxMETHOD( LXtObjectID, InstanceItem) ( LXtObjectID self);
These events are used for incremental updates to the tableau.
Update takes in a visitor, which acts as a callback to update the tableau data. When the tableau is "safe", such as when the render is stopped, it will perform the update. The "immediate" argument is whether or not the tableau contains dangerous / invalid data, in which case any tableau clients need to stop / abort immediately
The tableau will add-ref and release the visitor when it's done, so the client doesn't need to keep a reference around.
UpdateAll tells the tableau that it needs to be completely invalidated and rebuilt.
EltNotify notifies clients of the tableau (like the render caches) that a tableau element has changed. It takes in the element object (which the tableau source should have retained) and the event indicating what's changed.
InstNotify is effectively the same.
(7) SDK: Tableau::Update, etc.
LXxMETHOD( LxResult, Update) ( LXtObjectID self, LXtObjectID visitor, int immediate); LXxMETHOD( LxResult, UpdateAll) ( LXtObjectID self); LXxMETHOD( LxResult, EltNotify) ( LXtObjectID self, LXtObjectID element, int event); LXxMETHOD( LxResult, InstNotify) ( LXtObjectID self, LXtObjectID instance, int event);
EltNotify can have the following events.
(8) SDK: LXiTBX_SURF_ADD, etc. defines
#define LXiTBX_SURF_ADD 0x0 #define LXiTBX_SURF_REMOVE (LXiTBX_SURF_ADD + 1) #define LXiTBX_SURF_GEO (LXiTBX_SURF_REMOVE + 1) #define LXiTBX_SURF_XFRM (LXiTBX_SURF_GEO + 1) #define LXiTBX_SURF_SHADER (LXiTBX_SURF_XFRM + 1) #define LXiTBX_LGT_ADD (LXiTBX_SURF_SHADER + 1) #define LXiTBX_LGT_REMOVE (LXiTBX_LGT_ADD + 1) #define LXiTBX_LGT_DATA (LXiTBX_LGT_REMOVE + 1) #define LXiTBX_LGT_XFRM (LXiTBX_LGT_DATA + 1) #define LXiTBX_LGT_SHADER (LXiTBX_LGT_XFRM + 1) #define LXiTBX_LGT_GEO (LXiTBX_VOL_SHADER + 1) #define LXiTBX_VOL_ADD (LXiTBX_LGT_SHADER + 1) #define LXiTBX_VOL_REMOVE (LXiTBX_VOL_ADD + 1) #define LXiTBX_VOL_DATA (LXiTBX_VOL_REMOVE + 1) #define LXiTBX_VOL_XFRM (LXiTBX_VOL_DATA + 1) #define LXiTBX_VOL_SHADER (LXiTBX_VOL_XFRM + 1)
And InstNotify has a smaller set of events.
(9) SDK: LXiTBX_INST_ADD, etc. defines
#define LXiTBX_INST_ADD 0x0 #define LXiTBX_INST_REMOVE (LXiTBX_INST_ADD + 1) #define LXiTBX_INST_XFRM (LXiTBX_INST_REMOVE + 1)
This allows clients to add instance of other items, not just their own elements. This takes the item to be instanced (inst), the item doing the instacing (from), the TableauInstance object giving the transforms for the item. The final arguments give a TableauVertex for particle features and an array of those features, and can both be null if there are no particle features for the instance.
(10) SDK: Tableau::AddInstanceItem
LXxMETHOD( LxResult, AddInstanceItem) ( LXtObjectID self, LXtObjectID instItem, LXtObjectID fromItem, LXtObjectID inst, LXtObjectID vdesc, const float *vertex);
Items that provide an instanceable object channel call this method to define the elements that make up the item. The element is the TableauElement to be added and the tags are the string tags to be used for getting shaders for this element. Both objects are often the same.
(11) SDK: Tableau::AddInstanceableElement
LXxMETHOD( LxResult, AddInstanceableElement) ( LXtObjectID self, LXtObjectID elt, LXtObjectID tags);
(12) SDK: LXu_TABLEAU define
#define LXu_TABLEAU "76C4EDD9-5FF9-4342-BB08-EFCD0B344004"
(13) SDK: CLxUser_Tableau::Time0 method
float Time0 (void) { float t0, dt; Time (&t0, &dt); return t0; } float Time1 (void) { float t0, dt; Time (&t0, &dt); return t0 + dt; } bool IsVisible ( ILxUnknownID item) { return (Visible (item) == LXe_TRUE) ? true : false; } bool GetShader ( CLxLoc_TableauShader &shader, ILxUnknownID item, ILxUnknownID tags) { LXtObjectID obj; if (LXx_FAIL (FindShader (item, tags, &obj))) return false; return shader.take (obj); } bool GetChannels ( CLxLoc_ChannelRead &chan, unsigned type) { LXtObjectID obj; if (LXx_FAIL (Channels (type, &obj))) return false; return chan.take (obj); } LxResult VisitorUpdate ( CLxImpl_AbstractVisitor *visitor, int immediate) { CLxInst_OneVisitor<CLxGenericVisitor> gv; gv.loc.vis = visitor; return Update (gv, immediate); }
Empty Tableau Python user class.
(14) PY: empty Tableau user class
pass
3D Elements
Every element should provide some bound on its location in model space. This is given as an axis-aligned bounding box encoded as a six-element vector, where the first triple is the lower corner and second is the upper corner. Elements may also indicate that they have an infinite bound.
Note: this should *not* return an error code unless there is a serious error. A missing element should return LXe_OK with zero for all bounds.
(15) SDK Common: Element methods
LXxMETHOD( LxResult, Bound) ( LXtObjectID self, LXtTableauBox bbox);
(16) SDK: Types
typedef float LXtTableauBox[6];
(17) SDK: LXe_INFINITE_BOUND define
#define LXe_INFINITE_BOUND LXxGOODCODE(LXeSYS_REND,1)
Query for vertex data, like generalized VMaps. All elements can also have a vertex description selected, which should match available features.
(18) SDK Common: Element methods
LXxMETHOD( unsigned int, FeatureCount) ( LXtObjectID self, LXtID4 type); LXxMETHOD( LxResult, FeatureByIndex) ( LXtObjectID self, LXtID4 type, unsigned int index, const char **name); LXxMETHOD( LxResult, SetVertex) ( LXtObjectID self, LXtObjectID vdesc);
This feature type and set of names define the most basic set of features that most elements support. Velocity is in object space. Normals exist only for surface samples, and radius is meaningful only for line samples.
(19) SDK: LXiTBLX_BASEFEATURE, etc. defines
#define LXiTBLX_BASEFEATURE LXxID4(' ','v','r','t') #define LXsTBLX_FEATURE_POS "pos" #define LXsTBLX_FEATURE_OBJPOS "opos" #define LXsTBLX_FEATURE_VEL "vel" #define LXsTBLX_FEATURE_NORMAL "norm" #define LXsTBLX_FEATURE_RADIUS "rad" #define LXsTBLX_FEATURE_PARAM_LENGTH "plen" #define LXsTBLX_FEATURE_PARTID "partID" #define LXsTBLX_FEATURE_RADIANCE "radiance" #define LXsTBLX_FEATURE_TENSION "tension" #define LXsTBLX_FEATURE_TORSION "torsion" #define LXiTBLX_DPDU LXxID4('d','p','d','u') #define LXiTBLX_TBASIS LXxID4('T','B','A','S')
(20) SDK: ILxTableauElement interface
''[[#C15|SDK Common: Element methods]]''
(21) SDK: empty TableauElement User Class
Empty TableauElement Python user class.
(22) PY: empty TableauElement user class
pass
(23) SDK: LXu_TABLEAUELEMENT, etc. defines
#define LXu_TABLEAUELEMENT "71D90AD9-3E30-4CE8-9E2B-F70DA281B2DC" #define LXa_TABLEAUELEMENT "tableauElement"
Surfaces
2D surface elements are 3D elements that interact with the renderer as a pool of triangles. The Sample() method is called with a bounding box that intersects the surface element, a feature scale, and an interface to collect triangles. The scale parameter gives an approximate edge length scale that is used to determine surface dicing. The vertex vector description should already have been set for this element.
(24) SDK: TableauSurface::Sample
''[[#C15|SDK Common: Element methods]]'' LXxMETHOD( LxResult, Sample) ( LXtObjectID self, const LXtTableauBox bbox, float scale, LXtObjectID trisoup);
Surface elements can also provide a padding distance that will be added to the bounding box. In general this will be zero but certain surfaces need to add an extra padding. For example surfaces modeling hair may need to set the padding distance as the maximum length of hair guides.
(25) SDK: TableauSurface::Padding
LXxMETHOD( LxResult, Padding) ( LXtObjectID self, float *dist);
The bounding boxes of individual segments can be read. The client need to get the segment IDs by sampling the surface, but once given they can be passed to this function. If it return any error (incluing not-impl) the client should assume that no box is available.
(26) SDK: TableauSurface::SegmentBox
LXxMETHOD( LxResult, SegmentBox) ( LXtObjectID self, unsigned int segID, LXtTableauBox bbox);
The Bound() method for surfaces (since it cannot return "infinite") may also return a success code indicating that the surface supports adaptive subdivision.
(27) SDK: LXeTBLXSURF_ADAPTIVE define
#define LXeTBLXSURF_ADAPTIVE LXxGOODCODE(LXeSYS_REND,2)
(28) SDK: empty TableauSurface User Class
Empty TableauSurface Python user class.
(29) PY: empty TableauSurface user class
pass
A triangle "soup" consists of unconnected triangles grouped into segments. The idea of a soup is that although triangles may border on each other and share normals at those borders, there is no connectivity information in the data structure. What we have is just a big batch of triangles and it's up to the renderer to assure that any transformations it applies will maintain continuity. While this places definite limitations on the renderer, it also makes it much easier to deal with gigantic meshes since they can be processed in arbitrarily small units.
The triangle soup interface is passed to the surface object from the renderer, and the surface has the job of generating all the triangles that intersect the bounding box. The triangles are grouped into segments by the surface, each with a unique ID code. Before sending a segment the surface calls the Segment() method with the ID, and the renderer can return LXe_TRUE or LXe_FALSE. If false the segment is skipped, which allows the renderer to cache segments and only update them as needed. Each segment can contain either points, lines, or triangles.
(30) SDK: TriangleSoup::TestBox, etc.
LXxMETHOD( unsigned int, TestBox) ( LXtObjectID self, const LXtTableauBox bbox); LXxMETHOD( LxResult, Segment) ( LXtObjectID self, unsigned int segID, unsigned int type);
(31) SDK: LXiTBLX_SEG_POINT, etc. defines
#define LXiTBLX_SEG_POINT 1 #define LXiTBLX_SEG_LINE 2 #define LXiTBLX_SEG_TRIANGLE 3
Within each segment the surface calls Vertex() and Polygon() any number of times in any combination. Each call to Vertex() takes the vector of floats which define the vertex, and the vertices in the fragment are numbered starting from zero, incrementing by one each call. The Polygon() function knits vertices together into a part of the visible surface. For points and lines the Polygon() function ignores the last one or two vertex indices.
(32) SDK: TriangleSoup::Vertex, etc.
LXxMETHOD( LxResult, Vertex) ( LXtObjectID self, const float *vertex, unsigned int *index); LXxMETHOD( LxResult, Polygon) ( LXtObjectID self, unsigned int v0, unsigned int v1, unsigned int v2);
Connect allows the source to give hints about the connectivity of the elements in the soup. This is completely optional and there is no possibility of an error return.
(33) SDK: TriangleSoup::Connect
LXxMETHOD( void, Connect) ( LXtObjectID self, unsigned int type);
Empty TriangleSoup Python user class.
(34) PY: empty TriangleSoup user class
pass
QUAD | This indicates that two triangles form a quad. If a quad is given by the points 0, 1, 2, 3, then the calls would be polygon(0,1,2), connect(QUAD), polygon(0,2,3). For clients that understand quads, the last point of the second triangle is the fourth point of the quad. |
BEGIN, END | These mark the start and end of continuous curves. If the soup has type 2, such that each polygon is really a pair of endpoints, then this can be used to indicate that the lines are really part of a curve. For a curve consisting of the points 0, 1, 2, 3, the calling sequence is connect(BEGIN), polygon(0,1), polygon(1,2), polygon(2,3), polygon(3,4), connect(END). |
(35) SDK: LXiTBLX_CONNECT_QUAD, etc. defines
#define LXiTBLX_CONNECT_QUAD 0 #define LXiTBLX_CONNECT_BEGIN 1 #define LXiTBLX_CONNECT_END 2
The user method allows quads to be created with connectivity.
(36) SDK: CLxUser_TriangleSoup::Quad method
LxResult Quad ( unsigned int v0, unsigned int v1, unsigned int v2, unsigned int v3) { LxResult rc; rc = Polygon (v0, v1, v2); if (LXx_FAIL (rc)) return rc; Connect (LXiTBLX_CONNECT_QUAD); return Polygon (v0, v2, v3); }
(37) SDK: LXu_TABLEAUSURFACE, etc. defines
#define LXu_TABLEAUSURFACE "F785D229-6BA5-4C8E-9994-3E502053B83C" #define LXu_TRIANGLESOUP "17536C2D-07BD-49C8-8348-CEBDE4D3A856"
Volumes
Volume elements are 3D elements with a depth and internal structure. They need to be evaluated over the entire volume rather than just at the 2D surface.
Type | Returns the volume evaluate flags. We support 3 types that can be implemented simultaneously on the same element: |
(38) SDK: LXfTBLX_VOL_VOLUME, etc. defines
#define LXfTBLX_VOL_VOLUME 1 #define LXfTBLX_VOL_CLIPPING 2 #define LXfTBLX_VOL_IMPSURF 4 #define LXfTBLX_VOL_LOCAL_SHADER 5
RenderInit | After the tableau has fully been populated and the sample vector has been set, but before the first ray is fired, volumes are initialized. |
RaySample | Volumes are sampled with ray marching: during ray tracing volumes are intersected by rays and are evaluated to contribute to the ray. 'densitySlice' is the volume density shader slice 'shadingSlice' is the volume sample shader slice 'sv' is the sample vector. |
RayCast | Implicit surfaces need to be raycasted, these are volumes that can be evaluated as a surface usually by tracing the isosurface of the volume density field. This method returns the hit distance. It should also set the normal, position and facet packets. |
Density | Returns the density at the given position, if 'worldPos' is true it means that the position is in world space. The density is zero outside the volume so this can also be used to find out if we are inside or outside said volume. |
(39) SDK: TableauVolume::Type, etc.
''[[#C15|SDK Common: Element methods]]'' LXxMETHOD( int, Type) ( LXtObjectID self); LXxMETHOD( LxResult, RenderInit) ( LXtObjectID self, LXtObjectID sv); LXxMETHOD( LxResult, RaySample) ( LXtObjectID self, LXtObjectID densitySlice, LXtObjectID shadingSlice, LXtObjectID sv, LXtObjectID raycastObj, LXtObjectID raymarchObj); LXxMETHOD( LxResult, RayCast) ( LXtObjectID self, LXtObjectID densitySlice, LXtObjectID sv, LXtObjectID raycastObj, double *dist, int *localShader); LXxMETHOD( LxResult, Density) ( LXtObjectID self, LXtObjectID densitySlice, LXtObjectID sv, LXtObjectID raycastObj, const LXtVector pos, int worldPos, double *dens);
(40) SDK: LXu_TABLEAUVOLUME, etc. defines
#define LXu_TABLEAUVOLUME "97962302-4B49-4282-B259-F347F1012818" #define LXa_TABLEAUVOLUME "tableauVolume"
Empty TableauVolume Python user class.
(41) PY: empty TableauVolume user class
pass
Lights
Lights are 3D elements, where the bound (if any) represents the effective coverage area for anything illuminated by the light. The light source can be sampled at any desired quality level, which is simply the number of samples over the emissive volume defined by the light.
'Emit' traces photons from a light.
'ShadowMap' returns the map and true if the light uses a shadow map.
(42) SDK: TableauLight::Sample, etc.
''[[#C15|SDK Common: Element methods]]'' LXxMETHOD( LxResult, Sample) ( LXtObjectID self, float u, float v, const LXtFVector dir, LXtFVector wPos, LXtFVector oPos, LXtFVector norm, float t); LXxMETHOD( int, Geometry) ( LXtObjectID self, void *gc); LXxMETHOD( LxResult, Emit) ( LXtObjectID self, unsigned int nPhotons, int offset, LXtObjectID slice, LXtSampleVectorID sv); LXxMETHOD( int, ShadowMap) ( LXtObjectID self, void **ppvObj);
Empty TableauLight Python user class.
(43) PY: empty TableauLight user class
pass
(44) SDK: LightSample::Vertex
LXxMETHOD( void, Vertex) ( LXtObjectID self, const float *vertex);
(45) SDK: LXu_TABLEAULIGHT, etc. defines
#define LXu_TABLEAULIGHT "7FE816D1-4A7F-4BE5-9689-4991C03CAEE0" #define LXa_TABLEAULIGHT "tableauLight" #define LXu_LIGHTSAMPLE "43734621-9B93-4174-AC63-E2FE7DDA8794"
Empty LightSample Python user class.
(46) PY: empty LightSample user class
pass
The shader computes the light intensity and other parameters based on the sample and the ray. Sample source position is in homogeneous coordinates so it can include distant sources.
Quality and shadowing are determined reading packets from the shader. These are fixed for a given light, so they can be evaluated once and should not depend on any other inputs. The quality is given by a requested number of samples for the light, as well as approximate information about falloff. For local lights, 'center' and 'radius' define a region in which the light's sample points reside. For directional lights, 'radius' is half the spread in radians. 'dir' is the direction the light is pointing. 'power' is the radiant flux of the light in watts and is used for allocating emitted photons. 'infinite' should be one for directional lights, zero otherwise. 'indirect' should be one for portal lights, zero otherwise. 'item' is for light linking and points to the cinema light item that corresponds to this element.
(47) SDK: LXpLightQuality struct
LXtFVector center; LXtFVector dir; float radius; float cosine; float intensity; float power; float importance; unsigned int infinite; unsigned int indirect; unsigned int fallType; unsigned int shadType; unsigned int samples; unsigned int linkMode; void *linkGroup; void *item;
Lights that want to use a shadow map can compute this packet. It indicates the center, direction, orientation, spread angle and resolution of the requested shadow map. 'exclude' is for self shadowing. Some items do their own self shadowing and don't want to be included in the shadow computation.
(48) SDK: LXpLightShadowing struct
LXtFVector pos; LXtFVector ray, up; float angle; unsigned int mapRes; void *exclude;
The light color and brightness for locations in space is computed using another shader slice. This packet is initialized with the world and object position and the ray for the light sample being shaded.
(49) SDK: LXpLightSource struct
LXtFVector wPos, oPos; LXtFVector dir, norm; float len; float nDotWi; int sampleIndex; void *lightSource; void *lightItem;
The colors at the given sample location are computed by the light and returned in this packet. Brightness takes into account falloff and light shape, and the colors are not pre-multiplied by the attenuation. 'unshad' is not set by the light shader itself but is used in computing shadow alpha. 'pdf' is used for multiple importance sampling.
(50) SDK: LXpLightColor struct
LXtFVector color; LXtFVector shadow; LXtFVector unshad; float diffuse; float specular; float caustics; float subsurface; float brightness; float pdf;
(51) SDK: LXsP_LGT_QUALITY, etc. defines
#define LXsP_LGT_QUALITY "light.quality" #define LXsP_LGT_SHADOWING "light.shadowing" #define LXsP_LGT_SOURCE "light.source" #define LXsP_LGT_COLOR "light.color"
These are the texture effect names that apply to lights.
(52) SDK: LXs_FX_LIGHTCOLOR, etc. defines
#define LXs_FX_LIGHTCOLOR "lightColor" #define LXs_FX_LIGHTSHADOW "lightShadow" #define LXs_FX_LIGHTDIFFUSE "lightDiffuse" #define LXs_FX_LIGHTSPECULAR "lightSpecular" #define LXs_FX_LIGHTCAUSTICS "lightCaustics" #define LXs_FX_LIGHTDISTANCE "lightDistance" #define LXs_FX_LIGHTANGLE "lightAngle"
These are the texture effect names that apply to volumetrics.
(53) SDK: LXs_FX_VOLSCATTER, etc. defines
#define LXs_FX_VOLSCATTER "volScattering" #define LXs_FX_VOLSCATTER_COL "volScatteringColor" #define LXs_FX_VOLABSORB "volAbsorption" #define LXs_FX_VOLABSORB_COL "volAbsorptionColor" #define LXs_FX_VOLDENSITY "volDensity" #define LXs_FX_VOLLEVEL "volLevel" #define LXs_FX_VOLSMPDENSITY "volSampleDensity" #define LXs_FX_VOLAMB_COL "volAmbientColor" #define LXs_FX_VOLLUMI "volLuminosity" #define LXs_FX_VOLLUMI_COL "volLuminosityColor"
Proxies
A proxy is sampled to add elements to the tableau. The proxy object needs to keep track of which sub-elements have been added to the tableau so they are only added once.
(54) SDK: TableauProxy::Sample
''[[#C15|SDK Common: Element methods]]'' LXxMETHOD( LxResult, Sample) ( LXtObjectID self, const LXtTableauBox bbox, LXtObjectID tableau);
(55) SDK: LXu_TABLEAUPROXY, etc. defines
#define LXu_TABLEAUPROXY "FB34BD64-099C-4B30-8EF7-2BB04CA0E92C" #define LXa_TABLEAUPROXY "tableauProxy"
Empty TableauProxy Python user class.
(56) PY: empty TableauProxy user class
pass
Instances
An instance is a copy of another element, with variations. It most likely has a different position and orientation, and it may have differences in shading or shading parameters. These differences are encoded in the instance interface. Any normal element may also present this interface, if it wants to have these attributes as well.
Instances can set packets in the sample vector for global parameters of the element to be used by its shader.
(57) SDK: TableauInstance::Properties
LXxMETHOD( LxResult, Properties) ( LXtObjectID self, LXtObjectID vecstack);
The transformation of an instance (or any element) can be read with this method. The endpoint can specify either the start or end of the tableau time interval.
(58) SDK: TableauInstance::GetTransform
LXxMETHOD( LxResult, GetTransform) ( LXtObjectID self, unsigned endPoint, LXtVector offset, LXtMatrix xfrm);
The instance may be dissolved independently.
(59) SDK: TableauInstance::GetDissolve
LXxMETHOD( LxResult, GetDissolve) ( LXtObjectID self, double *dissolve);
An instance can define particle features. These are given by a tableau vertex to describe the feature vector, which can then be read.
(60) SDK: TableauInstance::ParticleDescription, etc.
LXxMETHOD( LxResult, ParticleDescription) ( LXtObjectID self, void **ppvObj); LXxMETHOD( LxResult, ParticleArray) ( LXtObjectID self, float *vector);
(61) SDK: LXu_TABLEAUINSTANCE, etc. defines
#define LXu_TABLEAUINSTANCE "77837A98-2BC5-466C-834F-DC937642558B" #define LXa_TABLEAUINSTANCE "tableauInstance2" #define LXiTBLX_ENDPOINT_T0 0 #define LXiTBLX_ENDPOINT_T1 1
(62) SDK: empty TableauInstance User Class
Empty TableauInstance Python user class.
(63) PY: empty TableauInstance user class
pass
Shaders
All 3D elements have shaders, which are used by the renderer to compute desired sample vector packets from a set of input packets. Shaders are polymorphic with an ILxVectorType interface, so it's easy to determine what they take as input and output.
To perform computations we need to "slice" the shader, which basically selects a set of desired output packets. The output packets are determined by the vector type, and the vertex description provides information about vertex packets to use during computation.
(64) SDK: TableauShader::Select, etc.
LXxMETHOD( LxResult, Select) ( LXtObjectID self, LXtObjectID teElt, LXtObjectID tvDesc); LXxMETHOD( LxResult, Slice) ( LXtObjectID self, LXtObjectID vtOutput, LXtObjectID tvDesc, void **ppvObj);
(65) SDK: CLxUser_TableauShader::GetSlice method
bool GetSlice ( CLxLoc_ShaderSlice &slice, ILxUnknownID vtOutput, ILxUnknownID tvDesc) { LXtObjectID obj; if (LXx_FAIL (Slice (vtOutput, tvDesc, &obj))) return false; return slice.take (obj); }
Empty TableauShader Python user class.
(66) PY: empty TableauShader user class
pass
The result of a successful slice is a shader slice interface. This is also polymorphic with an ILxVectorType to select its inputs. The Evaluate() method computes the output packets for a sample vector.
(67) SDK: ShaderSlice::Evaluate
LXxMETHOD( LxResult, Evaluate) ( LXtObjectID self, LXtObjectID vecstack);
(68) SDK: LXu_TABLEAUSHADER, etc. defines
#define LXu_TABLEAUSHADER "A0E3B574-B0AC-4530-A43F-7CC8DA536E25" #define LXa_TABLEAUSHADER "tableauShader" #define LXu_SHADERSLICE "47B885B9-B1D9-4F86-829F-A6AABBD7FFF7"
Empty ShaderSlice Python user class.
(69) PY: empty ShaderSlice user class
pass
Environment
The environment in the tableau is given as a list of shaders.
The primary function of an environment is to read the direction of the camera ray and output the color at infinity. Origin is also provided, although for environment shaders this can be ignored since the background is assumed to be at infinity. Spread is the angular size of the sampling cone, in radians.
(70) SDK: LXpCameraRay struct
LXtFVector dir; LXtFVector origin; float spread;
(71) SDK: LXpEnvInfiniteColor struct
LXtFVector rgb; float intensity;
An environment can also provide flags to determine where it is visible. Typically only one environment would be visible in a specific context. If there are multiple environments visible to the camera, for example, it's undetermined what the render camera will see.
(72) SDK: LXpEnvVisibility struct
unsigned int camera; unsigned int indirect; unsigned int reflection; unsigned int refraction;
In PhotoView, sometimes we render the environment as if it were an actual sphere in the background of everything. This packet is used for that feature.
(73) SDK: LXpEnvShape struct
unsigned int sphereVis; float size; float height; unsigned int flatten; LXtVector pos; LXtMatrix xfrmInv;
An environment can also provide fog values indicating color and absorption values.
(74) SDK: LXpEnvFog struct
LXtFVector color; LXtFVector opacity;
The environment shaders can also provide global render settings. Each of these packets should occur in only one shader, or else the result is undetermined. The global lighting packet sets ambient illumination and some basic raytracing settings.
(75) SDK: LXpGlobalLighting struct
LXtFVector ambientColor; float ambientIntensity; float rayThresh; float rayClamp; float rayOffset; unsigned int shadDepth; unsigned int reflDepth; unsigned int refrDepth; unsigned int unbiased; unsigned int specSmps; unsigned int animNoise; unsigned int rayAccel; unsigned int batchSize; unsigned int impBoost; unsigned int directSmps; unsigned int directMIS; unsigned int reflSmps; unsigned int refrSmps; unsigned int subsSmps; unsigned int noiseSeed; float smpThresh;
Displacement settings.
(76) SDK: LXpGlobalDisplacement struct
float rate; float ratio; float jitter; float edgeMin; unsigned int enable; unsigned int smooth; unsigned int useBump;
Indirect illumination and caustics settings.
(77) SDK: LXpGlobalIndirect struct
float range; float irrRays2; float irrRate; float irrRatio; float irrSmooth; float irrRetrace; unsigned int enable; unsigned int scope; unsigned int limit; unsigned int rays; unsigned int subs; unsigned int vols; unsigned int bump; unsigned int super; unsigned int reject; unsigned int caus; unsigned int giBack; unsigned int irrCache; unsigned int irrDirect2; unsigned int irrRays; unsigned int irrVals; unsigned int irrGrads; unsigned int irrSample; unsigned int irrData; unsigned int irrStart; unsigned int irrEnd; unsigned int irrWalk; unsigned int irrLEnable; unsigned int irrSEnable; unsigned int radCache; unsigned int envSample; unsigned int envRays; unsigned int envMIS; char *irrLName; char *irrSName;
(78) SDK: LXpGlobalCaustics struct
float multiplier; unsigned int total; unsigned int local; unsigned int walk;
Miscellaneous render settings, specific to our built-in renderer.
(79) SDK: LXpGlobalRendering struct
float subdRate; float coarseRate; float fineRate; float fineThresh; float aaImpMin; unsigned int multiGeo; unsigned int mergeFur; unsigned int subdAdapt; unsigned int renderType; unsigned int aa; unsigned int aaFilter; unsigned int motionBlur; unsigned int field; unsigned int frmPasses; unsigned int dof; unsigned int stereo; unsigned int stereoEye; unsigned int stereoComp; unsigned int upAxis; unsigned int bucketX; unsigned int bucketY; unsigned int bktOrder; unsigned int bktReverse; unsigned int bktWrite; unsigned int bktSkip; unsigned int bktRefine; unsigned int aRefine; unsigned int mergeRad; unsigned int bakeDir; unsigned int outputMasking; unsigned int proxyExp;
There are actually two camera ray packets. The default one contains the camera ray at time t0, the start interval for the tableau. The second ray packet contains the ray at time T1, the end of the interval. Good environment shaders will interpolate colors along an arc between the two rays to account for motion blurring of the environment as the camera rotates.
(80) SDK: LXsP_CAM_RAY, etc. defines
#define LXsP_CAM_RAY "camera.ray" #define LXsP_CAM_RAY_T1 "camera.ray_T1" #define LXsP_ENV_INFINITECOLOR "environment.color" #define LXsP_ENV_VISIBILITY "environment.visibility" #define LXsP_GLO_LIGHTING "global.lighting" #define LXsP_GLO_DISPLACEMENT "global.displacement" #define LXsP_GLO_INDIRECT "global.indirect" #define LXsP_GLO_CAUSTICS "global.caustics" #define LXsP_GLO_RENDERING "global.rendering"
Note that environment shape is intentionally NOT exposed to the SDK, since it's only for SolidWorks.
Camera
The environment shader also provides packets to describe the camera used for rendering. Some are required and some are optional, and which ones are present determines the type of camera to use for the rendering.
This required packet defines the frame buffer size in pixels and the per-pixel sampling. Sampling quality is given by a floating point number of samples per pixel, and a shading rate. These may be interpreted in any manner appropriate to the renderer.
(81) SDK: LXpCameraResolution struct
unsigned int width; unsigned int height; float pixelAspect; float dpi; // float samples; // float rate; float regX0, regX1, regY0, regY1;
Orthographic cameras are specified by a set of parameters which define the view frustum, lens and aperture. Eye position and transform are the location and orientation of the camera in world coordinates. Focal length, focus distance and f-Stop define the camera's zoom and depth of field. Iris blades, rotation, and bias affect the depth of field "bokeh" shape. Distort is a barrel or pin-cushion value and is 1.0 for a flat projection. Interocular distance is the distance between the eyes for stereo rendering. The remaining parameters define the projection from 3D to 2D, ala Maya.
(82) SDK: LXpCameraFrustum struct
LXtFVector eyePos; LXtMatrix xfrm, invXfrm; float focalLength; float focusDist, fStop; float irisRot, irisBias, distort; float ioDist, convDist; float blurLength, blurOffset; float apertureX, apertureY; float offsetX, offsetY; float squeeze; float target; float clipDist; int clipping; int filmFit; int projType; int irisBlades; void *item; int useMask; float overscan;
In addition to simple distortion, raytrace camera distortions can be computed procedurally for each pixel. If the environment has a slice that reads the camera pixel packet and writes the LXpCameraRay packet, then the slice will be evaluated before raytracing. The slice reads the buffer XY, and optionally the ray direction packet (which is initialized based on the frustum if any), and writes an updated ray direction.
(83) SDK: LXpCameraPixel struct
float x, y;
A camera intended to perform UV baking is specified by providing one of these packets instead of a frustum. The packet contains the name of the feature which is the source of the UV coordinates. Any element that doesn't support this UV feature name is not rendered.
(84) SDK: LXpCameraUVBake struct
const char *name;
The frustum may be a source of motion blur, so the renderer will query for one at time T0 and another at time T1. If the T1 frustum is missing, the camera is assumed to be non-moving.
(85) SDK: LXsP_CAM_RESOLUTION, etc. defines
#define LXsP_CAM_RESOLUTION "camera.resolution" #define LXsP_CAM_FRUSTUM "camera.frustum" #define LXsP_CAM_FRUSTUM_T1 "camera.frustum_T1" #define LXsP_CAM_PIXEL "camera.pixel" #define LXsP_CAM_UVBAKE "camera.uvBake"
Filters
Filters are fundamentally 2D elements, and operate in the image space over the frame buffer. The bound method for a filter returns a 2D bounding box and a kernel radius, plus some flags.
(86) SDK: TableauFilter::Order, etc.
LXxMETHOD( const char *, Order) ( LXtObjectID self); LXxMETHOD( LxResult, Select) ( LXtObjectID self, LXtObjectID framebuf); LXxMETHOD( unsigned int, Bound) ( LXtObjectID self, float box[4], float *kernel);
PIXEL | the filter can process individual pixels, and the Pixel() method is used rather than the region method. If the kernel is also zero then the filter can be used on a single pixel at a time without needing any other region information. |
STRIP | the filter requires complete strips in order to run. The Region() method will be called with strips scanned from top to bottom of the image. This is typically used by filters which act as image-savers. |
RELATIVE | the filter's bounding box and kernel are given as a percentage of the minimum dimenion of the entire frame. This allows for filters that are independent of the size of the rendering. |
(87) SDK: LXfTBLX_FILT_PIXEL, etc. defines
#define LXfTBLX_FILT_PIXEL 0x01 #define LXfTBLX_FILT_STRIP 0x02 #define LXfTBLX_FILT_RELATIVE 0x04
The Pixel() and Region() methods are used to do proecessing based on the filter type. Both get the frame buffer and the
(88) SDK: TableauFilter::Pixel, etc.
LXxMETHOD( unsigned int, Pixel) ( LXtObjectID self, LXtObjectID framebuf, const float pos[2]); LXxMETHOD( unsigned int, Region) ( LXtObjectID self, LXtObjectID framebuf, const float box[4]);
(89) SDK: LXu_TABLEAUFILTER, etc. defines
#define LXu_TABLEAUFILTER "FD1326E7-EECF-4EAC-B9AD-B1D64E7503BE" #define LXa_TABLEAUFILTER "tableauFilter"
Item Interface
A channel change can have no affect on the preview, or it may be necessary to update the geometry or the shading. The item can decide how individual channels should update the preview by returning the appropriate combination of the following values when the PreviewUpdate function is called.
(90) SDK: LXfTBLX_PREVIEW_UPDATE_NONE, etc. defines
#define LXfTBLX_PREVIEW_UPDATE_NONE 0x00 #define LXfTBLX_PREVIEW_UPDATE_GEOMETRY 0x01 #define LXfTBLX_PREVIEW_UPDATE_SHADING 0x02
Any item can potentially participate in rendering by adding elements to the tableau. Any item (or package) which presents the following interface will get called upon when it's time to create a tableau from a cinema.
Elements | This is called to let the item add elements directly to a tableau. |
Preview | This is similar, but is used for adding elements needed to preview this item. |
Instance | This will be called by other items which want instances of this item. The item should add elements to instance itself given the tableua instance object as reference. |
SubShader | Elements such as lights can affect their own shading. If that's the case, this method will be called to allow the item to create a shader to be used as a part of the shader for this item. |
GetCurves | Elements may be able to provide curves which can be used as hair guides. The string tag interface selects a subset of curves, and the object returned is a tableau surface element which can be sampled. |
ElementType | If implemented, ElementType allows the tableau source to specify what types of elements it can add to the tableau. It is queried with one of the following types, and puts 1 into *supported if it will add elements of that type, 0 if it won't, or -1 if it doesn't know. |
(91) SDK: LXiTBXELT_SURFACE, etc. defines
#define LXiTBXELT_SURFACE 0 #define LXiTBXELT_VOLUME 1 #define LXiTBXELT_LIGHT 2 #define LXiTBXELT_FILTER 3 #define LXiTBXELT_PROXY 4
(92) SDK: TableauSource::Elements, etc.
LXxMETHOD( LxResult, Elements) ( LXtObjectID self, LXtObjectID tableau); LXxMETHOD( LxResult, Preview) ( LXtObjectID self, LXtObjectID tableau); LXxMETHOD( LxResult, Instance) ( LXtObjectID self, LXtObjectID tableau, LXtObjectID instance); LXxMETHOD( LxResult, SubShader) ( LXtObjectID self, LXtObjectID tableau, void **ppvObj); LXxMETHOD( LxResult, PreviewUpdate) ( LXtObjectID self, int chanIndex, int *update); LXxMETHOD( LxResult, GetCurves) ( LXtObjectID self, LXtObjectID tableau, LXtObjectID tags, void **ppvObj); LXxMETHOD( LxResult, ElementType) ( LXtObjectID self, int type, int *supported);
(93) SDK: LXu_TABLEAUSOURCE define
#define LXu_TABLEAUSOURCE "9CC7F9F4-9540-4EEA-8EE9-710D58EC68F9"
Empty TableauSource Python user class.
(94) PY: empty TableauSource user class
pass
The cleanest way for items to provide elements that can be instanced is to implement an Instanceable object. This is stored in an OBJREF channel on the item, given by a server tag on the package. The item type will implement a modifier for computing the instanceable object from the state of the item's channels.
(95) SDK: LXu_INSTANCEABLE, etc. defines
#define LXu_INSTANCEABLE "9CC7F9F4-9540-4EEA-8EE9-710D58EC68F9" #define LXsPKG_INSTANCEABLE_CHANNEL "inst.channel"
Compare this instanceable to another of the same type and return a value on a comparison metric. The value is the same sense as strcmp(), with zero for identical objects, and positive and negative values indicating relatve order.
(96) SDK: Instanceable::Compare
LXxMETHOD( int, Compare) ( LXtObjectID self, LXtObjectID other);
When the elements are needed -- such as when the item itself is to be rendered or instanced -- the AddElements() method is called. The T0 and T1 instanceable objects are from the shutter open and close times, and can be read to compute state that changes while the shutter is open. The object itself is computed at the frame time. The method should call AddInstanceableElement() for all elements in the item.
(97) SDK: Instanceable::AddElements
LXxMETHOD( LxResult, AddElements) ( LXtObjectID self, LXtObjectID tableau, LXtObjectID instT0, LXtObjectID instT1);
Alternately the instanceable object can provide a Surface object which will be added to the tableau.
(98) SDK: Instanceable::GetSurface
LXxMETHOD( LxResult, GetSurface) ( LXtObjectID self, void **ppvObj);
Tableau Service
(99) SDK: TableauService::ScriptQuery, etc.
LXxMETHOD( LxResult, ScriptQuery) ( LXtObjectID self, void **ppvObj); LXxMETHOD( LxResult, AllocVertex) ( LXtObjectID self, void **ppvObj);
(100) SDK: CLxUser_TableauService::NewVertex method
bool NewVertex ( CLxLoc_TableauVertex &vert) { LXtObjectID obj; vert.clear (); if (LXx_FAIL (AllocVertex (&obj))) return false; return vert.take (obj); }
This utility method will populate a vertex description with all the known features of the tableau surface object. It puts the four required features at the front as normal.
(101) SDK: TableauService::VertexFromFeatures
LXxMETHOD( LxResult, VertexFromFeatures) ( LXtObjectID self, LXtObjectID surfObj, LXtObjectID vertex);
(102) SDK: LXu_TABLEAUSERVICE define
#define LXu_TABLEAUSERVICE "8DF92316-3172-465A-A199-254792D37732"
Empty tableau service Python user class.
(103) PY: empty Service.Tableau user class
pass
Nodal Service
The nodal service is used to establish and evaluate channels as part of the Nodal Shading system. The service is used by textures & shaders in two ways: as part of the Shader Tree, their inputs can be evaluated on a per-sample basis, and their outputs can also be requested as part of the Nodal Modifier system.
The Nodal Service will transparently handle both of these cases.
AddSampleChan & AddSampleChanName are used to add a channel of an item to the nodal evaluation system. When processed as part of the Shader Tree, the evaluator index will be stored in the 'idxArray' passed, and when processed as a nodal modifier, the evaluator index will be stored internally within the nodal evaluator (and 'idxArray' may be NULL). Additionally, within the Shader Tree, if the channel is not actually driven on a per-sample basis for the current pass, the evaluator index is stored as LXiNODAL_NOT_DRIVEN. This value speeds up the evaluations by letting the Get* methods know that the value does not have to be read from the evaluator.
When adding channels for texture locators, LXfECHAN_LOCATOR should be ORed with the LXfECHAN_READ and/or LXfECHAN_WRITE flags.
GetFloat, GetInt & GetValue are used to get the current sample values from a nodal evaluator. 'index' is the index of channel in the item. For evaluations in Shader Tree, the values will be read from the evaluator using the 'idxArray' passed, unless the stored index is LXiNODAL_NOT_DRIVEN, in which case the 'orig' value will be returned. When evaluated as a nodal modifier, the internal index array will be used.
IsDriven & IsDrivenName are used to determine if a channel is driven per-sample, and therefore needs to be read at every sample. If not, the value can be read once per layer.
AnyDrivenChans is used for optimization of the evaluation. It is passed a contiguous array of evaluator indexes, and will return LXe_TRUE for the first sample-driven channel, and LXe_FALSE if none are found.
(104) SDK: NodalService::AddSampleChan, etc.
LXxMETHOD( int, AddSampleChan) ( LXtObjectID self, LXtObjectID eval, LXtObjectID item, int chanIndex, int *idxArray, int type); LXxMETHOD( int, AddSampleChanName) ( LXtObjectID self, LXtObjectID eval, LXtObjectID item, const char *chanName, int *idxArray, int type); LXxMETHOD( double, GetFloat) ( LXtObjectID self, LXtObjectID etor, int *idxArray, int index, double orig); LXxMETHOD( int, GetInt) ( LXtObjectID self, LXtObjectID etor, int *idxArray, int index, int orig); LXxMETHOD( void*, GetValue) ( LXtObjectID self, LXtObjectID etor, int *idxArray, int index, void *orig); LXxMETHOD( int, IsDriven) ( LXtObjectID self, LXtObjectID item, int chanIndex); LXxMETHOD( int, IsDrivenName) ( LXtObjectID self, LXtObjectID item, const char *chanName); LXxMETHOD( int, AnyDrivenChans) ( LXtObjectID self, int *chans, int count);
Empty nodal service Python user class.
(105) PY: empty Service.Nodal user class
pass
This structure can be used to simplify conversion from the older value textures. It contains 3 indexes, the channel index inthe item, the evaluator index for the per-layer data, and the evaluator index for the per-sample data.
(106) SDK: LXtSampleIndex struct
unsigned chan; unsigned layer;
(107) SDK: LXfECHAN_LOCATOR, etc. defines
#define LXfECHAN_LOCATOR 0x40000000 #define LXiNODAL_NOT_DRIVEN 0xFFFFFFFF #define LXu_NODALSERVICE "2055F206-1682-11E3-9F05-6ACC6088709B"
Tableau Event Translator
In order for plugins to listen to events, we provide the following event translator interface.
A tableau channel change event is a general event such that a plugin can listen for any channel changes through the tableau. This is useful for plugins which generate tableau elements, as it gets events on both animation and general modification events, so it's simple to then fire a tableau update event.
(108) SDK: TableauListener::ChannelChange
LXxMETHOD( void, ChannelChange) ( LXtObjectID self, LXtObjectID tableau, LXtObjectID item, int channel);
The only two other events are when a tableau indicates that every element in the tableau is being flushed, and when the tableau is warning clients that it is being destroyed.
(109) SDK: TableauListener::FlushElements
LXxMETHOD( void, FlushElements) ( LXtObjectID self, LXtObjectID tableau);
(110) SDK: TableauListener::TableauDestroy
LXxMETHOD( void, TableauDestroy) ( LXtObjectID self, LXtObjectID tableau);
(111) SDK: LXu_TABLEAULISTENER define
#define LXu_TABLEAULISTENER "848C5B64-4C9F-404E-8E3F-CF725007F74D"