Documentation on the Public Domain Geometry Library (GPD) - Version 5 --------------------------------------------------------------------- In previous versions of Houdini source was distributed for a simple library to load and save .[b]geo files. This code is no longer distributed as its antiquated interface had become outdated. Instead, we recommend file converters be written using the HDK. A copy of the source to the current GPD library can be found here: http://houdinigpdlibra.sourceforge.net/ Be warned its functionality does not exceed loading and saving files and can only act as a rough template of how to work with .[b]geo files. At the end of this document are several example files (uuencoded) used for illustration. Binary Vs Ascii --------------- The binary .bgeo format and the ascii .geo format are very similar. Whereever possible the layout of the data is the same in both formats meaning both code paths can often be handled in the same function. Binary, of course, brings its own complexities. Data is stored big endian regardless of the native bit ordering of the platform. This means byte swapping is the norm for Intel architectures. Binary Data Types: char: An 8 bit unsigned integer. float32: A 32 bit floating point number. int8: A signed 8 bit integer int16: A signed 16 bit integer int32: A signed 32 bit integer uint16or32: An unsigned 16 or 32 bit integer. Which one depends on the maximum size of what is being indexed. uint16: An unsigned 16 bit integer. var16: A variable length 16 bit integer. This is an int16. If the value of the int16 is -1, an additional int32 is stored which is to be taken as the actual value. var8: Same as a var16, but starts with int8 before falling back to int16, etc string: A var16 giving the length of the string followed by the string itself stored as chars. Note the null terminator is *not* stored nor included in the length. string8: Same as string, but with a var8 to specify the length. Ascii Notes: The ascii file parser is line based. Each '\n' terminated line is read and processed individually. The contents of a line are separated by whitespace: ' ' or '\t'. Strings are stored in a protected form. If they contain spaces, they are quoted with ". If they contain \ or ", those characters are escaped. Note that most fields (such as group names, attribute names, etc) cannot contain spaces or special characters anyways. When writing floating point values using C++ iostreams, it is recommended to set the stream precision to 9 digits (os.precision(9)) or you will see round off errors in the conversion process. FILE FORMAT ----------- 1) Header Section -------------- Ascii: Magic Number: PGEOMETRY V# Point/Prim Counts: NPoints # NPrims # Group Counts: NPointGroups # NPrimGroups # Attribute Counts: NPointAttrib # NVertexAttrib # NPrimAttrib # NAttrib # Binary: Magic Number: int32 ((((('B'<<8)|'g')<<8)|'e')<<8)|'o' Version Name: char 'V' Version Number: int32 5 NPoints:int32 NPrims:int32 NPointGroups:int32 NPrimGroups:int32 NPointAttrib:int32 NVertexAttrib:int32 NPrimAttrib:int32 NAttrib:int32 In each of these cases, the # represents the number of the element described. V# is the version of the geo file format. Groups are named and may be defined to contain either points or primitives. Each point or primitive can be a member of any number of groups, thus membership is not exclusive to one group. Attributes can be assigned per point, per vertex, per primitive or on the detail. Therefore, the number of attributes is declared at the top of the file. Later, each of these attributes will be defined in full. 2) Attribute Definitions --------------------- Internally, there are "dictionaries" to define the attributes associated with each element. These dictionaries define the name of the attribute, the type of the attribute and the size of the attribute. Also, the default value of the attribute is stored in the dictionary. When the dictionary is saved, each attribute (in a specific order) is defined. The definition is basically as follows: Name Size Type Default For example, the attribute name for normals is "N", so the attribute definition (for Ascii) would look like: N 3 float 0 0 0 Specifying the attribute name "N", that there are 3 elements in this attribute and the type is float. The default value would be (0, 0, 0) Index attributes store the list of strings instead of the default value. For example, the a material index attribute of name "mat" and type index which has three strings in the string table would be: mat 1 index 3 marble gold crystal_glass3 If spaces are present in the strings the string needs to be placed in double quotes. If double quotes or backslashes are required in the string, they must be escaped with backslashes. Binary Notes: Name:string Size:var16 Type:uint32 Default:* The Name field is limited to 32k characters in Houdini 9.0. Size is the number of Type-sized attribute elements. If Type is float32, the number of bytes will be four times Size. Type is an int32 but has the optional Type Info stored in the high 16 bits. type = Type & 0xffff; typeinfo = Type >> 16; Values for type and typeinfo are: Type # Data Meaning 0 float32 float 1 int32 int 2 char * 32 string, deprecated! 3 char "mixed", should not be saved. 4 int32 index 5 float32 * 3 vector TypeInfo # Meaning 0 None 1 Index Pair The default data is stored according to the size and type fields. Thus, a size 3 float32 type will store 12 bytes for the 3 float values. The case of index attributes is different. Index attributes do not store a default: the default is always -1. Instead, they store their index table in place of the default. The index table is saved as an int32 for the number of entries in the index table. That number of strings then follows. Following the element definition is the attribute data associated with the element. There are braces delineating the attribute data. The attribute data appears in the order that the dictionary for the element was defined. Binary Notes: Saved after each element is the attribute data for that element. This is stored attribute-by-attribute in the order the attribute was defined. No padding is done between entries. For example, a dictionary might look like: PointAttrib Cd 3 float 0 0 0 # Color attribute, 3 floats, default 0 0 0 Alpha 1 float 1 # Alpha attribute, 1 float, default 1 N 3 float 0 0 0 # Normal attribute uv 2 float 0 0 # Texture coordinate The data for the point might look like: 0 0 0 1 (1 0 0 1 0 0 1 .5 .5) ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ Position Attributes The point would have: Cd = (1, 0, 0) Alpha = 1 N = (0 0 1) uv = (.5, .5) The types of attribute data supported are: integer, float, string and index. The "string" type is stored as a 32 character string since each attribute must have a fixed length. The string field should not be used, however: use the index type instead. The integer and float types are pretty self-explanatory. The index attribute type is used for specifying things like material. It contains a list of strings which are indexed by integer values. Thus the storage for an index attribute is an integer. In the definition of the index attribute the list of strings is given instead of the default value. The default value for all index attributes is -1 indicating that the attribute has not been assigned. In addition to these types, a TypeInfo may be optionally present after the type separated by a colon. The only current typeinfo is for indexpair, which has the token float:indexpair. This is used for capture attributes which are pairs of index/weight values with a -1 specifying an invalid index. For these attributes, -1 index/weight pairs must be at the _end_ of the attribute. In other words, valid index/weight pairs must be contiguous at the beginning of the attribute. 3) Point Definitions ----------------- If there are point attributes, the attribute dictionary is saved before the definition of the points. Dictionary Name: PointAttrib Dictionary Data: -- Attribute Definition -- In the binary case there is no Dictionary Name. Instead, the dictionary data is stored directly. The NPointAttrib field in the header can be used to determine if the dictionary data will be present. Following the attribute dictionary, is the point data for the points. Each point is stored with 4 components (x, y, z & w). The positions are not true homogeneous coordinates. To get the homogeneous coord, simply multiply each x, y & z by w. If (and only if) there is attribute data, the attribute data is defined following the point position. The attribute data is enclosed in parenthesis "()". In the binary case, the point attribute data is saved after the position with no padding or tags. 4) Primitive/Vertex Definitions ---------------------------- If (and only if) there are vertex attributes, the vertex attribute dictionary is found here. Following the vertex attribute dictionary is the primitive attribute dictionary (iff there are attributes for primitives). Since every primitive may have local information which needs to be saved, the format of every primitive is different. In general, the format is: Ascii: PrimKey [primitive_attributes] Binary: PrimKey:int32 [primitive_attributes] Here, the local_information is primitive specific. As part of the local information, a vertex or multiple vertices are specified. Each vertex is saved in the same format, which is: Ascii: point_number vertex_attribute_data Binary: point_number:uint16or32 vertex_attribute_data The point numbers start at 0 and go through NPoints - 1. If there is vertex attribute data, the data is delimited by parenthesis "()". If the total number of points is less than or equal to USHRT_MAX (65535), 16 bit unsigned integers are used to store the point index. Otherwise 32 bit unsigned integers are used. If there is primitive attribute data, it is delimited by brackets "[]". Each primitive has a unique identifier. The current primitives and their identifiers are: PrimKey Type Ascii Binary Polygon: "Poly" 0x00000001 NURBS Curve: "NURBCurve" 0x00000002 Rational Bezier Curve: "BezierCurve" 0x00000004 Linear Patch: "Mesh" 0x00000010 NURBS Surface "NURBMesh" 0x00000020 Rational Bezier Patch: "BezierMesh" 0x00000040 Paste Hierarchy: "PasteSurf" 0x00000f00 Ellipse/Circle: "Circle" 0x00001000 Ellipsoid/Sphere: "Sphere" 0x00002000 Tube/Cone: "Tube" 0x00004000 Particle System: "Part" 0x00008000 Metaball "MetaBall" 0x00100000 Meta Super-Quadric "MetaSQuad" 0x00200000 Triangle Fans: "TriFan" 0x01000000 Triangle Strips: "TriStrip" 0x02000000 Triangular Beziers: "TriBezier" 0x03000000 Volume "Volume" 0x04000000 Run "Run" 0xffffffff The primitive keys are case sensitive. For example: VertexAttrib uv 3 float 0 0 0 PrimitiveAttrib Cd 3 float 0 0 0 Poly 3 < 0 (1 0.5 0) 1 (0 0 0) 2 (0 1 0) [1 1 0 .5] Would specify a closed polygon (see below) which has 3 vertices referencing points 0, 1 & 2. Each vertex has 3D texture coordinates specified in (), the polygon has Color and Alpha specified in []. The color is yellow, with 50% alpha coverage. When there are two or more consecutive primitives of the same type, this is specified as a run of primitives. In this case, the following should appear in the file: Ascii: "Run" # PrimKey Binary: 0xffffffff RunLength:u16 PrimKey:int32 Where # is the number of primitives in the run. In this case, the following primitives are not saved with the PrimKey (type) identifier since it is implicit in the run. Binary Notes: Because only a 16 bit unsigned int is used for the run length, runs longer than this are broken into multiple runs. 4a) Local Primitive Information --------------------------- POLYGON Local Information Format ------- Ascii: #Vtx OpenClose Vertex_List Binary: #Vtx:int32 OpenClose:char Vertex_List Where: #Vtx = Number of vertices in the polygon OpenClose = A single character flag: "<" = Closed face ":" = Open face NURBS/BEZIER CURVE Local Information Format ------------------ Ascii: #Vtx OpenClose Basis Vertex_List Binary: #Vtx:int32 OpenClose:char Basis Vertex_List The basis definition for both NURBS and Bezier primitives starts with: Ascii: Keyword Order Binary: Order:int32 Where: Keyword = "Basis" Order = The order of the basis (degree + 1) The NURBS Basis --------------- The NURBS basis requires an end condition flag and a list of knots sorted in increasing order. The complete definition of the NURBS basis is: Ascii: Keyword Order EndCondition Knots Binary: Order:int32 EndCondition:int16 zero:int16 Knots:float32 Where: EndCondition = "end" to touch the end CVs, "noend" otherwise. Binary format uses 0 for "noend" and 1 for "end". Knots = Floating point numbers in increasing basis order. The number of knots in the list is determined by the order of the basis, its end conditions, the number of CVs in the Vertex_List, and the OpenClose flag. Let #K be the number of expected knots, and #Vtx the number of CVs. Then, if the EndCondition is false (ie. "noend"), #K = #Vtx + Order - 2 The two missing end knots (and the periodicity knots if closed) are generated internally. If theEndCondition is true (ie. "end"), then: if the curve is open #K = #Vtx - Order + 2 if the curve is closed #K = #Vtx - Order + 3 The Bezier Basis ---------------- The Bezier basis does not require a list of knots if the knots start at 0 and grow with unit increments (e.g. 0 1 2 3 ...) The complete definition of the Bezier basis is: Ascii: Keyword Order Knots Binary: notuniform:char [Knots:float32] notuniform of 0 means no knots will be present. Instead, the basis is to start at 0 and increment by unit increments. A value of 1 means that a sequence of knots will provide the basis values. The number of knots in the list is determined by the order of the basis, the number of CVs in the Vertex_List, and the OpenClose flag. Let #K be the number of expected knots, #Vtx the number of CVs. Then: if the curve is open #K = (#Vtx-1) / (Order-1) + 1 if the curve is closed #K = (#Vtx ) / (Order-1) If the curve is closed, the periodicity knot is generated internally. MESH Local Information Format ---- Ascii: #Cols #Rows UWrap VWrap connectivity Binary: #Cols:int32 #Rows:int32 Flags:int32 connectivity:int32 Flags stores the uwrap and vwrap in the upper bits: UWrap = (Flags & 0x80000000) != 0; VWrap = (Flags & 0x40000000) != 0; A value of 1 means to be wrapped. UWrap / VWrap: "open" or "wrap" columns or rows respectively Ascii Binary Meaning connectivity: "rows" 0 - Rows only "cols" 1 - Columns only "rowcol"2 - Rows & Columns "tri" 3 - Triangulated quads "quad" 4 - Quad "atri" 5 - Alternate triangulated "revtri"6 - Reverse triangulated The connectivity is ignored in many cases, but is critical for operations like sweeping or conversion to polygons. Default triangulated ("tri") meshes are structured like: +-+-+ |/|/| +-+-+ |/|/| +-+-+ Alternate triangulation ("atri") looks like: +-+-+ |\|/| +-+-+ |/|\| +-+-+ Reverse triangulated ("revtri") meshes are structured like: +-+-+ |\|\| +-+-+ |\|\| +-+-+ NURBS/BEZIER SURFACE Local Information Format -------------------- #Cols #Rows UWrap VWrap connectivity UBasis VBasis Vertex_List Profiles #Cols, #Rows, UWrap, VWrap, connectivity, and Vertex_List are the same as for MESH. UBasis and VBasis are the same as for NURBS/BEZIER CURVE. Profiles is an optional list of profile curves (curves on surfaces). The structure of the profiles section is very similar to that of the main geometry, including a header section, points, primitives, point and primitive groups. The differences are that this section doesn't contain any attributes and has only three profile types: polygon, NURBS curve, and Bezier curve. The profile token is "Profiles:". It is followed by " none" if there are no profiles. In the binary format, a int32 is stored to determine if there are any profiles. 0 means no profiles, 1 means that profiles are present. If there are profiles, the profile section has the following structure: Point/Prim Counts: NPoints # NPrims # NLoops # Group Counts: NPointGroups # NPrimGroups # Nested trim level: TrimLevel # Point list: u v w triplets Primitive list polygons, NURBS/Bezier curves Trim Regions Point group definitions Profile group definitions a. Header section ----------------- Point/Prim Counts: NPoints # NPrims # NLoops # Group Counts: NPointGroups # NPrimGroups # In each of these cases, the # represents the number of the element described. The number is stored as an int32 for the binary case. Nested trim level: TrimLevel # In this case, # is an int32 representing the sea-level for nested trimmed loops, and can be either positive or negative. Usually it is 0. A primitive is a 2D profile: a polygon, a Bezier curve, or a NURBS curve living within the domain of the spline surface. The points are 2D locations (i.e. uv pairs with a third, w (weight) component) in the surface domain. The loops are trimming loops, also know as "trim regions", defined by the primitive profiles mentioned above. It is possible to have several profiles on a surface and yet no trim loops. Groups are named and may be defined to contain either points or profiles. Each point or primitive can be a member of any number of groups, thus membership is not exclusive to one group. b. Point section ---------------- Each point is stored with 3 components (x, y, w). The positions are not true homogeneous coordinates. To get the homogeneous coord, simply multiply each x, y by w. c. Primitive section -------------------- Since every profile may have local information which needs to be saved, the format of every primitive is different. In general, the format is: ProfileKey Here, the local_information is profile specific. As part of the local information, a vertex or multiple vertices are specified. Each vertex is saved in the same format, which is: point_number:uint16or32 The point numbers start at 0 and go through NPoints - 1. Each profile has a unique identifier. The current profiles and their identifiers are identical to their 3D counterparts: Type Ascii Binary Polygon: "Poly" 1 NURBS Curve: "NURBCurve" 2 Rational Bezier Curve: "BezierCurve" 4 The profile keys are case sensitive. For example: Poly 3 < 0 1 2 Would specify a closed polygon (see below) which has 3 vertices referencing 2D points 0, 1 & 2. When there are two or more consecutive profiles of the same type, this is specified as a run of profiles. In this case, the following should appear in the file: Run # ProfileKey Where # is the number of profiles in the run. In this case, the following profiles are not saved with the ProfileKey identifier since it is implicit in the run. For the binary format for Run, see the 3D description. The format of the three profile types - polygon, NURBS curve, and Bezier curve - is identical to that of the 3D primitives and won't be listed again here. d. Trimming section ------------------- If NLoops is not zero, the surface will contain one or more trim regions. Each region can contain one or more profiles. Typically, the profiles should intersect to form a closed loop. Sometimes, though, as in the case of a loop that intersects the domain boundaries, the loop is partially defined by the domain boundaries and need not be explicitly closed. Single profile loops that are open and do not intersect the domain boundaries will be closed straight by houdini. The trimming section contains one or more lines like the one below, one line per trim region: Ascii: TrimRegion [natural] #Profiles ... Binary: keepdir:int32 #Profiles:int32 profile:int32 ustart:float32 uend:float32 If keepdir is 1, the "natural" flag is set, otherwise it is not set. The profile/ustart/uend is repeated #Profiles times. If "natural" is specified, open profiles are treated casually, i.e. their parametric direction is not checked and will not be reversed. profile_number is the index of each profile in the current trim region. ustart and uend are the parametric values defining the beginning and end of the profile. It is thus possible to use only a section of a profile for trimming. To reverse the direction of the trim curve without reversing the vertices of the profile itself, specify a ustart greater than ustop. A profile can therefore used in more than one trim region, and can have different orientations and lengths in each region. When punching holes in a surface, an outer profile is needed to specify the area of the surface to be kept. Usually, the outer profile is a closed polygon that envelops the perimeter of the domain. Example: TrimRegion 2 0 1 0 5 -3.5 8 The trim region has two profiles: 0 and 5. Profile 0 is reversed by evaluating between 1 and 0. Profile 5 is used between -3.5 and 8. e. Groups section ------------------- The point groups are saved first, followed by the profile groups. There is no identifier indicating the groups. The format for a group depends on whether it is ordered or unordered: GroupName Type NElements BitMask ElementList GroupName - is the name of the group. Type - is "unordered" or "ordered". NElements - Specifies the total number of bits in the BitMask. This is equivalent to NPrims in the profile header. BitMask - A string of 0's and 1's, where 1 indicates membership in the group. ElementList - If the groups is ordered, the element list contains the index of each selected point or profile in selection order. The first element of the list is the number of ordered elements in the list. For details on the binary implementation of the groups section, look forward to the 3D description. PASTE HIERARCHY Local Information Format --------------- #Features followed by as many lines as feature surfaces, in the order in which the surfaces are pasted. Each feature line has the format: Feature prim_number:int32 height:float32 up_or_down:int32 prim_number is the index of the spline surface in the list of primitives. height is the elevation of the pasted surface from its base. up_or_down is 1 is pasted upward, 0 if downward. Binary Notes: The binary format lacks the Feature tag. The domain transformation is either linear or bilinear. In Ascii, the keyword "Linear" or "Bilinear" is used. In Binary, an int32 is used: 1 is linear, 2 is bilinear. The data of the tranformations is stored as a series of float32s in binary without the keywords present. Linear transformation format: ----------------------------- Linear tx ty UT_Matrix2 m00 m01 m10 m11 The translation in the domain is given by (tx,ty). The rotation and scaling components are captured in the 2x2 matrix. Bilinear transformation format: ------------------------------- Bilinear origUL origUR origLR origLL warpUL warpUR warpLR warpLL L,U,L,R stand for Lower, Upper, Left and Right respectively. Each of the eight locations is a (u,v) pair in the surface domain. Example of a paste hierarchy with three surfaces: PasteSurf 3 Feature 0 0 1 Linear 0 0 UT_Matrix2 1 0 0 1 Feature 2 0.02 1 Bilinear 0 0.6 0.6 0.6 0.6 0 0 0 100.1 -22 100.4 -22 100.4 -28 100.1 -28 Feature 3 0.07 0 Bilinear 0 1 1 1 1 0 0 0 100.2 -21 100.45 -21 100.45 -26 100.2 -26 CIRCLE Local Information Format ------ Vertex_Info Matrix33 There is always only one vertex for a Circle. The 3x3 matrix contains scaling and rotation transformations about the center of the circle. Sheared circles are thus allowed. circle. The 3x3 matrix is stored as 9 float32s in binary. SPHERE Local Information Format ------ Vertex_Info Matrix33 There is always only one vertex for a Sphere. The 3x3 matrix contains scaling and rotation transformations about the center of the sphere. Sheared spheres are thus allowed. The 3x3 matrix is stored as 9 float32s in binary. TUBE/CONE Local Information Format --------- Vertex_Info Taper:float32 Closure:char Matrix33 There is always only one vertex for a Tube/Cone. The vertex lies in the center of the tube (along the axis connecting the centers of the top and bottom circles/ellipses). The taper value affects the radius of the top circle. A regular tube has a taper value of 1. A cone's taper is 0. The closure - "closed" or "open" - indicates whether the tube is end-capped. The binary Closure value is 0 for open, 1 for closed. The 3x3 matrix contains scaling and rotation transformations about the center of the tube. Sheared tubes are thus allowed. The 3x3 matrix is stored as 9 float32s in binary. METABALL Local Information Format -------- Vertex_Info Kernel_Function:char Weight:float32 Matrix33 There is always only one vertex for a metaball. The kernel function is one of: "wyvill", "quartic", "blinn" or "links". The 3x3 matrix contains scaling and rotation transformations about the center of the metaball. Sheared metaballs are thus allowed. In binary, the kernel function is stored with a single character matching the first letter of the desired kernel. META SUPER-QUADRIC Local Information Format ------------------ Vertex_Info XY_Exponent:float32 Z_Exponent:float32 Kernel_Function:char Weight:float32 Matrix33 There is always only one vertex for a meta super-quadric. The exponents are float values. The kernel function is one of: "wyvill", "quartic", "blinn" or "links". In binary, it is a single character. The 3x3 matrix contains scaling and rotation transformations about the center of the metaball. Sheared metaballs are thus allowed. PARTICLE SYSTEM Local Information Format --------------- Part_Count:int32 Vertex_List Where Part_Count is the number of particles in the system. TRIANGLE STRIPS Local Information Format --------------- Vertex_Count:int32 Vertex_List Where Vertex_Count is the number of points in the triangle strip. 1-3 /|/| 0-2-4 TRIANGLE FANS Local Information Format ------------- Vertex_Count:int32 Anchor_Vertex Vertex_List Where Vertex_Count is the number of vertices in the triangle fan. The first vertex forms the anchor and each successive vertex forms a point on a successive triangle: 1-2-3 \|/| 0-4 TRIANGULAR BEZIERS Local Information Format ------------------ Order:int32 Vertex_List The order is the order of the triangular patch. There are order*(order+1)/2 vertices forming the patch. The order of the vertices is, for a degree 3 patch: Column Row +-------- 0 | 6 7 8 9 1 | 3 4 5 2 | 1 2 3 | 0 The vertex index of the vertex in row/column (r,c) is found by calling the GEO_PrimTriBezier::getRawIndex() function. VOLUMES Local Information Format ------- Vertex_Info Matrix33 This controls the size and orienation of the volume Version:int32 Negative version number, -2, -3, and -4 are the current versions. Later versions may have a lower number. -2: Original versioned format -3: Taper support added -4: Data is saved tiled taperx:float32 tapery:float32 Only present for version number -3 and later. 1.0 means no taper, so a rectilinear (square) voxel grid. Taper is the radius of the z-plus side of the voxel grid prior to the size and orientatin matrix being applied. xres:int32 yres:int32 zres:int32 Resolution of the volume voxel array in voxels. The voxel data is stored in the center of the voxels, so the total number of samples is xres*yres*zres bordertype:int32 bordervalue:float32 Defines the end conditions of the volume. bordervalue is a float for out of bounds values to use. bordertype is one of: (binary - ascii) 0 - constant Use bordervalue for outside reads 1 - repeat Read opposite side of volume for outside reads 2 - streak Closest point on the volume will be used 3 - sdf Closest point plus the distance to that point, ensures signed distance fields are valid everywhere. compression_tolerance:float32 Controls how much lossy compression is allowed. volumevistype:int32 visiso:float32 visdensity:float32 Controls visualization of volume in viewport. volumevistype is one of: (binary - ascii) 0 - smoke Render as a cloud with self shadowing 1 - rainbow Render as uniformly lit cloud coloured with bounding box values 2 - iso Render as an isosurface using the visio value 3 - invisible Do not render at all visiso is the isosurface to render in that mode. visdensity is how opaque the could renders should be. volumedata:float32 There are two methods to store the data: tiled and flat. If the version is -4, it is stored tiled. -2 and -3 use flat storage. The HOUDINI10_VOLUME_COMPATIBILITY can be set to force Houdini to always use flat storage if needed for external compatibility. Note ASCII volumes are always stored flat. Flat Data: The actual volume values are stored as xres*yres*zres space delimitted floating point values. The order used is: for (z = 0; z < zres; z++) for (y = 0; y < yres; y++) for (x = 0; x < xres; x++) store voxel(x, y, z); Tiled Data: This data is stored with UT_VoxelArrayF::saveData. Note that code is available in the HDK. version:int8 0 - This is a constant volume. cvalue:float32 The entire volume has this value. 1 - Varying volume values If the version is 0, the cvalue should initialize all the tiles. If the version is 1, the following specification applies. First, the list of supported compression types are given. ntypes:int16 Number of compression types. For each compression type the name is given: compressionname:string8 These names match the UT_VoxelArrayF::getCompressionEngines() along with the internal types of "raw", "rawfull", and "constant" Then the tiles are saved. The xres, yres, zres volume is broken into 16x16x16 tiles. Where it is not divisible by 16, partial tiles are used at the high boundary. Thus the size of tiles on the high boundaries may be smaller than 16x16x16. The order the tiles are loaded is: for (tz = 0; tz < (zres+15)/16; tz++) for (ty = 0; ty < (yres+15)/16; ty++) for (tx = 0; tx < (xres+15)/16; tx++) Each tile has bounds, inclusive, of: X: [tx*16, min(xres, (tx+1)*16)-1] Y: [ty*16, min(yres, (ty+1)*16)-1] Z: [tz*16, min(zres, (tz+1)*16)-1] The format of each tile is: type:int8 The type of compression, indexing into the list of compression types in the compressionnames. "constant": cvalue:float32 All the voxels will have this one value. "raw", "rawfull": voxeldata:float32 The raw voxel data. rawfull is a hint that the voxel is a full 16x16x16 voxel. 5) Detail Attributes ----------------- The Detail Attribute Dictionary is saved after the Primitives and before the group information. 6) Point/Primitive Group Definitions --------------------------------- The Point groups are saved first, followed by the primitive groups. There is no identifier indicating the groups. The format for a group depends on whether it is ordered or unordered: Ascii: GroupName Type NElements BitMask ElementList GroupName - is the name of the group. Type - is "unordered" or "ordered". NElements - Specifies the total number of bits in the BitMask. This is equivalent to the number of elements in the detail. BitMask - In the ASCII format, this is a string of 0's and 1's, where 1 indicates membership in the group. ElementList - If the groups is ordered, the element list contains the index of each selected point or primitive in selection order. The first element of the list is the number of ordered elements in the list. In the case of primitive lists a second profile element may be described by appending a period and a secondary index number to each element. For example 5 specified the fifth primitive while 5.12 specifies the twelfth profile curve of the fifth primitive. The list must be empty if the group is unordered. Binary: [Ordered:char] GroupName:string NElements:int32 BitMask:int32 [NumOrdered:int32 Primary:int32 [Secondary:int32]] Ordered - If this is an ordered group it is the integer 1. If it is not an ordered group, it is not saved to the file! Thus, when you read the ordered flag, if it is not exactly 1, it should be treated as the first character of the group name. GroupName - A var16 giving the length of the string followed by the string itself stored as chars. Note the null terminator is *not* stored nor included in the length. NElements - The number of bits (as opposed to set bits) in the group. For a point group, this would be the number of points. BitMask - The bit mask is stored as a sequence of int32s. The endianess of these need to be corrected as they are loaded. The total number is floor((NElements + 31)/32). If the group is ordered, the list of ordered elements comes next. NumOrdered - The number of elements present in the ordered group. Primary - The primitive number to add to the group. If it is negative, it must be transformed by (-n - 1) to get the actual primitive number. 7) Other Information ----------------- This is meant for saving global information. The section is delimited by special tokens: beginExtra endExtra In binary, the char 0x00 is written to mark the start of the extra block. Each packet will then start with an additional 0x00. The end of the extra block is marked with a 0xff. After the 0x00 signifying the start of a packet, the actual packet data consists of: classid:int16 signature:int16 datalen:int32 data classid is 1 for extra packets. Signature determines which type of extra packet it is. The datalen is the length in bytes of the packet data. Valid contents of the extra section are: Particle Render (signature 1): Ascii: prender { blur ONOFF snml ONOFF size 1.0 btime 1.0 type TYPE } The prender command starts with the prender token. It then has a brace delimited list on one line. The list consists of keyword/value pairs. ONOFF is either "on" or "off" to represent being enabled or not. 1.0 stands for an floating point number. TYPE is one of sphere, line, tube, capped, rounded, or circle. Binary: flag:int32 size:float32 blurtime:float32 type:int32 Flag is a bit field: do motion blur 0x1 sphere normals 0x2 virtual 0x4 Type is an integer: sphere 0 circle 1 line 2 tube 3 capped tubes 4 round tubes 5 Example File ------------- To extract the information: save to a file run uudecode on the file This should generate all.geo.Z Run "uncompress all.geo.Z" which will create "all.geo" - a file containing all the primitives, groups, and attributes. --- Begin UUENCODED data -- begin 664 all.geo.Z M'YV04(X4>=*D"!4I64!8D:'`"90W:=S0F0-BAHT;(!S*2=.&8HP9#1]&I'-$ MSILZ<#QFA+*Q3@X'0M#01`V<-"$D=GU:UB9"NK8X>H5 MK-BD>!O2=7N7K`*\8V.`0`'#10VR3@TC+FQC<8J_B`435@RX\.'*+AI7?ER9 M[>3+9"F'UDR6<^3!EA>+QIO9,63`DE-C!LV:--['@F&C=H%CAF_?JGO_GJ': MME/.O&'D@!$#HV4<-V[@`!W;Q0T;.2[*4'T]^XWMF(W#0#Y#.7/G+G+4B`&C MAG//C&&4AR$^LWP8](N[;E&X_/+FB:G'GGN![39#=CGDT!-F!V*GH'Z;*C"_Z=!\*$`K9'6G4-)KA@ M:%D^Z&2$_0&)$97K66ED?//59\-]^7UIHH]B3ODYZ<+,D1'Y*-U%D8# M##>,2JFHI)J:Z7B;YECCF++!YP(-M-:J6JVV\JGIA.W5X&L-C0$JXVXTX!!# ML;F%ABRRJR+7ZZ_!QEK=>M/%X.AL,51[[6BN%>;JC<+*^JNO]8T+;+-_<>JI M=*`&6D,.,KQ+:&COQIO#O#R""26CC;8[[&0VR)`=OHD%/#"Z?TJ[FXVO%L?P MJ:U%"&BB_&Z+I:&%#H[\"RYCRJZL\NS&LLL9LL:B[#0YD:K,\CN9KO> MMJQ1>_73.!==L;OCEAOVTRE_RG+(G\$KKVKUKETS>5^?':C!-A#,F,!U/WV8 MW$@S?&-X#P>]-\KK*GFQQAG_%K315$]8-KM(EXPI@R,'_?C*A*O,\\P0FZKJ MVZT&[GCA/`/-M.G<2ES8T.>.KCG232?+6NQ/LR[UY55KR[;5UG(M>N:?(ATU MVV.##CR[K@18\RE M^?F:*/?-W\LJ.=!=LQ\^[*B;70`+]B3;C:]]U:$= MTY3F-.-!;6S^:YCP>(>UQ&BM=P[LG[<0N)OAS:9XJ9,>[B+XM^79"WIM:YX# M&4>]#?[O>GC+7@RW1\+W5,=O$,.A^'CE0?>AKU(_9,R36.BQU?4P4B:C7!)# MB*CCT<^`L-L?TZ3(Q%VYL&$\!&$"!R@J+D:OB0^$UJ.@>#\&RBXQ"JPBJXP( M03:*<8*ZPU8#2AV^CUO*<1<8Q'7-@,P[-( M.J9K<'<\E_=>6)OVI0^,EXGDE0P41$$ASI%\TV2@WJ<:4LK/B8DA8P*I.#M6 M]E%]5_R;*`&(JY_5\I2SG&49C]5`99FQ=A[4Y;0HN+LY7E)3L42/*CO(1\LT M\XO(5-?KA-G!0L[&FH[LS]<`*4D8'HR1W\PF9:@),$L6S)Q"5-TX[7$PC6E!8F9PH.QDYAOI]4R%IJM[&;5A-4_H/):N<)LI MG5LC:S/35UITG1PL)R7/N=.*6G&+D[+E$?"Y4G])4 MWBK[*3.JXI)\4;6>07.%T(,Z=5-0S*KAB/7+!4X4F,43:^ZV)D>VBA.K215I M(/F^>U;*LC[-)V`=R\_/Z<^JH-PG9^_GQ9YMZ:L,Q>-H$UA6B4:TKV&E[$;= MFC6/OG6@LI5K-^DZ5YM&$Z6YS>L@LX;-OLISM8HD;,$$"\TUCC.XB.VI8J7+ M6-E`BI-#!6)V,_M4SEYW,J9DZE)1"]50S>J?YP4M>6.JL,F8UI9<76]8S9O& MV;46ML$T[P4K:!G;]A6K^GUF#_N*4OT6UX('YFZZCFM>[8$S;P[,9(,7N]AN MK>9Z%*:NA2%)&\66BD`Z?6@E-1PA%+771YT4CCL=&0/%A`NQ'\8("LY(T>;B MYL*2H3&Z6BSAT5R$!B#6,>AR\UT4;Y3YJ1[>U(VX\U!_>MS>H\L61K.L^=B7B7NYT4BBL;RXO!=J$= MWF^(9UQ^1"8XH`V>V(2#>LG^FE7'L3MI[;;\Y*(9MZ[9W84EQO#4R"`S.&A1M&GF\\',(#TWL`@-RCV6 MJ^<@ZS;8.KM!+IJGVR#J,I@Z1B3C=;"+_=2(:;O6N8[:9!_&[&A7>\%E+/>P MT[TB6)_[V)W=Z!9+1VE(WXW)V1O:<1YFYSU_-WB!_O*)@WN_=>%EG M>N63WSS.U3?T1]-Z,HM?O-#GK!B.BWG3/&X4#6RP;=@81O:TE[;&`X/Y>@OZ M]@K*??YD!/S9U][9CB=Z)A_^^PL%__C$=[[Q=0_RPN]=\4HGL;X;_?G70]R3 ME>?\5Y]-;.BW'M[7YK.PRZ_[QF8R\Q<&M\(?@W>I;SO5YXZW(T4-`P[-0.^I MUGNG)W\$V&7\YW]Z%WWYEW[[)S0(6'NM)X#?%G\4:%+UEW806&T+&&[JIVW4 MEWPCUV:TP7WBU&'OYWN=VB@EV4JJ'U]4GK7-QF5%ARC-X.L5VTN MZ'V*IAM\1AT2&&2+-G[)YWJ)IF=`R&BI87H3>(.8`84ER'T]F(0PZ#`R^%.> M)U3AEX,_=4CAHE3PTU3SMRE_5&3IY5FMI%YE6$/^0EI>96=Q"',&%(9D=59F M]5IE>%%O.%L81"_^M8?(6`E96%G:&!\A6"+2&6.18B#!6&CP5Q*MH-S M8V:?9GFL!UW@9W,NYXDP!X;:=#2518;]@5F:>(:K6%H)54## MPS<0U4OVA8?B5(>C2#5P1%L=Q5&."(O;)"Z&6%>"J(K%."T)9AC-6(FBB%P` M0XF4N&%>0XHWA(DY]"20=%B="#WBUX:]V$*`58KC=5FFF(JD,S^;XXII.'SB M.(CZ!(?Q)8?U2(>U.(^LI8NYJ(>.R(OEZ(?\91B!.(R_$Y"Z)3;(Z(AGZ(TI MA$+/:&'1Z(T.-HG*Y8C=2#J3=&8KB$D'5%`L!XK?*%D[XX:1@XKAM5YG&%+N MA5ZLR#\'R9)=-(8LU5E^"")`R29#"")3`:)#ADY/389E^3)JB$;H=9-VM)8U>8]SZ3.X!)!RR9.B(XPAU)YZ9)O^218E9>R:).TF%9YR9=[R8]]29N?*91_6%M!68FON9L# M9D&)*4(:R9@/V5*0>97>E9G46)G66)@8MI59J%F9])/A")HB>9/'A9UGF8YI M>9P_^9)3Y(YP"5(Y-9-T^5YW&4SC:9M)@YO_Z)[IR9L#*9@?]3]9F9#$:)JG")Y/@E+>2)Z? MU9:O.%`;&IMT>9-AM:'PJ9?,6:(:*2X%:9^#*4$(68B'.9Q*.4T.V8P"*DX4 MNJ(WA*#Y=E.&Q:-E1IV*&H"25HF:''N8JL:9ZNB5M( MZEXB:I>-%UM9>IO^&)]A6HE>BHT=U*+X>5OZR8DTBIC^B8A3^J6/Z93$1:`2 M.5ER:IF1^*/1E$FJHD`5CHT MR9Y=FE\\B^\>JR_ M.J%`QCW,:B!%PB#7VGC"UHW#:JTCJ$W?JHDT@"F.TZW@)6;AAZ[(JD[CFC/] MMTGG.JZ\JJ[1NBG`P2LR`*_],9`'8CD",T8WD"P)Q"%U4L0JT"2RPUD*^9"&08NXWJU'_;L:P5ZU[P4K`CB[`%U"+"VK#$ M4K*=P[+\HQPIRS-U4[`S:[+J]!%I9BUCY5[`4GE`5C?K&E`T@ID:12S3>CKA MFI:MLSK9PC/'4K!/:[,!%2]2PQSZ.BM1VSE9RS_7,48P"T`?(9*T$K;U>C/M MD4I'>S\V$*ZSE[2N>;;>TJ^PL[:W0K=7!;<$);-L:[>-1VPQPBG5ZEYK0K/T M(;5@E*^$`K@A*RHQX'_0,VR.*SC!BC*!&R;."H[0*KG@P2GF:KG&>KE!W:%FT,_ M4J0L>+^*.S?]B[`#_+PW)6R;^R',:P/'4AP-O$(`'+\+\\"C0<'NRR&\.S?# M5AP;_%'NVK2&R670DKO.12/H(<$R*L+D0L+($2^&Q;H7$JXQ3#;%2[G,.\.S MD:VPU20!+#R9.QL_O(L\C,*6$<198\2"2&P81<2&H2@B[,0LG"Y*'+/"`\40 MP[`XX+\WU7^X"L-(7,2@ZT!<3+'N\L6&8<;_6;P@ZRXZ;$%MS)!JC+^]^QPR M_,:B"BYR##;`DHDC;,#19,(`NR5'N<=7O,)^[%PR,+&\PASX@1_@(2X%S#:1 MO$(>,D;_-S?L<6:9',7:E#/"N\#_"DY/HRJ.,S9<2'EB\Q!>U/CVA,W MPZ4W1"NQ#,N'3!YDQBM\>T/;NT6L%$G$FTF+T<0/7W%[T/"SV?%/LC+U6EC+RG&-LX<\?U\WS MT2GM@L_"&ZP&7;'__(4+?6Q$QQR\/,\'O='_W%T!G78I%S#Q#"(17<\)O7!" MW2#YV-P=`D\J_E41&"4RX$>-\75WKM_[C1_SW6O]-]\`#@/??;:9/-]K!W?L ML=_\36R]UKC]#>`![@15(`5"P-L$?N:@?@=R$`9P(-ZC7NH-WMT*`-QSD`84 M01RWO14%(AC;L1W$01P]L>IAT.JO#@*Q#@*SKMS"?NL\`0(03FS51B/]O785 MWCN-*R,@W;@_C<&-^]WQ(A/YBNUK1R*-N]\CCK,R4/'\MW3^K0R@;R\=._[70,R\N/"^]-"+KS?7;S".^$$(KPD M/;PT(B--3B,_G3WAS?'>;-,>'1H?$X M0!4F80;(/>`Z``)N\`9N4`:K7@9ZD`9`X>D%/NE)L>`*;ML,[N"ZSNO%'O2N M/O0:O]]HGBV]MN;9`N!N+A-%DBT3#AU03]+]8BTR@N@73AP7WA,7?G?Y<>$8<>$@_EUW^(<_N$WDJ]WG_&=@N%;WBFU[N6=`O=A7L[* M7?*=I% MG^O;?_9F_B$8CN;^3[DY#04F`&G=FOL0M>X`]@8!Z/86X(>`>T_O`0K`NU,D M/@0%_'!Q[D/4O44A`,]>OQ`8&,[.@4#EIO4$!JTK@0I+8-2ZYB$PX%Z?$QAW M1^SA#1)8]\J>P'`4\Z$BJ+WR8.L.78?0@;=./NC`GE`>B*"BTX$J[FR5A[NC MSX[=8;A_NR[_&3L=V!C*0Q6,&>4!(Y0'$.$?2%Q2^#\ESM+]GUOW$4@<$6Q@ M_\<(V@`(]_2@H-#3?_]'Q0DO$E<%E=W_J8-:$$#\GSS(!9O6_^F#.+!W_!\< MF/@\Q!$_BM`37MZOXQ[C(S3, MKDJ!1KA:8D`/?\M1$#V*L!W>X;"`<,)&"\HS88,#:9\W2W&V3LB=,B)8O%19 MBM."2.Z4X<`E9Q%*G/&S"+`DO@""LQ)I2%_C`@LET14W0Q8R:@C.5@L`J&>I@.:^>D6`I]1F2, M18VX?3JQ?GR'K)-)C.+:^FE2[,*QA\2%'6)84/06%@0_J(JD^.RF8J50=.KA M*BK%3F'NO(6;-\4N*(+`GAHDQ<_#2Q:U:6[-KS)P=`/=( MP&*8*V+CZEPDQ3&3R'!<80A848?,#$9D=NT*PWY;,`I"%":&1A&^\D-2M`B. M;',%+#Q7T!9,L7`U3U!Q7[$(JH<5%Z.;NT[R(4'P1<>8 M%7&B6&P4#:)@%*NKERZRF,!H&<>L;JB]I-@;9!]59&=1KS<2&P1X#U.%F4N* M^NP^:,:VYS2@X]GA@(?Q^J7&%0$LNM9A/&6*[KNEB^\`]A(74Y0.HS$SD"_@ M^!VR6,!+%Q`C,41QC*%1"$;XV!P4W9HI M%:PO+=H'Y4!L"H:O.&4D[9'X1@S&&*3>Q$J*[@&6N;&O\[`P9-T@,Y9AS$B' M7O-(Z@:'L!"D`L_-1L,0,,;,WZ)F&0]#!JQ>A49.9,G#D,:B-V"4`T&U)AR! M-`]_RPK.P:3X%)M;I6`/8%%!GAU]AAW5A:\0>>\MOH&`-$`&,IN!JV_#PM85 MN_NFY4!=#OB&G`[^R3_-9A3:P)4$`>NPV+E#-R#K',>H4!0Y:_9(AZI5*APB MTX(71F-!'0@6\5?L!0/[*Z=,$7%#;8C,-U-$`!P(&:0!),`DH``>GO#<@!,@#: M'IQ%<`Z-+%WB!TK'+MLEDE27\#)>RLMY22\;V5^HE_@R7^K+?0DO[R6__)<` M,V#ZRX!),`OFO!R8!C-A)DR$61;@0$N(B0IN7)9+!5`&F0.Q.9@`CBLP!-EV 2!B)"$<`#.2$,*(!8]S%#I@(` ` end --- End UUENCODED data --