TKE_Shell

Opcode

ASCII S
Hexadecimal 0x53
Decimal 83

Operands

Operands depend on suboptions. Operands enclosed in brackets (‘<STRONG>[]</STRONG>’) will not be present in all situations. See the description of the specific operands for the rules that dictate whether or not they appear.

Format 1: (standard)

byte suboptions, [short suboptions2], [int index],
byte level_of_detail, variable points,
variable faces, [variable attributes]

Format 2: (edgebreaker)

byte suboptions, [short suboptions2], [int index],
byte level_of_detail, variable edgebreaker data,
[3 * float * pointcount uncompressed points ],
[variable attributes]

Format 3: (bounding only)

byte suboptions, [short suboptions2],
byte level_of_detail, float * 6 bounding

Format 4: (collection)

byte suboptions, [short suboptions2],
variable collection

Format 5: (null shell)

byte suboptions, [short suboptions2],
byte level_of_detail
suboptions a bit field with information about the formatting. See below for more details
suboptions2 more formatting information. Present if and only if suboptions contains the TKSH_EXPANDED bit, otherwise implicitly assumed to be zero
index indicates the tagged opcode in the hsf file of which this shell is given as a refinement. Present if and only if suboptions does not contain the TKSH_FIRSTPASS bit
level_of_detail the level of detail into which this shell is meant to be inserted. The full-resolution version is level 0. Coarser versions have higher LOD numbers. HSF files may have up to 256 distinct levels, though HOOPS-based applications are limited to 8 levels as of this writing
points compressed or uncompressed vertex location data. See below for more details
faces face data. See below for more details
edgebreaker_data highly compressed data for points and faces combined. See edgebreaker.html
bounding an axis-aligned bounding cuboid in the order Xmin, Ymin, Zmin, Xmax, Ymax, Zmax. Present if and only if suboptions contains the TKSH_BOUNDING_ONLY bit
collection a set of Opcodes to be interpreted as the Level of Detail for a shell (e.g. a polyline and two markers in place of a cylinder-shaped shell at LOD 2). All subsequent opcodes will be interpreted as part of the collection until a TKE_Termination opcode is encountered. More details below.
attributes optional attributes to be bound to vertices, edges and/or faces. See attributes.html

Suboptions and Suboptions2

As mentioned above, the formatting depends on the values of “suboptions” and “suboptions2”. The following two tables define the bits of those two flags, as well as the rules that use the values of those bits to determine by which format the shell is to be interpreted. Bits that dictate a particular format are all mutually exclusive.

Suboptions

0x01 TKSH_COMPRESSED_POINTS -- Points are compressed
0x02 RESERVED -- unused
0x04 TKSH_TRISTRIPS -- Information on how to interpret the face list
0x08 TKSH_HAS_OPTIONALS -- Vertices, edges and/or faces have attributes. See attributes.html
0x10 TKSH_FIRSTPASS -- A new shell, not a refinement. "Index" does not exist
0x20 TKSH_BOUNDING_ONLY -- Shell is format 3. This bit takes precedence over TKSH_CONNECTIVITY_COMPRESSION and TKSH2_COLLECTION
0x40 TKSH_CONNECTIVITY_COMPRESSION -- Shell is format 2
0x80 TKSH_EXPANDED -- Suboptions2 is present

Suboptions2

0x0001

TKSH2_COLLECTION -- Shell is format 4

0x0002

TKSH2_NULL -- Shell is format 5. This bit takes precedence over TKSH2_COLLECTION, TKSH_CONNECTIVITY_COMPRESSION and/or TKSH_BOUNDING_ONLY

0x0004

TKSH2_HAS_NEGATIVE_FACES -- Face list contains signed, not unsigned, values

0x0004

TKSH2_GLOBAL_QUANTIZATION -- Compressed vertices inherit global bounding box instead of specifying their own.

Notes

Shell is inserted into the currently opened segment.

Points (uncompressed)

int pointcount, float array uncompressed triplets of point data, in order xyzxyz…

Points (compressed)

byte compression scheme, int pointcount, byte bits_per_sample, variable array of compressed floats (see attributes.html)

Points are either compressed or uncompressed vertex data. Compression status is dictated by the TKSH_COMPRESSED_POINTS bit in the shell suboptions. If uncompressed, it will consist of triples of 32-bit floating point coordinates in the order xyzxyz… If compressed, it will consist of a compression scheme identifier, followed by data that is specific to that compression scheme. The specifics of the compressed format are described in attributes.html in the “array of compressed floats” section. bits_per_sample may have any value from 2 to 31.

