OpenGLContext.scenegraph.indexedfaceset
Indexed Face-set VRML97 node implemented using ArrayGeometry
XXX This node needs some serious optimization. Possible approaches:
display-list-generation, probably the most appropriate
approach of them all, as it will almost certainly
provide a serious speed boost. This can be a
fairly simplistic mechanism, as it won't need the
tesselator, and it can simply process the values
as a stream of instructions.
OpenGL 3.x deprecates display-lists...
GL_TRIANGLE_STRIP, GL_QUAD_STRIP -- can dramatically
reduce memory bandwidth, requires some serious
analysis of the topology to get a decent result
while keeping VRML semantics
IndexedPolygons -- a single index array or equal
index arrays can be rendered without expansion
Double vs. floating point -- be able to downsample
arrays to 'f' type if the data can be precisely
stored within a 'f' type array
GL_ATI_vertex_array_object -- cache arrays on the
"server" side of the GL engine then use them
from there
GL_EXT_vertex_array_set -- cache the arrays in the
client-side GL engine with all arrays together
and the associated enables etc. should make the
call to render a single restore of state and then
glDrawArrays() -- note that I (mcf) don't have
this extension available, so can't implement this.
- GL_EXT_compiled_vertex_array
- should be used if available, alternate version of same functionality GL_EXT_static_vertex_array. This is only useful if we are making multiple calls to render, which we are currently not doing.
cache index-sets:
used to do a take of the data-arrays to get triangles-arrays
depends on the index arrays and the tessellation-types
if no tessellation required:
possible to update the entire coordinate array
and just re-take before rendering
all-equal-index sets:
basically if the indices arrays are all identical
we could use an index-based array-drawing call,
which avoids the take-calls entirely, see
IndexedPolygons for an implementation.
if tessellation required:
store polys-to-tessellate as meta-indices
depends on the index-sets
re-tessellate whenever coordinates change
store end-of-data-array indices
depends on everything, used to decide
where the new values start writing
if the data array has changed, then is
the length of the data-array
Functions
build_normalPerVertex(
vertices
,
creaseAngle
,
vertexArray
= None
)
Create a normal vector using creaseAngle to determine smoothing
Note: the semantics of normalPerVertex requires using expanded
(i.e. tessellated) values, as the generated normals are *not*
supposed to be applied to each vertex, but instead to each
*use* of each vertex (i.e. each triangle's ref to the vertex
has a potentially different normal)
- vertices
- list of vertex objects in rendering order (triangles)
- creaseAngle
- radian angle above which faces do not smooth.
- vertexArray
- x*3*3 array of coordinates expanded into a flat data-array, if not provided, generated from vertices
Classes
class ArrayGeometryCompiler(
IFSCompiler
):
Compiles to an ArrayGeometry instance for rendering uniform arrays of data
compile(
self
,
visible
= 1
,
lit
= 1
,
textured
= 1
,
transparent
= 0
,
mode
= None
)
Compile the rendering structures for an ArrayGeometry version of IFS
XXX Should redo to cache like so...
cache tessellated triangle indices
if any indices change, need to re-calculate everything
coord -> [ pointIndices ], [ calcualtedNormals ]
normal -> [ normalIndices ]
when points change, just re-calculate:
expanded-normals (if we are calculating normals)
expanded-points
when normals change (explicit normal/indices)
expanded-normals
fully-expanded normal, texCooord, and color
class DisplayListCompiler(
IFSCompiler
):
Compiles to a display-list for static geometry
Note that this implementation is basically without real purpose,
the arraygeometry version should be much faster on all modern
hardware, particularly if VBO support is available.
Also note that display lists are deprecated in OpenGL 3.x
class DisplayListRenderer(
object
):
class DummyRender(
object
):
class IFSCompiler(
object
):
__call__(
self
,
*
args
,
**
named
)
Call the compiler to produce the renderer or None if no renderer needed
buildIndexedSources(
self
)
Build the set of IndexedValueSource objects for this node
These are color, normal and texture-coordinate only,
not the coord set, as that's the driver for the rest.
compile(
self
,
visible
= 1
,
lit
= 1
,
textured
= 1
,
transparent
= 0
,
mode
= None
)
Compile a renderer to represent the IFS at run-time
polygons(
self
,
sources
= None
)
Yield each polygon in the IFS
The polygon object is a sub-class of list holding
Vertex objects.
tessellate(
self
,
polygons
= None
,
sources
= None
)
Tessellate our arrays into triangle-only arrays
The return value is a list of triangle vertices, with
each vertex represented by a Vertex instance (see below).
In addition to tessellation, this function is responsible
for turning the index-format structures into a set of
polygons (i.e. identifying the individual polygons within
the indexed face set).
Indexed Face-set VRML97 node
The IndexedFaceSet is the most common VRML97
geometry-node type. Most 3D modellers will export
most geometry as IndexedFaceSets, as they are
the most general of the polygonal geometry types.
The OpenGLContext IndexedFaceSet node tries to
follow the VRML97 IndexedFaceSet node's semantics
as closely as possible whenever those semantics are
defined. If you detect non-conformant operation,
please report it as a bug in OpenGLContext.
There are a number of major sub-types of IFS:
have coord + normal
need to tesselate
need to get simple triangle-points array
need to get simple normals array
# may need texCoordArray as well
# may need color as well
have coord but no normal
need to tesselate
need to get simple triangle-points array
need to calculate normals for (face/vertex)
# may need texCoordArray as well
# may need color as well
have only a single index-set, but 2 or 3 arrays
could just use indexed drawing if all elements
are triangles, in this case we don't have _any_
real overhead for a delta on the points/normals/colors,
what would VRML do?
have everything
once tesselated, we have a simple "take" to get values
class IndexedPolygonsCompiler(
IFSCompiler
):
Compile to set of equal-indexed vertex arrays
compile(
self
,
visible
= 1
,
lit
= 1
,
textured
= 1
,
transparent
= 0
,
mode
= None
)
Compile the rendering structures for an ArrayGeometry version of IFS
XXX Should redo to cache like so...
cache tessellated triangle indices
if any indices change, need to re-calculate everything
coord -> [ pointIndices ], [ calcualtedNormals ]
normal -> [ normalIndices ]
when points change, just re-calculate:
expanded-normals (if we are calculating normals)
expanded-points
when normals change (explicit normal/indices)
expanded-normals
fully-expanded normal, texCooord, and color
class IndexedValueSource(
object
):
Holds data-arrays which together form a source for indexed values
This object should make it possible to reliably
calculate indexed values from multiple arrays
without needing to duplicate the logic for each
array being processed.
__init__(
self
,
vertexIndices
,
indices
,
values
,
perFace
,
name
= 'color'
,
attribute
= 'color'
,
vertexAttribute
= 'color'
)
Initialize the IndexedValueSource object
- vertexIndices
- the vertex indices for the indexedfaceset if indices is NULL, we will use these for-our indices
- indices
- index-values specific to this particular value-type or None if there are no specifically-defined values
- values
- array of values specific to this particular value type or None if there are no specifically-defined values
- perFace
- whether or not this particular type of source is defined on a per-polygon/face basis, that is whether values should be indexed by polygon or vertex position.
- name
- name to be reported in debugging logs