1955 lines
73 KiB
Plaintext
1955 lines
73 KiB
Plaintext
THE PHILOSOPHY OF EGG FILES (vs. bam files)
|
|
|
|
Egg files are used by Panda3D to describe many properties of a scene:
|
|
simple geometry, including special effects and collision surfaces,
|
|
characters including skeletons, morphs, and multiple-joint
|
|
assignments, and character animation tables.
|
|
|
|
Egg files are designed to be the lingua franca of model manipulation
|
|
for Panda tools. A number of utilities are provided that read and
|
|
write egg files, for instance to convert to or from some other
|
|
modeling format, or to apply a transform or optimize vertices. The
|
|
egg file philosophy is to describe objects in an abstract way that
|
|
facilitates easy manipulation; thus, the format doesn't (usually)
|
|
include information such as polygon connectivity or triangle meshes.
|
|
Egg files are furthermore designed to be human-readable to help a
|
|
developer diagnose (and sometimes repair) problems. Also, the egg
|
|
syntax is always intended to be backward compatible with previous
|
|
versions, so that as the egg syntax is extended, old egg files will
|
|
continue to remain valid.
|
|
|
|
This is a different philosophy than Panda's bam file format, which is
|
|
a binary representation of a model and/or animation that is designed
|
|
to be loaded quickly and efficiently, and is strictly tied to a
|
|
particular version of Panda. The data in a bam file closely mirrors
|
|
the actual Panda structures that are used for rendering. Although an
|
|
effort is made to keep bam files backward compatible, occasionally
|
|
this is not possible and we must introduce a new bam file major
|
|
version.
|
|
|
|
Where egg files are used for model conversion and manipulation of
|
|
models, bam files are strictly used for loading models into Panda.
|
|
Although you can load an egg file directly, a bam file will be loaded
|
|
much more quickly.
|
|
|
|
Egg files might be generated by outside sources, and thus it makes
|
|
sense to document its syntax here. Bam files, on the other hand,
|
|
should only be generated by Panda3D, usually by the program egg2bam.
|
|
The exact specification of the bam file format, if you should need it,
|
|
is documented within the Panda3D code itself.
|
|
|
|
|
|
GENERAL EGG SYNTAX
|
|
|
|
Egg files consist of a series of sequential and hierarchically-nested
|
|
entries. In general, the syntax of each entry is:
|
|
|
|
<Entry-type> name { contents }
|
|
|
|
Where the name is optional (and in many cases, ignored anyway) and the
|
|
syntax of the contents is determined by the entry-type. The name (and
|
|
strings in general) may be either quoted with double quotes or
|
|
unquoted. Newlines are treated like any other whitespace, and case is
|
|
not significant. The angle brackets are literally a part of the entry
|
|
keyword. (Square brackets and ellipses in this document are used to
|
|
indicate optional pieces, and are not literally part of the syntax.)
|
|
|
|
The name field is always syntactically allowed between an entry
|
|
keyword and its opening brace, even if it will be ignored. In the
|
|
syntax lines given below, the name is not shown if it will be ignored.
|
|
|
|
Comments may be delimited using either the C++-style // ... or the
|
|
C-style /* ... */. C comments do not nest. There is also a <Comment>
|
|
entry type, of the form:
|
|
|
|
<Comment> { text }
|
|
|
|
<Comment> entries are slightly different, in that tools which read and
|
|
write egg files will preserve the text within <Comment> entries, but
|
|
they may not preserve comments delimited by // or /* */. Special
|
|
characters and keywords within a <Comment> entry should be quoted;
|
|
it's safest to quote the entire comment.
|
|
|
|
|
|
|
|
LOCAL INFORMATION ENTRIES
|
|
|
|
These nodes contain information relevant to the current level of
|
|
nesting only.
|
|
|
|
<Scalar> name { value }
|
|
<Char*> name { value }
|
|
|
|
Scalars can appear in various contexts. They are always optional,
|
|
and specify some attribute value relevant to the current context.
|
|
The scalar name is the name of the attribute; different attribute
|
|
names are meaningful in different contexts. The value is either a
|
|
numeric or a (quoted or unquoted) string value; the interpretation
|
|
as a number or as a string depends on the nature of the named
|
|
attribute. Because of a syntactic accident with the way the egg
|
|
syntax evolved, <Scalar> and <Char*> are lexically the same and both
|
|
can represent either a string or a number. <Char*> is being phased
|
|
out; it is suggested that new egg files use only <Scalar>.
|
|
|
|
|
|
|
|
GLOBAL INFORMATION ENTRIES
|
|
|
|
These nodes contain information relevant to the file as a whole. They
|
|
can be nested along with geometry nodes, but this nesting is
|
|
irrelevant and the only significant placement rule is that they should
|
|
appear before they are referenced.
|
|
|
|
|
|
<CoordinateSystem> { string }
|
|
|
|
This entry indicates the coordinate system used in the egg file; the
|
|
egg loader will automatically make a conversion if necessary. The
|
|
following strings are valid: Y-up, Z-up, Y-up-right, Z-up-right,
|
|
Y-up-left, or Z-up-left. (Y-up is the same as Y-up-right, and Z-up
|
|
is the same as Z-up-right.)
|
|
|
|
By convention, this entry should only appear at the beginning of the
|
|
file, although it is technically allowed anywhere. It is an error
|
|
to include more than one coordinate system entry in the same file.
|
|
If it is omitted, Y-up is assumed.
|
|
|
|
|
|
<Texture> name { filename [scalars] }
|
|
|
|
This describes a texture file that can be referenced later with
|
|
<TRef> { name }. It is not necessary to make a <Texture> entry for
|
|
each texture to be used; a texture may also be referenced directly
|
|
by the geometry via an abbreviated inline <Texture> entry, but a
|
|
separate <Texture> entry is the only way to specify anything other
|
|
than the default texture attributes.
|
|
|
|
If the filename is a relative path, the current egg file's directory
|
|
is searched first, and then the texture-path and model-path are
|
|
searched.
|
|
|
|
The following attributes are presently implemented for textures:
|
|
|
|
<Scalar> alpha-file { alpha-filename }
|
|
|
|
If this scalar is present, the texture file's alpha channel is
|
|
read in from the named image file (which should contain a
|
|
grayscale image), and the two images are combined into a single
|
|
two- or four-channel image internally. This is useful for loading
|
|
alpha channels along with image file formats like JPEG that don't
|
|
traditionally support alpha channels.
|
|
|
|
<Scalar> alpha-file-channel { channel }
|
|
|
|
This defines the channel that should be extracted from the file
|
|
named by alpha-file to determine the alpha channel for the
|
|
resulting channel. The default is 0, which means the grayscale
|
|
combination of r, g, b. Otherwise, this should be the 1-based
|
|
channel number, for instance 1, 2, or 3 for r, g, or b,
|
|
respectively, or 4 for the alpha channel of a four-component
|
|
image.
|
|
|
|
<Scalar> format { format-definition }
|
|
|
|
This defines the load format of the image file. The
|
|
format-definition is one of:
|
|
|
|
RGBA, RGBM, RGBA12, RGBA8, RGBA4,
|
|
RGB, RGB12, RGB8, RGB5, RGB332,
|
|
LUMINANCE_ALPHA,
|
|
RED, GREEN, BLUE, ALPHA, LUMINANCE
|
|
|
|
The formats whose names end in digits specifically request a
|
|
particular texel width. RGB12 and RGBA12 specify 48-bit texels
|
|
with or without alpha; RGB8 and RGBA8 specify 32-bit texels, and
|
|
RGB5 and RGBA4 specify 16-bit texels. RGB332 specifies 8-bit
|
|
texels.
|
|
|
|
The remaining formats are generic and specify only the semantic
|
|
meaning of the channels. The size of the texels is determined by
|
|
the width of the components in the image file. RGBA is the most
|
|
general; RGB is the same, but without any alpha channel. RGBM is
|
|
like RGBA, except that it requests only one bit of alpha, if the
|
|
graphics card can provide that, to leave more room for the RGB
|
|
components, which is especially important for older 16-bit
|
|
graphics cards (the "M" stands for "mask", as in a cutout).
|
|
|
|
The number of components of the image file should match the format
|
|
specified; if it does not, the egg loader will attempt to provide
|
|
the closest match that does.
|
|
|
|
<Scalar> compression { compression-mode }
|
|
|
|
Defines an explicit control over the real-time compression mode
|
|
applied to the texture. The various options are:
|
|
|
|
DEFAULT OFF ON
|
|
FXT1 DXT1 DXT2 DXT3 DXT4 DXT5
|
|
|
|
This controls the compression of the texture when it is loaded
|
|
into graphics memory, and has nothing to do with on-disk
|
|
compression such as JPEG. If this option is omitted or "DEFAULT",
|
|
then the texture compression is controlled by the
|
|
compressed-textures config variable. If it is "OFF", texture
|
|
compression is explicitly off for this texture regardless of the
|
|
setting of the config variable; if it is "ON", texture compression
|
|
is explicitly on, and a default compression algorithm supported by
|
|
the driver is selected. If any of the other options, it names the
|
|
specific compression algorithm to be used.
|
|
|
|
<Scalar> wrap { repeat-definition }
|
|
<Scalar> wrapu { repeat-definition }
|
|
<Scalar> wrapv { repeat-definition }
|
|
<Scalar> wrapw { repeat-definition }
|
|
|
|
This defines the behavior of the texture image outside of the
|
|
normal (u,v) range 0.0 - 1.0. It is "REPEAT" to repeat the
|
|
texture to infinity, "CLAMP" not to. The wrapping behavior may be
|
|
specified independently for each axis via "wrapu" and "wrapv", or
|
|
it may be specified for both simultaneously via "wrap".
|
|
|
|
Although less often used, for 3-d textures wrapw may also be
|
|
specified, and it behaves similarly to wrapu and wrapv.
|
|
|
|
There are other legal values in addtional to REPEAT and CLAMP.
|
|
The full list is:
|
|
|
|
CLAMP
|
|
REPEAT
|
|
MIRROR
|
|
MIRROR_ONCE
|
|
BORDER_COLOR
|
|
|
|
<Scalar> borderr { red-value }
|
|
<Scalar> borderg { green-value }
|
|
<Scalar> borderb { blue-value }
|
|
<Scalar> bordera { alpha-value }
|
|
|
|
These define the "border color" of the texture, which is
|
|
particularly important when one of the wrap modes, above, is
|
|
BORDER_COLOR.
|
|
|
|
<Scalar> type { texture-type }
|
|
|
|
This may be one of the following attributes:
|
|
|
|
1D
|
|
2D
|
|
3D
|
|
CUBE_MAP
|
|
|
|
The default is "2D", which specifies a normal, 2-d texture. If
|
|
any of the other types is specified instead, a texture image of
|
|
the corresponding type is loaded.
|
|
|
|
If 3D or CUBE_MAP is specified, then a series of texture images
|
|
must be loaded to make up the complete texture; in this case, the
|
|
texture filename is expected to include a sequence of one or more
|
|
hash mark ("#") characters, which will be filled in with the
|
|
sequence number. The first image in the sequence must be numbered
|
|
0, and there must be no gaps in the sequence. In this case, a
|
|
separate alpha-file designation is ignored; the alpha channel, if
|
|
present, must be included in the same image with the color
|
|
channel(s).
|
|
|
|
<Scalar> read-mipmaps { flag }
|
|
|
|
If this flag is nonzero, then pre-generated mipmap levels will be
|
|
loaded along with the texture. In this case, the filename should
|
|
contain a sequence of one or more hash mark ("#") characters,
|
|
which will be filled in with the mipmap level number; the texture
|
|
filename thus determines a series of images, one for each mipmap
|
|
level. The base texture image is mipmap level 0.
|
|
|
|
If this flag is specified in conjunction with a 3D or cube map
|
|
texture (as specified above), then the filename should contain two
|
|
hash mark sequences, separated by a character such as an
|
|
underscore, hyphen, or dot. The first sequence will be filled in
|
|
with the mipmap level index, and the second sequence will be
|
|
filled in with the 3D sequence or cube map face.
|
|
|
|
<Scalar> minfilter { filter-type }
|
|
<Scalar> magfilter { filter-type }
|
|
<Scalar> magfilteralpha { filter-type }
|
|
<Scalar> magfiltercolor { filter-type }
|
|
|
|
This specifies the type of filter applied when minimizing or
|
|
maximizing. Filter-type may be one of:
|
|
|
|
NEAREST
|
|
LINEAR
|
|
NEAREST_MIPMAP_NEAREST
|
|
LINEAR_MIPMAP_NEAREST
|
|
NEAREST_MIPMAP_LINEAR
|
|
LINEAR_MIPMAP_LINEAR
|
|
|
|
There are also some additional filter types that are supported for
|
|
historical reasons, but each of those additional types maps to one
|
|
of the above. New egg files should use only the above filter
|
|
types.
|
|
|
|
<Scalar> envtype { environment-type }
|
|
|
|
This specifies the type of texture environment to create; i.e. it
|
|
controls the way in which textures apply to models.
|
|
Environment-type may be one of:
|
|
|
|
MODULATE
|
|
DECAL
|
|
BLEND
|
|
REPLACE
|
|
ADD
|
|
BLEND_COLOR_SCALE
|
|
MODULATE_GLOW
|
|
MODULATE_GLOSS
|
|
*NORMAL
|
|
*NORMAL_HEIGHT
|
|
*GLOW
|
|
*GLOSS
|
|
*HEIGHT
|
|
*SELECTOR
|
|
|
|
The default environment type is MODULATE, which means the texture
|
|
color is multiplied with the base polygon (or vertex) color. This
|
|
is the most common texture environment by far. Other environment
|
|
types are more esoteric and are especially useful in the presence
|
|
of multitexture. In particular, the types prefixed by an asterisk
|
|
(*) require enabling Panda's automatic ShaderGenerator.
|
|
|
|
<Scalar> combine-rgb { combine-mode }
|
|
<Scalar> combine-alpha { combine-mode }
|
|
<Scalar> combine-rgb-source0 { combine-source }
|
|
<Scalar> combine-rgb-operand0 { combine-operand }
|
|
<Scalar> combine-rgb-source1 { combine-source }
|
|
<Scalar> combine-rgb-operand1 { combine-operand }
|
|
<Scalar> combine-rgb-source2 { combine-source }
|
|
<Scalar> combine-rgb-operand2 { combine-operand }
|
|
<Scalar> combine-alpha-source0 { combine-source }
|
|
<Scalar> combine-alpha-operand0 { combine-operand }
|
|
<Scalar> combine-alpha-source1 { combine-source }
|
|
<Scalar> combine-alpha-operand1 { combine-operand }
|
|
<Scalar> combine-alpha-source2 { combine-source }
|
|
<Scalar> combine-alpha-operand2 { combine-operand }
|
|
|
|
These options replace the envtype and specify the texture combiner
|
|
mode, which is usually used for multitexturing. This specifies
|
|
how the texture combines with the base color and/or the other
|
|
textures applied previously. You must specify both an rgb and an
|
|
alpha combine mode. Some combine-modes use one source/operand
|
|
pair, and some use all three; most use just two.
|
|
|
|
combine-mode may be one of:
|
|
|
|
REPLACE
|
|
MODULATE
|
|
ADD
|
|
ADD-SIGNED
|
|
INTERPOLATE
|
|
SUBTRACT
|
|
DOT3-RGB
|
|
DOT3-RGBA
|
|
|
|
combine-source may be one of:
|
|
|
|
TEXTURE
|
|
CONSTANT
|
|
PRIMARY-COLOR
|
|
PREVIOUS
|
|
CONSTANT_COLOR_SCALE
|
|
LAST_SAVED_RESULT
|
|
|
|
combine-operand may be one of:
|
|
|
|
SRC-COLOR
|
|
ONE-MINUS-SRC-COLOR
|
|
SRC-ALPHA
|
|
ONE-MINUS-SRC-ALPHA
|
|
|
|
The default values if any of these are omitted are:
|
|
<Scalar> combine-rgb { modulate }
|
|
<Scalar> combine-alpha { modulate }
|
|
<Scalar> combine-rgb-source0 { previous }
|
|
<Scalar> combine-rgb-operand0 { src-color }
|
|
<Scalar> combine-rgb-source1 { texture }
|
|
<Scalar> combine-rgb-operand1 { src-color }
|
|
<Scalar> combine-rgb-source2 { constant }
|
|
<Scalar> combine-rgb-operand2 { src-alpha }
|
|
<Scalar> combine-alpha-source0 { previous }
|
|
<Scalar> combine-alpha-operand0 { src-alpha }
|
|
<Scalar> combine-alpha-source1 { texture }
|
|
<Scalar> combine-alpha-operand1 { src-alpha }
|
|
<Scalar> combine-alpha-source2 { constant }
|
|
<Scalar> combine-alpha-operand2 { src-alpha }
|
|
|
|
<Scalar> saved-result { flag }
|
|
|
|
If flag is nonzero, then it indicates that this particular texture
|
|
stage will be supplied as the "last_saved_result" source for any
|
|
future texture stages.
|
|
|
|
<Scalar> tex-gen { mode }
|
|
|
|
This specifies that texture coordinates for the primitives that
|
|
reference this texture should be dynamically computed at runtime,
|
|
for instance to apply a reflection map or some other effect. The
|
|
valid values for mode are:
|
|
|
|
EYE_SPHERE_MAP (or SPHERE_MAP)
|
|
WORLD_CUBE_MAP
|
|
EYE_CUBE_MAP (or CUBE_MAP)
|
|
WORLD_NORMAL
|
|
EYE_NORMAL
|
|
WORLD_POSITION
|
|
EYE_POSITION
|
|
POINT_SPRITE
|
|
|
|
<Scalar> stage-name { name }
|
|
|
|
Specifies the name of the TextureStage object that is created to
|
|
render this texture. If this is omitted, a custom TextureStage is
|
|
created for this texture if it is required (e.g. because some
|
|
other multitexturing parameter has been specified), or the system
|
|
default TextureStage is used if multitexturing is not required.
|
|
|
|
<Scalar> priority { priority-value }
|
|
|
|
Specifies an integer sort value to rank this texture in priority
|
|
among other textures that are applied to the same geometry. This
|
|
is only used to eliminate low-priority textures in case more
|
|
textures are requested for a particular piece of geometry than the
|
|
graphics hardware can render.
|
|
|
|
<Scalar> blendr { red-value }
|
|
<Scalar> blendg { green-value }
|
|
<Scalar> blendb { blue-value }
|
|
<Scalar> blenda { alpha-value }
|
|
|
|
Specifies a four-component color that is applied with the color in
|
|
case the envtype, above, is "blend", or one of the combine-sources
|
|
is "constant".
|
|
|
|
<Scalar> uv-name { name }
|
|
|
|
Specifies the name of the texture coordinates that are to be
|
|
associated with this texture. If this is omitted, the default
|
|
texture coordinates are used.
|
|
|
|
<Scalar> rgb-scale { scale }
|
|
<Scalar> alpha-scale { scale }
|
|
|
|
Specifies an additional scale factor that will scale the r, g, b
|
|
(or a) components after the texture has been applied. This is
|
|
only used when a combine mode is in effect. The only legal values
|
|
are 1, 2, or 4.
|
|
|
|
<Scalar> alpha { alpha-type }
|
|
|
|
This specifies whether and what type of transparency will be
|
|
performed. Alpha-type may be one of:
|
|
|
|
OFF
|
|
ON
|
|
BLEND
|
|
BLEND_NO_OCCLUDE
|
|
MS
|
|
MS_MASK
|
|
|
|
If alpha-type is OFF, it means not to enable transparency, even if
|
|
the image contains an alpha channel or the format is RGBA. If
|
|
alpha-type is ON, it means to enable the default transparency,
|
|
even if the image filename does not contain an alpha channel. If
|
|
alpha-type is any of the other options, it specifies the type of
|
|
transparency to be enabled.
|
|
|
|
<Scalar> bin { bin-name }
|
|
|
|
This specifies the bin name order of all polygons with this
|
|
texture applied, in the absence of a bin name specified on the
|
|
polygon itself. See the description for bin under polygon
|
|
attributes.
|
|
|
|
<Scalar> draw_order { number }
|
|
|
|
This specifies the fixed drawing order of all polygons with this
|
|
texture applied, in the absence of a drawing order specified on
|
|
the polygon itself. See the description for draw_order under
|
|
polygon attributes.
|
|
|
|
<Scalar> quality-level { quality }
|
|
|
|
Sets a hint to the renderer about the desired performance /
|
|
quality tradeoff for this particular texture. This is most useful
|
|
for the tinydisplay software renderer; for normal,
|
|
hardware-accelerated renderers, this may have little or no effect.
|
|
|
|
This may be one of:
|
|
|
|
DEFAULT
|
|
FASTEST
|
|
NORMAL
|
|
BEST
|
|
|
|
"Default" means to use whatever quality level is specified by the
|
|
global texture-quality-level config variable.
|
|
|
|
<Transform> { transform-definition }
|
|
|
|
This specifies a 2-d or 3-d transformation that is applied to the
|
|
UV's of a surface to generate the texture coordinates.
|
|
|
|
The transform syntax is similar to that for groups, except it may
|
|
define either a 2-d 3x3 matrix or a 3-d 4x4 matrix. (You should
|
|
use the two-dimensional forms if the UV's are two-dimensional, and
|
|
the three-dimensional forms if the UV's are three-dimensional.)
|
|
|
|
A two-dimensional transform may be any sequence of zero or more of
|
|
the following. Transformations are post multiplied in the order
|
|
they are encountered to produce a net transformation matrix.
|
|
Rotations are counterclockwise about the origin in degrees.
|
|
Matrices, when specified explicitly, are row-major.
|
|
|
|
<Translate> { x y }
|
|
<Rotate> { degrees }
|
|
<Scale> { x y }
|
|
<Scale> { s }
|
|
|
|
<Matrix3> {
|
|
00 01 02
|
|
10 11 12
|
|
20 21 22
|
|
}
|
|
|
|
A three-dimensional transform may be any sequence of zero or more
|
|
of the following. See the description under <Group>, below, for
|
|
more information.
|
|
|
|
<Translate> { x y z }
|
|
<RotX> { degrees }
|
|
<RotY> { degrees }
|
|
<RotZ> { degrees }
|
|
<Rotate> { degrees x y z }
|
|
<Scale> { x y z }
|
|
<Scale> { s }
|
|
|
|
<Matrix4> {
|
|
00 01 02 03
|
|
10 11 12 13
|
|
20 21 22 23
|
|
30 31 32 33
|
|
}
|
|
|
|
|
|
<Material> name { [scalars] }
|
|
|
|
This defines a set of material attributes that may later be
|
|
referenced with <MRef> { name }.
|
|
|
|
The following attributes may appear within the material block:
|
|
|
|
<Scalar> diffr { number }
|
|
<Scalar> diffg { number }
|
|
<Scalar> diffb { number }
|
|
<Scalar> diffa { number }
|
|
|
|
<Scalar> ambr { number }
|
|
<Scalar> ambg { number }
|
|
<Scalar> ambb { number }
|
|
<Scalar> amba { number }
|
|
|
|
<Scalar> emitr { number }
|
|
<Scalar> emitg { number }
|
|
<Scalar> emitb { number }
|
|
<Scalar> emita { number }
|
|
|
|
<Scalar> specr { number }
|
|
<Scalar> specg { number }
|
|
<Scalar> specb { number }
|
|
<Scalar> speca { number }
|
|
|
|
<Scalar> shininess { number }
|
|
<Scalar> local { flag }
|
|
|
|
These properties collectively define a "material" that controls the
|
|
lighting effects that are applied to a surface; a material is only
|
|
in effect in the presence of lighting.
|
|
|
|
The four color groups, diff*, amb*, emit*, and spec* specify the
|
|
diffuse, ambient, emission, and specular components of the lighting
|
|
equation, respectively. Any of them may be omitted; the omitted
|
|
component(s) take their color from the native color of the
|
|
primitive, otherwise the primitive color is replaced with the
|
|
material color.
|
|
|
|
The shininess property controls the size of the specular highlight,
|
|
and the value ranges from 0 to 128. A larger value creates a
|
|
smaller highlight (creating the appearance of a shinier surface).
|
|
|
|
|
|
<VertexPool> name { vertices }
|
|
|
|
A vertex pool is a set of vertices. All geometry is created by
|
|
referring to vertices by number in a particular vertex pool. There
|
|
may be one or several vertex pools in an egg file, but all vertices
|
|
that make up a single polygon must come from the same vertex pool.
|
|
The body of a <VertexPool> entry is simply a list of one or more
|
|
<Vertex> entries, as follows:
|
|
|
|
|
|
<Vertex> number { x [y [z [w]]] [attributes] }
|
|
|
|
A <Vertex> entry is only valid within a vertex pool definition.
|
|
The number is the index by which this vertex will be referenced.
|
|
It is optional; if it is omitted, the vertices are implicitly
|
|
numbered consecutively beginning at one. If the number is
|
|
supplied, the vertices need not be consecutive.
|
|
|
|
Normally, vertices are three-dimensional (with coordinates x, y,
|
|
and z); however, in certain cases vertices may have fewer or more
|
|
dimensions, up to four. This is particularly true of vertices
|
|
used as control vertices of NURBS curves and surfaces. If more
|
|
coordinates are supplied than needed, the extra coordinates are
|
|
ignored; if fewer are supplied than needed, the missing
|
|
coordinates are assumed to be 0.
|
|
|
|
The vertex's coordinates are always given in world space,
|
|
regardless of any transforms before the vertex pool or before the
|
|
referencing geometry. If the vertex is referenced by geometry
|
|
under a transform, the egg loader will do an inverse transform to
|
|
move the vertex into the proper coordinate space without changing
|
|
its position in world space. One exception is geometry under an
|
|
<Instance> node; in this case the vertex coordinates are given in
|
|
the space of the <Instance> node. (Another exception is a
|
|
<DynamicVertexPool>; see below.)
|
|
|
|
In neither case does it make a difference whether the vertex pool
|
|
is itself declared under a transform or an <Instance> node. The
|
|
only deciding factor is whether the geometry that *uses* the
|
|
vertex pool appears under an <Instance> node. It is possible for
|
|
a single vertex to be interpreted in different coordinate spaces
|
|
by different polygons.
|
|
|
|
While each vertex must at least have a position, it may also have
|
|
a color, normal, pair of UV coordinates, and/or a set of morph
|
|
offsets. Furthermore, the color, normal, and UV coordinates may
|
|
themselves have morph offsets. Thus, the [attributes] in the
|
|
syntax line above may be replaced with zero or more of the
|
|
following entries:
|
|
|
|
|
|
|
|
<Dxyz> target { x y z }
|
|
|
|
This specifies the offset of this vertex for the named morph
|
|
target. See the "MORPH DESCRIPTION ENTRIES" header, below.
|
|
|
|
|
|
<Normal> { x y z [morph-list] }
|
|
|
|
This specifies the surface normal of the vertex. If omitted, the
|
|
vertex will have no normal. Normals may also be morphed;
|
|
morph-list here is thus an optional list of <DNormal> entries,
|
|
similar to the above.
|
|
|
|
|
|
<RGBA> { r g b a [morph-list] }
|
|
|
|
This specifies the four-valued color of the vertex. Each
|
|
component is in the range 0.0 to 1.0. A vertex color, if
|
|
specified for all vertices of the polygon, overrides the polygon's
|
|
color. If neither color is given, the default is white
|
|
(1 1 1 1). The morph-list is an optional list of <DRGBA> entries.
|
|
|
|
|
|
<UV> [name] { u v [w] [tangent] [binormal] [morph-list] }
|
|
|
|
This gives the texture coordinates of the vertex. This must be
|
|
specified if a texture is to be mapped onto this geometry.
|
|
|
|
The texture coordinates are usually two-dimensional, with two
|
|
component values (u v), but they may also be three-dimensional,
|
|
with three component values (u v w). (Arguably, it should be
|
|
called <UVW> instead of <UV> in the three-dimensional case, but
|
|
it's not.)
|
|
|
|
As before, morph-list is an optional list of <DUV> entries.
|
|
|
|
Unlike the other kinds of attributes, there may be multiple sets
|
|
of UV's on each vertex, each with a unique name; this provides
|
|
support for multitexturing. The name may be omitted to specify
|
|
the default UV's.
|
|
|
|
The UV's also support an optional tangent and binormal. These
|
|
values are based on the vertex normal and the UV coordinates of
|
|
connected vertices, and are used to render normal maps and similar
|
|
lighting effects. They are defined within the <UV> entry because
|
|
there may be a different set of tangents and binormals for each
|
|
different UV coordinate set. If present, they have the expected
|
|
syntax:
|
|
|
|
<UV> [name] { u v [w] <Tangent> { x y z } <Binormal> { x y z } }
|
|
|
|
|
|
<DynamicVertexPool> name { vertices }
|
|
|
|
A dynamic vertex pool is similar to a vertex pool in most respects,
|
|
except that each vertex might be animated by substituting in values
|
|
from a <VertexAnim> table. Also, the vertices defined within a
|
|
dynamic vertex pool are always given in local coordinates, instead
|
|
of world coordinates.
|
|
|
|
The presence of a dynamic vertex pool makes sense only within a
|
|
character model, and a single dynamic vertex pool may not span
|
|
multiple characters. Each dynamic vertex pool creates a DynVerts
|
|
object within the character by the same name; this name is used
|
|
later when matching up the corresponding <VertexAnim>.
|
|
|
|
At the present time, the DynamicVertexPool is not implemented in
|
|
Panda3D.
|
|
|
|
|
|
|
|
|
|
GEOMETRY ENTRIES
|
|
|
|
<Polygon> name {
|
|
[attributes]
|
|
<VertexRef> {
|
|
indices
|
|
<Ref> { pool-name }
|
|
}
|
|
}
|
|
|
|
A polygon consists of a sequence of vertices from a single vertex
|
|
pool. Vertices are identified by pool-name and index number within
|
|
the pool; indices is a list of vertex numbers within the given
|
|
vertex pool. Vertices are listed in counterclockwise order.
|
|
Although the vertices must all come from the same vertex pool, they
|
|
may have been assigned to arbitrarily many different joints
|
|
regardless of joint connectivity (there is no "straddle-polygon"
|
|
limitation). See Joints, below.
|
|
|
|
The polygon syntax is quite verbose, and there isn't any way to
|
|
specify a set of attributes that applies to a group of polygons--the
|
|
attributes list must be repeated for each polygon. This is why egg
|
|
files tend to be very large.
|
|
|
|
The following attributes may be specified for polygons:
|
|
|
|
<TRef> { texture-name }
|
|
|
|
This refers to a named <Texture> entry given earlier. It applies
|
|
the given texture to the polygon. This requires that all the
|
|
polygon's vertices have been assigned texture coordinates.
|
|
|
|
This attribute may be repeated multiple times to specify
|
|
multitexture. In this case, each named texture is applied to the
|
|
polygon, in the order specified.
|
|
|
|
|
|
<Texture> { filename }
|
|
|
|
This is another way to apply a texture to a polygon. The
|
|
<Texture> entry is defined "inline" to the polygon, instead of
|
|
referring to a <Texture> entry given earlier. There is no way to
|
|
specify texture attributes given this form.
|
|
|
|
There's no advantage to this syntax for texture mapping. It's
|
|
supported only because it's required by some older egg files.
|
|
|
|
|
|
<MRef> { material-name }
|
|
|
|
This applies the material properties defined in the earlier
|
|
<Material> entry to the polygon.
|
|
|
|
|
|
<Normal> { x y z [morph-list] }
|
|
|
|
This defines a polygon surface normal. The polygon normal will be
|
|
used unless all vertices also have a normal. If no normal is
|
|
defined, none will be supplied. The polygon normal, like the
|
|
vertex normal, may be morphed by specifying a series of <DNormal>
|
|
entries.
|
|
|
|
The polygon normal is used only for lighting and environment
|
|
mapping calculations, and is not related to the implicit normal
|
|
calculated for CollisionPolygons.
|
|
|
|
|
|
<RGBA> { r g b a [morph-list] }
|
|
|
|
This defines the polygon's color, which will be used unless all
|
|
vertices also have a color. If no color is defined, the default
|
|
is white (1 1 1 1). The color may be morphed with a series of
|
|
<DRGBA> entries.
|
|
|
|
|
|
<BFace> { boolean-value }
|
|
|
|
This defines whether the polygon will be rendered double-sided
|
|
(i.e. its back face will be visible). By default, this option is
|
|
disabled, and polygons are one-sided; specifying a nonzero value
|
|
disables backface culling for this particular polygon and allows
|
|
it to be viewed from either side.
|
|
|
|
|
|
<Scalar> bin { bin-name }
|
|
|
|
It is sometimes important to control the order in which objects
|
|
are rendered, particularly when transparency is in use. In Panda,
|
|
this is achieved via the use of named bins and, within certain
|
|
kinds of bins, sometimes an explicit draw_order is also used (see
|
|
below).
|
|
|
|
In the normal (state-sorting) mode, Panda renders its geometry by
|
|
first grouping into one or more named bins, and then rendering the
|
|
bins in a specified order. The programmer is free to define any
|
|
number of bins, named whatever he/she desires.
|
|
|
|
This scalar specifies which bin this particular polygon is to be
|
|
rendered within. If no bin scalar is given, or if the name given
|
|
does not match any of the known bins, the polygon will be assigned
|
|
to the default bin, which renders all opaque geometry sorted by
|
|
state, followed by all transparent geometry sorted back-to-front.
|
|
|
|
See also draw_order, below.
|
|
|
|
|
|
<Scalar> draw_order { number }
|
|
|
|
This works in conjunction with bin, above, to further refine the
|
|
order in which this polygon is drawn, relative to other geometry
|
|
in the same bin. If (and only if) the bin type named in the bin
|
|
scalar is a CullBinFixed, this draw_order is used to define the
|
|
fixed order that all geometry in the same will be rendered, from
|
|
smaller numbers to larger numbers.
|
|
|
|
If the draw_order scalar is specified but no bin scalar is
|
|
specified, the default is a bin named "fixed", which is a
|
|
CullBinFixed object that always exists by default.
|
|
|
|
|
|
<Scalar> visibility { hidden | normal }
|
|
|
|
If the visibility of a primitive is set to "hidden", the primitive
|
|
is not generated as a normally visible primitive. If the
|
|
Config.prc variable egg-suppress-hidden is set to true, the
|
|
primitive is not converted at all; otherwise, it is converted as a
|
|
"stashed" node.
|
|
|
|
This, like the other rendering flags alpha, draw_order, and bin,
|
|
may be specified at the group level, within the primitive level,
|
|
or even within a texture.
|
|
|
|
|
|
<PointLight> name {
|
|
[attributes]
|
|
<VertexRef> {
|
|
indices
|
|
<Ref> { pool-name }
|
|
}
|
|
}
|
|
|
|
A PointLight is a set of single points. One point is drawn for each
|
|
vertex listed in the <VertexRef>. Normals, textures, and colors may
|
|
be specified for PointLights, as well as draw_order, plus one
|
|
additional attribute valid only for PointLights and Lines:
|
|
|
|
<Scalar> thick { number }
|
|
|
|
This specifies the size of the PointLight (or the width of a
|
|
line), in pixels, when it is rendered. This may be a
|
|
floating-point number, but the fractional part is meaningful only
|
|
when antialiasing is in effect. The default is 1.0.
|
|
|
|
<Scalar> perspective { boolean-value }
|
|
|
|
If this is specified, then the thickness, above, is to interpreted
|
|
as a size in 3-d spatial units, rather than a size in pixels, and
|
|
the point should be scaled according to its distance from the
|
|
viewer normally.
|
|
|
|
|
|
|
|
<Line> name {
|
|
[attributes]
|
|
<VertexRef> {
|
|
indices
|
|
<Ref> { pool-name }
|
|
}
|
|
[component attributes]
|
|
}
|
|
|
|
A Line is a connected set of line segments. The listed N vertices
|
|
define a series of N-1 line segments, drawn between vertex 0 and
|
|
vertex 1, vertex 1 and vertex 2, etc. The line is not implicitly
|
|
closed; if you wish to represent a loop, you must repeat vertex 0 at
|
|
the end. As with a PointLight, normals, textures, colors,
|
|
draw_order, and the "thick" attribute are all valid (but not
|
|
"perspective"). Also, since a Line (with more than two vertices) is
|
|
made up of multiple line segments, it may contain a number of
|
|
<Component> entries, to set a different color and/or normal for each
|
|
line segment, as in TriangleStrip, below.
|
|
|
|
|
|
<TriangleStrip> name {
|
|
[attributes]
|
|
<VertexRef> {
|
|
indices
|
|
<Ref> { pool-name }
|
|
}
|
|
[component attributes]
|
|
}
|
|
|
|
A triangle strip is only rarely encountered in an egg file; it is
|
|
normally generated automatically only during load time, when
|
|
connected triangles are automatically meshed for loading, and even
|
|
then it exists only momentarily. Since a triangle strip is a
|
|
rendering optimization only and adds no useful scene information
|
|
over a loose collection of triangles, its usage is contrary to the
|
|
general egg philosophy of representing a scene in the abstract.
|
|
Nevertheless, the syntax exists, primarily to allow inspection of
|
|
the meshing results when needed. You can also add custom
|
|
TriangleStrip entries to force a particular mesh arrangement.
|
|
|
|
A triangle strip is defined as a series of connected triangles.
|
|
After the first three vertices, which define the first triangle,
|
|
each new vertex defines one additional triangle, by alternating up
|
|
and down.
|
|
|
|
It is possible for the individual triangles of a triangle strip to
|
|
have a separate normal and/or color. If so, a <Component> entry
|
|
should be given for each so-modified triangle:
|
|
|
|
<Component> index {
|
|
<RGBA> { r g b a [morph-list] }
|
|
<Normal> { x y z [morph-list] }
|
|
}
|
|
|
|
Where index ranges from 0 to the number of components defined by the
|
|
triangle strip (less 1). Note that the component attribute list
|
|
must always follow the vertex list.
|
|
|
|
|
|
<TriangleFan> name {
|
|
[attributes]
|
|
<VertexRef> {
|
|
indices
|
|
<Ref> { pool-name }
|
|
}
|
|
[component attributes]
|
|
}
|
|
|
|
A triangle fan is similar to a triangle strip, except all of the
|
|
connected triangles share the same vertex, which is the first
|
|
vertex. See <TriangleStrip>, above.
|
|
|
|
|
|
|
|
PARAMETRIC DESCRIPTION ENTRIES
|
|
|
|
The following entries define parametric curves and surfaces.
|
|
Generally, Panda supports these only in the abstract; they're not
|
|
geometry in the true sense but do exist in the scene graph and may
|
|
have specific meaning to the application. However, Panda can create
|
|
visible representations of these parametrics to aid visualization.
|
|
|
|
These entries might also have meaning to external tools outside of an
|
|
interactive Panda session, such as egg-qtess, which can be used to
|
|
convert NURBS surfaces to polygons at different levels of resolution.
|
|
|
|
In general, dynamic attributes such as morphs and joint assignment are
|
|
legal for the control vertices of the following parametrics, but Panda
|
|
itself doesn't support them and will always create static curves and
|
|
surfaces. External tools like egg-qtess, however, may respect them.
|
|
|
|
<NURBSCurve> {
|
|
[attributes]
|
|
|
|
<Order> { order }
|
|
<Knots> { knot-list }
|
|
<VertexRef> { indices <Ref> { pool-name } }
|
|
}
|
|
|
|
A NURBS curve is a general parametric curve. It is often used to
|
|
represent a motion path, e.g. for a camera or an object.
|
|
|
|
The order is equal to the degree of the polynomial basis plus 1. It
|
|
must be an integer in the range [1,4].
|
|
|
|
The number of vertices must be equal to the number of knots minus the
|
|
order.
|
|
|
|
Each control vertex of a NURBS is defined in homogeneous space with
|
|
four coordinates x y z w (to convert to 3-space, divide x, y, and z
|
|
by w). The last coordinate is always the homogeneous coordinate; if
|
|
only three coordinates are given, it specifies a curve in two
|
|
dimensions plus a homogeneous coordinate (x y w).
|
|
|
|
The following attributes may be defined:
|
|
|
|
<Scalar> type { curve-type }
|
|
|
|
This defines the semanting meaning of this curve, either XYZ, HPR,
|
|
or T. If the type is XYZ, the curve will automatically be
|
|
transformed between Y-up and Z-up if necessary; otherwise, it will
|
|
be left alone.
|
|
|
|
<Scalar> subdiv { num-segments }
|
|
|
|
If this scalar is given and nonzero, Panda will create a visible
|
|
representation of the curve when the scene is loaded. The number
|
|
represents the number of line segments to draw to approximate the
|
|
curve.
|
|
|
|
<RGBA> { r g b a [morph-list] }
|
|
|
|
This specifies the color of the overall curve.
|
|
|
|
|
|
NURBS control vertices may also be given color and/or morph
|
|
attributes, but <Normal> and <UV> entries do not apply to NURBS
|
|
vertices.
|
|
|
|
|
|
|
|
<NURBSSurface> name {
|
|
[attributes]
|
|
|
|
<Order> { u-order v-order }
|
|
<U-knots> { u-knot-list }
|
|
<V-knots> { v-knot-list }
|
|
|
|
<VertexRef> {
|
|
indices
|
|
<Ref> { pool-name }
|
|
}
|
|
}
|
|
|
|
A NURBS surface is an extension of a NURBS curve into two parametric
|
|
dimensions, u and v. NURBS surfaces may be given the same set of
|
|
attributes assigned to polygons, except for normals: <TRef>,
|
|
<Texture>, <MRef>, <RGBA>, and draw_order are all valid attributes
|
|
for NURBS. NURBS vertices, similarly, may be colored or morphed,
|
|
but <Normal> and <UV> entries do not apply to NURBS vertices. The
|
|
attributes may also include <NURBSCurve> and <Trim> entries; see
|
|
below.
|
|
|
|
To have Panda create a visualization of a NURBS surface, the
|
|
following two attributes should be defined as well:
|
|
|
|
<Scalar> U-subdiv { u-num-segments }
|
|
<Scalar> V-subdiv { v-num-segments }
|
|
|
|
These define the number of subdivisions to make in the U and V
|
|
directions to represent the surface. A uniform subdivision is
|
|
always made, and trim curves are not respected (though they will
|
|
be drawn in if the trim curves themselves also have a subiv
|
|
parameter). This is only intended as a cheesy visualization.
|
|
|
|
|
|
The same sort of restrictions on order and knots applies to NURBS
|
|
surfaces as do to NURBS curves. The order and knot description may
|
|
be different in each dimension.
|
|
|
|
The surface must have u-num * v-num vertices, where u-num is the
|
|
number of u-knots minus the u-order, and v-num is the number of
|
|
v-knots minus the v-order. All vertices must come from the same
|
|
vertex pool. The nth (zero-based) index number defines control
|
|
vertex (u, v) of the surface, where n = (v * u-num) + u. Thus, it
|
|
is the u coordinate which changes faster.
|
|
|
|
As with the NURBS curve, each control vertex is defined in
|
|
homogeneous space with four coordinates x y z w.
|
|
|
|
|
|
A NURBS may also contain curves on its surface. These are one or
|
|
more nested <NURBSCurve> entries included with the attributes; these
|
|
curves are defined in the two-dimensional parametric space of the
|
|
surface. Thus, these curve vertices should have only two dimensions
|
|
plus the homogeneous coordinate: u v w. A curve-on-surface has no
|
|
intrinsic meaning to the surface, unless it is defined within a
|
|
<Trim> entry, below.
|
|
|
|
Finally, a NURBS may be trimmed by one or more trim curves. These
|
|
are special curves on the surface which exclude certain areas from
|
|
the NURBS surface definition. The inside is specified using two
|
|
rules: an odd winding rule that states that the inside consists of
|
|
all regions for which an infinite ray from any point in the region
|
|
will intersect the trim curve an odd number of times, and a curve
|
|
orientation rule that states that the inside consists of the regions
|
|
to the left as the curve is traced.
|
|
|
|
Each trim curve contains one or more loops, and each loop contains
|
|
one or more NURBS curves. The curves of a loop connect in a
|
|
head-to-tail fashion and must be explicitly closed.
|
|
|
|
The trim curve syntax is as follows:
|
|
|
|
<Trim> {
|
|
<Loop> {
|
|
<NURBSCurve> {
|
|
<Order> { order }
|
|
<Knots> { knot-list }
|
|
|
|
<VertexRef> { indices <Ref> { pool-name } }
|
|
}
|
|
[ <NURBSCurve> { ... } ... ]
|
|
}
|
|
[ <Loop> { ... } ... ]
|
|
}
|
|
|
|
Although the egg syntax supports trim curves, there are at present
|
|
no egg processing tools that respect them. For instance, egg-qtess
|
|
ignores trim curves and always tesselates the entire NURBS surface.
|
|
|
|
|
|
MORPH DESCRIPTION ENTRIES
|
|
|
|
Morphs are linear interpolations of attribute values at run time,
|
|
according to values read from an animation table. In general, vertex
|
|
positions, surface normals, texture coordinates, and colors may be
|
|
morphed.
|
|
|
|
A morph target is defined by giving a net morph offset for a series of
|
|
vertex or polygon attributes; this offset is the value that will be
|
|
added to the attribute when the morph target has the value 1.0. At
|
|
run time, the morph target's value may be animated to any scalar value
|
|
(but generally between 0.0 and 1.0); the corresponding fraction of the
|
|
offset is added to the attribute each frame.
|
|
|
|
There is no explicit morph target definition; a morph target exists
|
|
solely as the set of all offsets that share the same target name. The
|
|
target name may be any arbitrary string; like any name in an egg file,
|
|
it should be quoted if it contains special characters.
|
|
|
|
The following types of morph offsets may be defined, within their
|
|
corresponding attribute entries:
|
|
|
|
<Dxyz> target { x y z }
|
|
|
|
A position delta, valid within a <Vertex> entry or a <CV> entry.
|
|
The given offset vector, scaled by the morph target's value, is
|
|
added to the vertex or CV position each frame.
|
|
|
|
|
|
<DNormal> target { x y z }
|
|
|
|
A normal delta, similar to the position delta, valid within a
|
|
<Normal> entry (for vertex or polygon normals). The given offset
|
|
vector, scaled by the morph target's value, is added to the normal
|
|
vector each frame. The resulting vector may not be automatically
|
|
normalized to unit length.
|
|
|
|
|
|
<DUV> target { u v [w] }
|
|
|
|
A texture-coordinate delta, valid within a <UV> entry (within a
|
|
<Vertex> entry). The offset vector should be 2-valued if the
|
|
enclosing UV is 2-valued, or 3-valued if the enclosing UV is
|
|
3-valued. The given offset vector, scaled by the morph target's
|
|
value, is added to the vertex's texture coordinates each frame.
|
|
|
|
|
|
<DRGBA> target { r g b a }
|
|
|
|
A color delta, valid within an <RGBA> entry (for vertex or polygon
|
|
colors). The given 4-valued offset vector, scaled by the morph
|
|
target's value, is added to the color value each frame.
|
|
|
|
|
|
|
|
|
|
GROUPING ENTRIES
|
|
|
|
<Group> name { group-body }
|
|
|
|
A <Group> node is the primary means of providing structure to the
|
|
egg file. Groups can contain vertex pools and polygons, as well as
|
|
other groups. The egg loader translates <Group> nodes directly into
|
|
PandaNodes in the scene graph (although the egg loader reserves the
|
|
right to arbitrarily remove nodes that it deems unimportant--see the
|
|
<Model> flag, below to avoid this). In addition, the following
|
|
entries can be given specifically within a <Group> node to specify
|
|
attributes of the group:
|
|
|
|
GROUP BINARY ATTRIBUTES
|
|
|
|
These attributes may be either on or off; they are off by default.
|
|
They are turned on by specifying a non-zero "boolean-value".
|
|
|
|
<DCS> { boolean-value }
|
|
|
|
DCS stands for Dynamic Coordinate System. This indicates that
|
|
show code will expect to be able to read the transform set on this
|
|
node at run time, and may need to modify the transform further.
|
|
This is a special case of <Model>, below.
|
|
|
|
<DCS> { dcs-type }
|
|
|
|
This is another syntax for the <DCS> flag. The dcs-type string
|
|
should be one of either "local" or "net", which specifies the kind
|
|
of preserve_transform flag that will be set on the corresponding
|
|
ModelNode. If the string is "local", it indicates that the local
|
|
transform on this node (as well as the net transform) will not be
|
|
affected by any flattening operation and will be preserved through
|
|
the entire model loading process. If the string is "net", then
|
|
only the net transform will be preserved; the local transform may
|
|
be adjusted in the event of a flatten operation.
|
|
|
|
<Model> { boolean-value }
|
|
|
|
This indicates that the show code might need a pointer to this
|
|
particular group. This creates a ModelNode at the corresponding
|
|
level, which is guaranteed not to be removed by any flatten
|
|
operation. However, its transform might still be changed, but see
|
|
also the <DCS> flag, above.
|
|
|
|
|
|
<Dart> { boolean-value }
|
|
|
|
This indicates that this group begins an animated character. A
|
|
Character node, which is the fundamental animatable object of
|
|
Panda's high-level Actor class, will be created for this group.
|
|
|
|
This flag should always be present within the <Group> entry at the
|
|
top of any hierarchy of <Joint>'s and/or geometry with morphed
|
|
vertices; joints and morphs appearing outside of a hierarchy
|
|
identified with a <Dart> flag are undefined.
|
|
|
|
<Switch> { boolean-value }
|
|
|
|
This attribute indicates that the child nodes of this group
|
|
represent a series of animation frames that should be
|
|
consecutively displayed. In the absence of an "fps" scalar for
|
|
the group (see below), the egg loader creates a SwitchNode, and it
|
|
the responsibility of the show code to perform the switching. If
|
|
an fps scalar is defined and is nonzero, the egg loader creates a
|
|
SequenceNode instead, which automatically cycles through its
|
|
children.
|
|
|
|
|
|
GROUP SCALARS
|
|
|
|
<Scalar> fps { frame-rate }
|
|
|
|
This specifies the rate of animation for a SequenceNode (created
|
|
when the Switch flag is specified, see above). A value of zero
|
|
indicates a SwitchNode should be created instead.
|
|
|
|
<Scalar> bin { bin-name }
|
|
|
|
This specifies the bin name for all polygons at or below this node
|
|
that do not explicitly set their own bin. See the description of
|
|
bin for geometry attributes, above.
|
|
|
|
<Scalar> draw_order { number }
|
|
|
|
This specifies the drawing order for all polygons at or below this
|
|
node that do not explicitly set their own drawing order. See the
|
|
description of draw_order for geometry attributes, above.
|
|
|
|
<Scalar> visibility { hidden | normal }
|
|
|
|
If the visibility of a group is set to "hidden", the primitives
|
|
nested within that group are not generated as a normally visible
|
|
primitive. If the Config.prc variable egg-suppress-hidden is set
|
|
to true, the primitives are not converted at all; otherwise, they
|
|
are converted as a "stashed" node.
|
|
|
|
<Scalar> decal { boolean-value }
|
|
|
|
If this is present and boolean-value is non-zero, it indicates
|
|
that the geometry *below* this level is coplanar with the geometry
|
|
*at* this level, and the geometry below is to be drawn as a decal
|
|
onto the geometry at this level. This means the geometry below
|
|
this level will be rendered "on top of" this geometry, but without
|
|
the Z-fighting artifacts one might expect without the use of the
|
|
decal flag.
|
|
|
|
<Scalar> decalbase { boolean-value }
|
|
|
|
This can optionally be used with the "decal" scalar, above. If
|
|
present, it should be applied to a sibling of one or more nodes
|
|
with the "decal" scalar on. It indicates which of the sibling
|
|
nodes should be treated as the base of the decal. In the absence
|
|
of this scalar, the parent of all decal nodes is used as the decal
|
|
base. This scalar is useful when the modeling package is unable
|
|
to parent geometry nodes to other geometry nodes.
|
|
|
|
<Scalar> collide-mask { value }
|
|
<Scalar> from-collide-mask { value }
|
|
<Scalar> into-collide-mask { value }
|
|
|
|
Sets the CollideMasks on the collision nodes and geometry nodes
|
|
created at or below this group to the indicated values. These
|
|
are bits that indicate which objects can collide with which
|
|
other objects. Setting "collide-mask" is equivalent to setting
|
|
both "from-collide-mask" and "into-collide-mask" to the same
|
|
value.
|
|
|
|
The value may be an ordinary decimal integer, or a hex number in
|
|
the form 0x000, or a binary number in the form 0b000.
|
|
|
|
<Scalar> blend { mode }
|
|
|
|
Specifies that a special blend mode should be applied geometry at
|
|
this level and below. The available options are none, add,
|
|
subtract, inv-subtract, min, and max. See ColorBlendAttrib.
|
|
|
|
<Scalar> blendop-a { mode }
|
|
<Scalar> blendop-b { mode }
|
|
|
|
If blend mode, above, is not none, this specifies the A and B
|
|
operands to the blend equation. Common options are zero, one,
|
|
incoming-color, one-minus-incoming-color. See ColorBlendAttrib
|
|
for the complete list of available options. The default is "one".
|
|
|
|
<Scalar> blendr { red-value }
|
|
<Scalar> blendg { green-value }
|
|
<Scalar> blendb { blue-value }
|
|
<Scalar> blenda { alpha-value }
|
|
|
|
If blend mode, above, is not none, and one of the blend operands
|
|
is constant-color or a related option, this defines the constant
|
|
color that will be used.
|
|
|
|
|
|
OTHER GROUP ATTRIBUTES
|
|
|
|
<Billboard> { type }
|
|
|
|
This entry indicates that all geometry defined at or below this
|
|
group level is part of a billboard that will rotate to face the
|
|
camera. Type is either "axis" or "point", describing the type of
|
|
rotation.
|
|
|
|
Billboards rotate about their local axis. In the case of a Y-up
|
|
file, the billboards rotate about the Y axis; in a Z-up file, they
|
|
rotate about the Z axis. Point-rotation billboards rotate about
|
|
the origin.
|
|
|
|
There is an implicit <Instance> around billboard geometry. This
|
|
means that the geometry within a billboard is not specified in
|
|
world coordinates, but in the local billboard space. Thus, a
|
|
vertex drawn at point 0,0,0 will appear to be at the pivot point
|
|
of the billboard, not at the origin of the scene.
|
|
|
|
<SwitchCondition> {
|
|
<Distance> {
|
|
in out [fade] <Vertex> { x y z }
|
|
}
|
|
}
|
|
|
|
The subtree beginning at this node and below represents a single
|
|
level of detail for a particular model. Sibling nodes represent
|
|
the additional levels of detail. The geometry at this node will
|
|
be visible when the point (x, y, z) is closer than "in" units, but
|
|
further than "out" units, from the camera. "fade" is presently
|
|
ignored.
|
|
|
|
|
|
<Tag> key { value }
|
|
|
|
This attribute defines the indicated tag (as a key/value pair),
|
|
retrievable via NodePath::get_tag() and related interfaces, on
|
|
this node.
|
|
|
|
|
|
<Collide> name { type [flags] }
|
|
|
|
This entry indicates that geometry defined at this group level is
|
|
actually an invisible collision surface, and is not true geometry.
|
|
The geometry is used to define the extents of the collision
|
|
surface. If there is no geometry defined at this level, then a
|
|
child is searched for with the same collision type specified, and
|
|
its geometry is used to define the extent of the collision
|
|
surface (unless the "descend" flag is given; see below).
|
|
|
|
Valid types so far are:
|
|
|
|
Plane
|
|
|
|
The geometry represents an infinite plane. The first polygon
|
|
found in the group will define the plane.
|
|
|
|
Polygon
|
|
|
|
The geometry represents a single polygon. The first polygon is
|
|
used.
|
|
|
|
Polyset
|
|
|
|
The geometry represents a complex shape made up of several
|
|
polygons. This collision type should not be overused, as it
|
|
provides the least optimization benefit.
|
|
|
|
Sphere
|
|
|
|
The geometry represents a sphere. The vertices in the group are
|
|
averaged together to determine the sphere's center and radius.
|
|
|
|
InvSphere
|
|
|
|
The geometry represents an inverse sphere. This is the same as
|
|
Sphere, with the normal inverted, so that the solid part of an
|
|
inverse sphere is the entire world outside of it. Note that an
|
|
inverse sphere is in infinitely large solid with a finite hole
|
|
cut into it.
|
|
|
|
Tube
|
|
|
|
The geometry represents a tube. This is a cylinder-like shape
|
|
with hemispherical endcaps; it is sometimes called a capsule or
|
|
a lozenge in other packages. The smallest tube shape that will
|
|
fit around the vertices is used.
|
|
|
|
|
|
The flags may be any zero or more of:
|
|
|
|
event
|
|
|
|
Throws the name of the <Collide> entry, or the name of the
|
|
surface if the <Collide> entry has no name, as an event whenever
|
|
an avatar strikes the solid. This is the default if the
|
|
<Collide> entry has a name.
|
|
|
|
intangible
|
|
|
|
Rather than being a solid collision surface, the defined surface
|
|
represents a boundary. The name of the surface will be thrown
|
|
as an event when an avatar crosses into the interior, and
|
|
name-out will be thrown when an avater exits.
|
|
|
|
descend
|
|
|
|
Instead of creating only one collision object of the given type,
|
|
each group descended from this node that contains geometry will
|
|
define a new collision object of the given type. The event
|
|
name, if any, will also be inherited from the top node and
|
|
shared among all the collision objects.
|
|
|
|
keep
|
|
|
|
Don't discard the visible geometry after using it to define a
|
|
collision surface; create both an invisible collision surface
|
|
and the visible geometry.
|
|
|
|
level
|
|
|
|
Stores a special effective normal with the collision solid that
|
|
points up, regardless of the actual shape or orientation of the
|
|
solid. This can be used to allow an avatar to stand on a
|
|
sloping surface without having a tendency to slide downward.
|
|
|
|
|
|
<ObjectType> { type }
|
|
|
|
This is a short form to indicate one of several pre-canned sets of
|
|
attributes. Type may be any word, and a Config definition will be
|
|
searched for by the name "egg-object-type-word", where "word" is
|
|
the type word. This definition may contain any arbitrary egg
|
|
syntax to be parsed in at this group level.
|
|
|
|
A number of predefined ObjectType definitions are provided:
|
|
|
|
barrier
|
|
|
|
This is equivalent to <Collide> { Polyset descend }. The
|
|
geometry defined at this root and below defines an invisible
|
|
collision solid.
|
|
|
|
trigger
|
|
|
|
This is equivalent to <Collide> { Polyset descend intangible }.
|
|
The geometry defined at this root and below defines an invisible
|
|
trigger surface.
|
|
|
|
sphere
|
|
|
|
Equivalent to <Collide> { Sphere descend }. The geometry is
|
|
replaced with the smallest collision sphere that will enclose
|
|
it. Typically you model a sphere in polygons and put this flag
|
|
on it to create a collision sphere of the same size.
|
|
|
|
tube
|
|
|
|
Equivalent to <Collide> { Tube descend }. As in sphere, above,
|
|
but the geometry is replaced with a collision tube (a capsule).
|
|
Typically you will model a capsule or a cylinder in polygons.
|
|
|
|
bubble
|
|
|
|
Equivalent to <Collide> { Sphere keep descend }. A collision
|
|
bubble is placed around the geometry, which is otherwise
|
|
unchanged.
|
|
|
|
ghost
|
|
|
|
Equivalent to <Scalar> collide-mask { 0 }. It means that the
|
|
geometry beginning at this node and below should never be
|
|
collided with--characters will pass through it.
|
|
|
|
backstage
|
|
|
|
This has no equivalent; it is treated as a special case. It
|
|
means that the geometry at this node and below should not be
|
|
translated. This will normally be used on scale references and
|
|
other modeling tools.
|
|
|
|
There may also be additional predefined egg object types not
|
|
listed here; see the *.pp files that are installed into the etc
|
|
directory for a complete list.
|
|
|
|
<Transform> { transform-definition }
|
|
|
|
This specifies a matrix transform at this group level. This
|
|
defines a local coordinate space for this group and its
|
|
descendents. Vertices are still specified in world coordinates
|
|
(in a vertex pool), but any geometry assigned to this group will
|
|
be inverse transformed to move its vertices to the local space.
|
|
|
|
The transform definition may be any sequence of zero or more of
|
|
the following. Transformations are post multiplied in the order
|
|
they are encountered to produce a net transformation matrix.
|
|
Rotations are defined as a counterclockwise angle in degrees about
|
|
a particular axis, either implicit (about the x, y, or z axis), or
|
|
arbitrary. Matrices, when specified explicitly, are row-major.
|
|
|
|
<Translate> { x y z }
|
|
<RotX> { degrees }
|
|
<RotY> { degrees }
|
|
<RotZ> { degrees }
|
|
<Rotate> { degrees x y z }
|
|
<Scale> { x y z }
|
|
<Scale> { s }
|
|
|
|
<Matrix4> {
|
|
00 01 02 03
|
|
10 11 12 13
|
|
20 21 22 23
|
|
30 31 32 33
|
|
}
|
|
|
|
Note that the <Transform> block should always define a 3-d
|
|
transform when it appears within the body of a <Group>, while it
|
|
may define either a 2-d or a 3-d transform when it appears within
|
|
the body of a <Texture>. See <Texture>, above.
|
|
|
|
<DefaultPose> { transform-definition }
|
|
|
|
This defines an optional default pose transform, which might be a
|
|
different transform from that defined by the <Transform> entry,
|
|
above. This makes sense only for a <Joint>. See the <Joint>
|
|
description, below.
|
|
|
|
The default pose transform defines the transform the joint will
|
|
maintain in the absence of any animation being applied. This is
|
|
different from the <Transform> entry, which defines the coordinate
|
|
space the joint must have in order to keep its vertices in their
|
|
(global space) position as given in the egg file. If this is
|
|
different from the <Transform> entry, the joint's vertices will
|
|
*not* be in their egg file position at initial load. If there is
|
|
no <DefaultPose> entry for a particular joint, the implicit
|
|
default-pose transform is the same as the <Transform> entry.
|
|
|
|
Normally, the <DefaultPose> entry, if any, is created by the
|
|
egg-optchar -defpose option. Most other software has little
|
|
reason to specify an explicit <DefaultPose>.
|
|
|
|
<VertexRef> { indices <Ref> { pool-name } }
|
|
|
|
This moves geometry created from the named vertices into the
|
|
current group, regardless of the group in which the geometry is
|
|
actually defined. See the <Joint> description, below.
|
|
|
|
<AnimPreload> {
|
|
<Scalar> fps { float-value }
|
|
<Scalar> num-frames { integer-value }
|
|
}
|
|
|
|
One or more AnimPreload entries may appear within the <Group> that
|
|
contains a <Dart> entry, indicating an animated character (see
|
|
above). These AnimPreload entries record the minimal preloaded
|
|
animation data required in order to support asynchronous animation
|
|
binding. These entries are typically generated by the egg-optchar
|
|
program with the -preload option, and are used by the Actor code
|
|
when allow-async-bind is True (the default).
|
|
|
|
|
|
<Instance> name { group-body }
|
|
|
|
An <Instance> node is exactly like a <Group> node, except that
|
|
vertices referenced by geometry created under the <Instance> node
|
|
are not assumed to be given in world coordinates, but are instead
|
|
given in the local space of the <Instance> node itself (including
|
|
any transforms given to the node).
|
|
|
|
In other words, geometry under an <Instance> node is defined in
|
|
local coordinates. In principle, similar geometry can be created
|
|
under several different <Instance> nodes, and thus can be positioned
|
|
in a different place in the scene each instance. This doesn't
|
|
necessarily imply the use of shared geometry in the Panda3D scene
|
|
graph, but see the <Ref> syntax, below.
|
|
|
|
This is particularly useful in conjunction with a <File> entry, to
|
|
load external file references at places other than the origin.
|
|
|
|
|
|
A special syntax of <Instance> entries does actually create shared
|
|
geometry in the scene graph. The syntax is:
|
|
|
|
<Instance> name {
|
|
<Ref> { group-name }
|
|
[ <Ref> { group-name } ... ]
|
|
}
|
|
|
|
In this case, the referenced group name will appear as a duplicate
|
|
instance in this part of the tree. Local transforms can be applied
|
|
and are relative to the referencing group's transform. The
|
|
referenced group must appear preceding this point in the egg file,
|
|
and it will also be a part of the scene in the point at which it
|
|
first appears. The referenced group may be either a <Group> or an
|
|
<Instance> of its own; usually, it is a <Group> nested within an
|
|
earlier <Instance> entry.
|
|
|
|
|
|
<Joint> name { [transform] [ref-list] [joint-list] }
|
|
|
|
A joint is a highly specialized kind of grouping node. A tree of
|
|
joints is used to specify the skeletal structure of an animated
|
|
character.
|
|
|
|
A joint may only contain one of three things. It may contain a
|
|
<Transform> entry, as above, which defines the joint's unanimated
|
|
(rest) position; it may contain lists of assigned vertices or CV's;
|
|
and it may contain other joints.
|
|
|
|
A tree of <Joint> nodes only makes sense within a character
|
|
definition, which is created by applying the <DART> flag to a group.
|
|
See <DART>, above.
|
|
|
|
The vertex assignment is crucial. This is how the geometry of a
|
|
character is made to move with the joints. The character's geometry
|
|
is actually defined outside the joint tree, and each vertex must be
|
|
assigned to one or more joints within the tree.
|
|
|
|
This is done with zero or more <VertexRef> entries per joint, as the
|
|
following:
|
|
|
|
<VertexRef> { indices [<Scalar> membership { m }] <Ref> { pool-name } }
|
|
|
|
This is syntactically similar to the way vertices are assigned to
|
|
polygons. Each <VertexRef> entry can assign vertices from only one
|
|
vertex pool (but there may be many <VertexRef> entries per joint).
|
|
Indices is a list of vertex numbers from the specied vertex pool, in
|
|
an arbitrary order.
|
|
|
|
The membership scalar is optional. If specified, it is a value
|
|
between 0.0 and 1.0 that indicates the fraction of dominance this
|
|
joint has over the vertices. This is used to implement
|
|
soft-skinning, so that each vertex may have partial ownership in
|
|
several joints.
|
|
|
|
The <VertexRef> entry may also be given to ordinary <Group> nodes.
|
|
In this case, it treats the geometry as if it was parented under the
|
|
group in the first place. Non-total membership assignments are
|
|
meaningless.
|
|
|
|
|
|
<Bundle> name { table-list }
|
|
<Table> name { table-body }
|
|
|
|
A table is a set of animated values for joints. A tree of tables
|
|
with the same structure as the corresponding tree of joints must be
|
|
defined for each character to be animated. Such a tree is placed
|
|
under a <Bundle> node, which provides a handle within Panda to the
|
|
tree as a whole.
|
|
|
|
Bundles may only contain tables; tables may contain more tables,
|
|
bundles, or any one of the following (<Scalar> entries are optional,
|
|
and default as shown):
|
|
|
|
<S$Anim> name {
|
|
<Scalar> fps { 24 }
|
|
<V> { values }
|
|
}
|
|
|
|
This is a table of scalar values, one per frame. This may be
|
|
applied to a morph slider, for instance.
|
|
|
|
|
|
<Xfm$Anim> name {
|
|
<Scalar> fps { 24 }
|
|
<Scalar> order { srpht }
|
|
<Scalar> contents { ijkabcrphxyz }
|
|
<V> { values }
|
|
}
|
|
|
|
This is a table of matrix transforms, one per frame, such as may
|
|
be applied to a joint. The "contents" string consists of a subset
|
|
of the letters "ijkabcrphxyz", where each letter corresponds to a
|
|
column of the table; <V> is a list of numbers of length(contents)
|
|
* num_frames. Each letter of the contents string corresponds to a
|
|
type of transformation:
|
|
|
|
i, j, k - scale in x, y, z directions, respectively
|
|
a, b, c - shear in xy, xz, and yz planes, respectively
|
|
r, p, h - rotate by pitch, heading, roll
|
|
x, y, z - translate in x, y, z directions
|
|
|
|
The net transformation matrix specified by each row of the table
|
|
is defined as the net effect of each of the individual columns'
|
|
transform, according to the corresponding letter in the contents
|
|
string. The order the transforms are applied is defined by the
|
|
order string:
|
|
|
|
s - all scale and shear transforms
|
|
r, p, h - individual rotate transforms
|
|
t - all translation transforms
|
|
|
|
|
|
<Xfm$Anim_S$> name {
|
|
<Scalar> fps { 24 }
|
|
<Scalar> order { srpht }
|
|
<S$Anim> i { ... }
|
|
<S$Anim> j { ... }
|
|
...
|
|
}
|
|
|
|
This is a variant on the <Xfm$Anim> entry, where each column of
|
|
the table is entered as a separate <S$Anim> table. This syntax
|
|
reflects an attempt to simplify the description by not requiring
|
|
repetition of values for columns that did not change value during
|
|
an animation sequence.
|
|
|
|
|
|
<VertexAnim> name {
|
|
<Scalar> width { table-width }
|
|
<Scalar> fps { 24 }
|
|
<V> { values }
|
|
}
|
|
|
|
This is a table of vertex positions, normals, texture coordinates,
|
|
or colors. These values will be subsituted at runtime for the
|
|
corresponding values in a <DynamicVertexPool>. The name of the
|
|
table should be "coords", "norms", "texCoords", or "colors",
|
|
according to the type of values defined. The number table-width
|
|
is the number of floats in each row of the table. In the case of
|
|
a coords or norms table, this must be 3 times the number of
|
|
vertices in the corresponding dynamic vertex pool. (For texCoords
|
|
and colors, this number must be 2 times and 4 times, respectively.)
|
|
|
|
|
|
|
|
MISCELLANEOUS
|
|
|
|
<File> { filename }
|
|
|
|
This includes a copy of the referenced egg file at the current
|
|
point. This is usually placed under an <Instance> node, so that the
|
|
current transform will apply to the geometry in the external file.
|
|
The extension ".egg" is implied if it is omitted.
|
|
|
|
As with texture filenames, the filename may be a relative path, in
|
|
which case the current egg file's directory is searched first, and
|
|
then the model-path is searched.
|
|
|
|
|
|
|
|
ANIMATION STRUCTURE
|
|
|
|
Unanimated models may be defined in egg files without much regard to
|
|
any particular structure, so long as named entries like VertexPools
|
|
and Textures appear before they are referenced.
|
|
|
|
However, a certain rigid structural convention must be followed in
|
|
order to properly define an animated skeleton-morph model and its
|
|
associated animation data.
|
|
|
|
The structure for an animated model should resemble the following:
|
|
|
|
<Group> CHARACTER_NAME {
|
|
<Dart> { 1 }
|
|
<Joint> JOINT_A {
|
|
<Transform> { ... }
|
|
<VertexRef> { ... }
|
|
<Group> { <Polygon> ... }
|
|
<Joint> JOINT_B {
|
|
<Transform> { ... }
|
|
<VertexRef> { ... }
|
|
<Group> { <Polygon> ... }
|
|
}
|
|
<Joint> JOINT_C {
|
|
<Transform> { ... }
|
|
<VertexRef> { ... }
|
|
<Group> { <Polygon> ... }
|
|
}
|
|
...
|
|
}
|
|
}
|
|
|
|
The <Dart> flag is necessary to indicate that this group begins an
|
|
animated model description. Without the <Dart> flag, joints will be
|
|
treated as ordinary groups, and morphs will be ignored.
|
|
|
|
In the above, UPPERCASE NAMES represent an arbitrary name that you
|
|
may choose. The name of the enclosing group, CHARACTER_NAME, is
|
|
taken as the name of the animated model. It should generally match
|
|
the bundle name in the associated animation tables.
|
|
|
|
Within the <Dart> group, you may define an arbitrary hierarchy of
|
|
<Joint> entries. There may be as many <Joint> entries as you like,
|
|
and they may have any nesting complexity you like. There may be
|
|
either one root <Joint>, or multiple roots. However, you must
|
|
always include at least one <Joint>, even if your animation consists
|
|
entirely of morphs.
|
|
|
|
Polygons may be directly attached to joints by enclosing them within
|
|
the <Joint> group, perhaps with additional nesting <Group> entries,
|
|
as illustrated above. This will result in the polygon's vertices
|
|
being hard-assigned to the joint it appears within. Alternatively,
|
|
you declare the polygons elsewhere in the egg file, and use
|
|
<VertexRef> entries within the <Joint> group to associate the
|
|
vertices with the joints. This is the more common approach, since
|
|
it allows for soft-assignment of vertices to multiple joints.
|
|
|
|
It is not necessary for every joint to have vertices at all. Every
|
|
joint should include a transform entry, however, which defines the
|
|
initial, resting transform of the joint (but see also <DefaultPose>,
|
|
above). If a transform is omitted, the identity transform is
|
|
assumed.
|
|
|
|
Some of the vertex definitions may include morph entries, as
|
|
described in MORPH DESCRIPTION ENTRIES, above. These are meaningful
|
|
only for vertices that are assigned, either implicitly or
|
|
explicitly, to at least one joint.
|
|
|
|
You may have multiple versions of a particular animated model--for
|
|
instance, multiple different LOD's, or multiple different clothing
|
|
options. Normally each different version is stored in a different
|
|
egg file, but it is also possible to include multiple versions
|
|
within the same egg file. If the different versions are intended to
|
|
play the same animations, they should all have the same
|
|
CHARACTER_NAME, and their joint hierarchies should exactly match in
|
|
structure and names.
|
|
|
|
The structure for an animation table should resemble the following:
|
|
|
|
<Table> {
|
|
<Bundle> CHARACTER_NAME {
|
|
<Table> "<skeleton>" {
|
|
<Table> JOINT_A {
|
|
<Xfm$Anim_S$> xform {
|
|
<Char*> order { sphrt }
|
|
<Scalar> fps { 24 }
|
|
<S$Anim> x { 0 0 10 10 20 ... }
|
|
<S$Anim> y { 0 0 0 0 0 ... }
|
|
<S$Anim> z { 20 20 20 20 20 ... }
|
|
}
|
|
<Table> JOINT_B {
|
|
<Xfm$Anim_S$> xform {
|
|
<Char*> order { sphrt }
|
|
<Scalar> fps { 24 }
|
|
<S$Anim> x { ... }
|
|
<S$Anim> y { ... }
|
|
<S$Anim> z { ... }
|
|
}
|
|
}
|
|
<Table> JOINT_C {
|
|
<Xfm$Anim_S$> xform {
|
|
<Char*> order { sphrt }
|
|
<Scalar> fps { 24 }
|
|
<S$Anim> x { ... }
|
|
<S$Anim> y { ... }
|
|
<S$Anim> z { ... }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
<Table> morph {
|
|
<S$Anim> MORPH_A {
|
|
<Scalar> fps { 24 }
|
|
<V> { 0 0 0 0.1 0.2 0.3 1 ... }
|
|
}
|
|
<S$Anim> MORPH_B {
|
|
<Scalar> fps { 24 }
|
|
<V> { ... }
|
|
}
|
|
<S$Anim> MORPH_C {
|
|
<Scalar> fps { 24 }
|
|
<V> { ... }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
The <Bundle> entry begins an animation table description. This
|
|
entry must have at least one child: a <Table> named "<skeleton>"
|
|
(this name is a literal keyword and must be present). The children
|
|
of this <Table> entry should be a hierarchy of additional <Table>
|
|
entries, one for each joint in the model. The joint structure and
|
|
names defined by the <Table> hierarchy should exactly match the
|
|
joint structure and names defined by the <Joint> hierarchy in the
|
|
corresponding model.
|
|
|
|
Each <Table> that corresponds to a joint should have one child, an
|
|
<Xfm$Anim_S$> entry named "xform" (this name is a literal keyword
|
|
and must be present). Within this entry, there is a series of up to
|
|
twelve <S$Anim> entries, each with a one-letter name like "x", "y",
|
|
or "z", which define the per-frame x, y, z position of the
|
|
corresponding joint. There is one numeric entry for each frame, and
|
|
all frames represent the same length of time. You can also define
|
|
rotation, scale, and shear. See the full description of
|
|
<Xfm$Anim_S$>, above.
|
|
|
|
Within a particular animation bundle, all of the various components
|
|
throughout the various <Tables> should define the same number of
|
|
frames, with the exception that if any of them define exactly one
|
|
frame value, that value is understood to be replicated the
|
|
appropriate number of times to match the number of frames defined by
|
|
other components.
|
|
|
|
(Note that you may alternatively define an animation table with an
|
|
<Xfm$Anim> entry, which defines all of the individual components in
|
|
one big matrix instead of individually. See the full description
|
|
above.)
|
|
|
|
Each joint defines its frame rate independently, with an "fps"
|
|
scalar. This determines the number of frames per second for the
|
|
frame data within this table. Typically, all joints have the same
|
|
frame rate, but it is possible for different joints to animate at
|
|
different speeds.
|
|
|
|
Each joint also defines the order in which its components should be
|
|
composed to determine the complete transform matrix, with an "order"
|
|
scalar. This is described in more detail above.
|
|
|
|
|
|
If any of the vertices in the model have morphs, the top-level
|
|
<Table> should also include a <Table> named "morph" (this name is
|
|
also a literal keyword). This table in turn contains a list of
|
|
<S$Anim> entries, one for each named morph description. Each table
|
|
contains a list of numeric values, one per frame; as with the joint
|
|
data, there should be the same number of numeric values in all
|
|
tables, with the exception that just one value is understood to mean
|
|
hold that value through the entire animation.
|
|
|
|
The "morph" table may be omitted if there are no morphs defined in
|
|
the model.
|
|
|
|
There should be a separate <Bundle> definition for each different
|
|
animation. The <Bundle> name should match the CHARACTER_NAME used
|
|
for the model, above. Typically each bundle is stored in a separate
|
|
egg file, but it is also possible to store multiple different
|
|
animation bundles within the same egg file. If you do this, you may
|
|
violate the CHARACTER_NAME rule, and give each bundle a different
|
|
name; this will become the name of the animation in the Actor
|
|
interface.
|
|
|
|
Although animations and models are typically stored in separate egg
|
|
files, it is possible to store them together in one large egg file.
|
|
The Actor interface will then make available all of the animations
|
|
it finds within the egg file, by bundle name.
|
|
|