Interpretation of the face (a.k.a polygon or facet) data in faces will depend on whether the TKSH_TRISTRIPS bit is set in suboptions. In any case, however, it will specify which vertices should be connected to form faces.

Faces (compressed)

byte compression scheme, int face list length, <strong>byte</strong> bits per value, variable face list data (see below).

If the TKSH_TRISTRIPS bit is set in suboptions, the face list is interpreted exactly as per the HOOPS function, Insert_Shell. Here is the relevant excerpt from the HOOPS Reference Manual:

The face_list is an array of integers. The first integer is the number of vertices that should be connected to form the first face. For example, “3” for a triangle. The next three integers (in this example) are the offsets into the points array at which the three x-y-z’s can be found. The first point in the points array is considered to be at offset zero, so “0, 1, 2” in the face_list array would form the triangle from the first three entries in points.

Continuing with the example, a second triangle might be specified as “3, 0, 1, 3”, meaning “form a face using three vertices. The vertices are at offsets zero, one, and three in the points array”. So this second face happens to share an edge - the (0, 1) edge - with the first face. A third face might be “4, 1, 2, 11, 12”, forming a quadrilateral. Faces continue being formed until an flist_length number of integers in face_list have been processed.

One special case: if a vertex count in the list is negative, that means “continue with the previous face and subtract a polygon formed from the following vertices”. This allows you to build faces with true holes in them. Multiple holes get an “even-odd” rule applied. A region is part of the face if there are an odd number of edges between it and infinity in the plane of the face. Otherwise a region is considered exterior and is not drawn. The edges of the hole receive the usual edge attributes. For face-numbering purposes (for example, Edit_Shell_Faces) the hole is not counted separately - it’s a part of the face it’s in.

If the TKSH_TRISTRIPS bit is set in suboptions, the shell is assumed to contain triangles only and may not contain holes, and the “faces” are actually the way that vertices are connected into triangle strips. The first 3 vertices form a triangle, and every additional vertex is combined with the two previous ones to define one additional triangle. Exactly as with OpenGL’s GL_TRIANGLE_STRIP primitive, the orientation of every even triangle is reversed, beginning with the second.

There is still special meaning attached to a negative count in the TKSH_TRISTRIPS case. A negative count indicates the beginning of a triangle fan. As with triangle strips, every vertex i after the second (for i < 2) defines a new triangle. Triangle strips connect i to vertices i-2 and i-1. Triangle fans connect i to vertices 0 and i-1.

The values will of a type appropriate to the maximum vertex index (as opposed to always 32-bit integers). For shells that have less than 256 vertices, the values will be 8-bit characters. Otherwise they will be 16-bit shorts for shells with less than 65536 and 32-bit integers for shells with more.

If suboptions2 contains the TKSH_HAS_NEGATIVE_FACES bit, vertex indices will use 16-bit shorts if the maximum index is greater than or equal to 128, and 32-bit integers if the maximum is greater than or equal to 327678.

As of this writing, CS_TRIVIAL is the only supported value for compression scheme for faces. Future revisions may introduce new methods, however.

If suboptions2 contains TKSH2_COLLECTION, a shell is interpreted according to format 4. This is a set of opcodes, possibly including primitives other than shells, that are to be inserted into the Level of Detail for a shell (e.g. a polyline and two markers in place of a cylinder-shaped shell at LOD 2). All subsequent opcodes will be interpreted as part of the collection until a TKE_Termination opcode is encountered. Legal opcodes as part of a collection are the following:

TKE_Circle TKE_Circular_Arc TKE_Circular_Chord
TKE_Circular_Wedge TKE_Ellipse TKE_Elliptical_Arc
TKE_Grid TKE_Image TKE_Line
TKE_Marker TKE_Mesh TKE_NURBS_Curve
TKE_Polygon TKE_Polyline TKE_Shell
TKE_Text TKE_Text_With_Encoding

In other words, a collection allows for any geometry with the exception of lights and cutting planes (TKE_Area_Light, TKE_Distant_Light, :doc:TKE_Local_Light </general/hsf/opcodes/TKE_Local_Light>`, TKE_Spot_Light and TKE_Cutting_Plane). There are no limits placed on the number of opcodes that may be in a collection prior to the TKE_Termination. This situation is an exception to the rule that there should be only one TKE_Termination opcode in the file.

Shells that are included as part of a collection may not themselves contain collections (i.e. they may not be format 4). Additionally, their level_of_detail member will be present but ignored.