> Date:         Mon, 24 Mar 2003 17:30:50 -0800
> From: Justin Couch <[EMAIL PROTECTED]>
> Mark Hood wrote:
>
> > Indexed geometry is great for storage and convenient for
> > representation, but terrible for rendering.  Graphics hardware wants
> > contiguous streams of vertex data for the best performance.  With
> > indices you can skip around vertex data -- this destroys all
> > locality of reference and creates shorter data packets across the
> > graphics bus.
>
> Except that you have also destroyed the end user's request that they
> want to optimise in a different way - minimal bus usage. By using
> indexed geometry, that's what they are asking for. If they wanted to
> provide interleaved data, then there is the facilities to do so in
> Java3D. Don't screw around with the data in the way we want it
> presented.

So, is your suggestion that Java 3D iterate through the index arrays and
send off individual vertex-level commands to the native graphics layer
for every indexed geometry array every frame?  That would be fairly slow
(the vertex-level immediate mode API of OpenGL, while extremely
flexible, has a lot of overhead), but not unreasonable for applications
prepared to make that tradeoff.

It's important to note however, that the scenegraph is also used to
derive information for spatial queries, so it would slow down other
aspects of the system as well as rendering.  I suspect that the overall
performance implications and the desire to reduce the complexity of the
code led to the implementation decisions to which you object.

> We know best how to render our geometry and how we want to
> optimise. Not you.  If we want to pass it in indexed, leave it that
> way.  The low level graphics APIs support that form, so there is no
> reason not to let it be that way.
> [...]
> > Allowing more fine-grained update sematics to the API could be a
> > reasonable RFE for the next major release of Java 3D.  If anybody
> > thinks this is important for their indexed geometry application,
> > please submit the RFE.
>
> There is no reason for one. All I want you to do is honour what I've
> requested of the rendering API, not what you happen to think might be
> best.

It's not clear to me that using indexed geometry necessarily means that
the programmer is signaling to the implementation that it should
conserve memory at the expense of rendering performance.  A programmer
might decide to use indexed geometry simply because it seems easier to
code, or because the data was already in that format, or perhaps because
some random loader delivered it that way.

Of course you know what you're doing.  But anybody who's read this
interest list can see that many folks using a high-level scene graph API
have the opposite expectation: they want the implementation to figure
out what best to do with the data.  And implementors of the API and
licensees of the source code want to have the flexibility to tune their
implementations and add their own value to it.

For the most part, Java 3D tries to accomodate that point of view, while
providing hooks for advanced users to have more control.  Baking in
overly rigid implementation semantics into a high-level API can have the
effect of making it obsolete faster.  Of course it's a balancing act,
and mistakes will be made.  The RFE mechanism is there to correct
mistakes and omissions.

As Kelvin pointed out, the USE_COORD_INDEX_ONLY attribute was added to
IndexedGeometryArray in Java 3D 1.3 for exactly that problem you're
experiencing.  A single index array for coordinates, colors, normals,
and textures enables Java 3D to use vertex arrays and a single call to
the DrawElements OpenGL command to render indexed geometry directly
without having to unindexify them.  (We need to add a note to the
performance guide to this effect).

If USE_COORD_INDEX_ONLY is not specified, then we can't use DrawElements
to render the geometry.  We either have to iterate through the index
arrays each time or copy the vertex data to an array in the correct
order.  The Java 3D sample implementation does the latter.

> > We have never characterized indexed geometry as high-performance and
> > don't recommend it for performance-sensitive applications.  Using
> > by-reference mode for the vertex data doesn't improve the situation.
>
> What do you define as "performance sensitive"?  If I have an
> application that uses minimal geometry but heavy textures, I want that
> bus allocated to shipping my textures in and out of main memory. I
> don't want it lost to someone else deciding to unindex the geometry on
> me and generating bucketloads of garbage. My code wants to optimise
> for minimal geometry being passed over the bus because other far more
> important things need it, and rendering performance is going to be
> impacted by something else far greater.

The graphics system architectures with which I'm familiar don't work
that way.  I was referring to how the data is transfered, not the amount
of data going over the bus.  Generally for highest performance you want
to initiate a DMA or a low-level system call to transfer the data
asynchronously from the client thread, so that it can return immediately
and do other tasks while the transfer takes place and the data is
rendered.

OpenGL can't do this if the client is making individual vertex-level
calls while sitting in a loop iterating over an index array; it either
has to buffer the data (copy it), or generate a sequence of short
transfers that are much slower than one big transfer.  This is also why
the attribute and state sorting features of the scene graph are so
important -- you want to minimize interruptions to the transfer of
consistent vertex and texture data.

> > There isn't any way for Java 3D to find out if you've changed a normal
> > or a texture coordinate in one or more of the array elements addressed
> > by the reference without iterating through all the data and keeping a
> > copy itself for comparison.
>
> What's that got to do with it? If I've told you I've changed the normal
> data, but nothing else, then that's all I've changed.

I was referring to the by-reference mode for indexed geometry arrays.
In by-reference mode you can update individual array elements directly
without changing the array reference.  There isn't any mechanism in the
GeometryUpdater interface to indicate that only the normal data has
changed, so the current implementation reindexes and recopies everything
if USE_COORD_INDEX_ONLY is not set.  That's why I suggested the RFE.

-- Mark Hood

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA3D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to