18.2 Threads running a Java 3D application
By now I hope you are curious to know how Java 3D achieves what it does. In this chapter we gallop through some of the implementation details behind the Java 3D API gaining insight into getting the most from Java 3D and maximizing the performance of your applications. This chapter gives you some clues for implementing your own 3D graphics API in Java.
Sun’s Java 3D internal implementation details are all subject to change at any time. The version described here is Java 3D 1.2 running on the Win32 platform.
The implementation of the Java 3D API has undergone considerable revision between the 1.1 and 1.2 versions of the API. About 70 percent of the Java code was rewritten between these two versions! The Java 3D 1.1 architecture was fairly simplistic and could be considered a proof-of-concept implementation of the API.
Version 1.2 moved to a message-based architecture and took tighter control of the various worker threads created by the API implementation. The collision detection thread was removed in 1.2, and collision detection is carried out by the new TimerThread
functionality. By explicitly activating the threads in the system, the 1.2 API has removed the free-running threads (behaviors and collision detection) that caused 100 percent CPU utilization in Java 3D 1.1.
As you can see from tables 18.1 through 18.3, a typical Java 3D application contains many threads, some concerned with system behavior, some running the GUI event processing, and some (13) controlling the Java 3D runtime environment. The two ThreadGroups
, “main” and “Java 3D,” are subgroups of the top-level “system” ThreadGroup
.
The Java 3D threads have the default thread priority of 5, although this can be controlled using the VirtualUniverse.setJ3DThreadPriority
method. The priority must fall between Thread.MAX_PRIORITY
and Thread.MIN_PRIORITY
. The default is Thread.NORM_PRIORITY
. The priority of the parent ThreadGroup
(Java 3D) cannot be exceeded. Note that unlike nondaemon threads, daemon threads do not have to exit their Runnable
’s run
method for the JVM to exit.
Name | Priority | Daemon |
---|---|---|
Reference Handler | 10 | Yes |
Finalizer | 8 | Yes |
Signal Dispatcher | 10 | Yes |
Name | Priority | Daemon |
---|---|---|
Main | 5 | No |
AWT-EventQueue-0 | 6 | No |
SunToolkit.PostEventQueue-0 | 5 | No |
AWT-Windows | 5 | No |
Image Fetcher 1 | 8 | No |
Image Fetcher 0 | 8 | No |
Name | Priority | Daemon |
---|---|---|
J3D-MasterControl | 5 | No |
J3D-RenderingAttributesStructureUpdateThread | 5 | No |
J3D-TimerThread | 5 | No |
J3D-BehaviorStructureUpdateThread-1 | 5 | No |
J3D-GeometryStructureUpdateThread-1 | 5 | No |
J3D-SoundStructureUpdateThread-1 | 5 | No |
J3D-RenderingEnvironmentStructureUpdateThread-1 | 5 | No |
J3D-TransformStructureUpdateThread-1 | 5 | No |
J3D-BehaviorScheduler-1 | 5 | No |
J3D-RenderStructureUpdateThread-1 | 5 | No |
J3D-SoundSchedulerUpdateThread-1 | 5 | No |
J3D-InputDeviceScheduler-1 | 5 | No |
J3D-Renderer-1 | 5 | No |
The Java 3D implementation is heavily multithreaded. Typically each thread controls access to a particular data structure. The threads use the MasterControl
thread to periodically synchronize and exchange notifications and messages across threads. Each thread maintains a subclass of the J3dStructure
member, which contains the messages to be processed by the thread. The
Once a message is posted to a thread by the MasterControl
thread, the receiving thread is marked as having work to do and scheduled for activation. See the discussion of the MasterControl
class for details of the message dispatch and processing mechanism.
Most threads are associated with an instance of a VirtualUniverse
(threads with the -1 suffix), while the MasterControl
, RenderingAttributesStructureUpdateThread
, and TimerThread
are systemwide and maintain data structures that apply across all VirtualUniverse
instances.
The multithreaded nature of Java 3D allows it to leverage multiple CPUs if available; however, it does make synchronizing certain operations difficult or impossible.
As illustrated in figure 18.1 a Windows Java 3D application creates five threads above normal priority and three Time Critical threads. This will cause other applications running simultaneously to experience a dramatic slowdown when the Java 3D application is in the foreground.
The MasterControl
class is Java 3D’s central message dispatch and thread scheduling mechanism. The MasterControl
object is a static member of the VirtualUniverse
class, and is initialized by a static initializer on the VirtualUniverse
class. All instances of the VirtualUniverse
class therefore share the same MasterControl
instance.
The first time a message is posted to the MasterControl
class, it creates the MasterControlThread
. The MasterControlThread
runs the main message-processing loop for the MasterControl
class.
Master Root Thread Group Name: Java3D Thread Name: J3D-MasterControl |
class MasterControlThread extends Thread
{
MasterControlThread(ThreadGroup threadgroup)
{
super(threadgroup, "J3D-MasterControl");
VirtualUniverse.mc.createMCThreads();
start();
}
public void run()
{
do
while(VirtualUniverse.mc.running)
{
VirtualUniverse.mc.doWork();
Thread.yield();
}
while(!VirtualUniverse.mc.mcThreadDone());
}
}
The constructor for the MasterControl
class loads the J3D.DLL native DLL and reads the Java 3D system properties (see table 18.4).
The MasterControl
class is a message exchange mechanism between the various subsystems that compose the Java 3D runtime. The MasterControl
thread maintains five UnorderList
members, each containing Java 3D worker threads.
stateWorkThreads
:RenderingAttributesStructure
calls updateMirrorObject
on the NodeComponentRetained
passed with the message.GeometryStructure
maintains a binary hash tree of GeometryAtom
objects and Groups
. Maintains the wakeupOnCollisionEntry
, Exit
, and Movement
lists.BehaviorStructure
maintains a list of behaviors and marks them for activation.RenderingEnvironmentStructure
maintains a list of the lights, fog, alternate appearances, clipping regions, and backgrounds to be used for each RenderAtom
.SoundStructure
maintains a list of sounds and soundscapes and schedules them for activation with the View
’s SoundScheduler
.BehaviorScheduler
, for all VirtualUniverse
instances, maintains a list of BillBoard
behaviors and behaviors in the system and calls the processStimulus
method on each if marked for activation.Inputdevicescheduler
maintains lists of nonblocking and blocking input devices and calls the pollAndProcessInput
method on the nonblocking devices. A new thread is created to handle the input from each blocking InputDevice
.RenderBin
, for each View
, maintains lists of RenderAtoms
that describe rendering operations to be performed. The RenderBin
implements methods such as renderOpaque
, renderBackground
, renderOrdered
, renderTransparent
, which are called by the Render
class.SoundScheduler
, for each View
, maintains a list of SoundSchedulerAtoms
and marks each for activation. The render
method iterates the scheduled SoundSchedulerAtoms
and calls the start
method on each.renderWorkThreads
:Renderer
for each Canvas3D
’s Screen3D
. The Render
class runs the main Java 3D rendering loop by calling methods on the Canvas3D
class and processing the RenderBin
for the Canvas3D
’s View
.requestRenderWorkThreads
:Renderer
for each Screen3D
in the device render map.renderThreadData
:Renderer
for each Screen3D
for each View
, including offscreen Renderers
.inputDeviceThreads
:Inputdevicescheduler
.Each UnorderList
member contains an array of J3dThreadData
objects, containing a J3dThread
member and additional scheduling information.
The MasterControl.doWork
method (invoked by the MasterControlThread.run
method) runs in two phases. The first phase checks for any pending messages to be executed and returns if there is nothing to execute. The second phase runs the threads under the control of the MasterControl
class.
void doWork()
{
runMonitor( CHECK_FOR_WORK, null, null, null, null);
if(pendingRequest)
handlePendingRequest();
if(!running)
return;
if(threadListsChanged)
updateWorkThreads();
updateTimeValues();
View aview[] = (View[])views.toArray(false);
for(int i = views.size() - 1; i >= 0; i--)
if(aview[i].active)
aview[i].updateViewCache();
runMonitor( RUN_THREADS, stateWorkThreads, renderWorkThreads, requestRenderWorkThreads, null);
if(renderOnceList.size() > 0)
clearRenderOnceList();
}
The actual runMonitor
method is fairly complex, and it seems to perform the four functions shown in table 18.4, depending on the value of the first argument.
Identifier | Index | Purpose |
---|---|---|
CHECK_FOR_WORK | 0 | Evaluates each thread and set the MasterControlThread to wait if none of the threads needs to be processed. |
SET_WORK | 1 | Calls notify() on the MasterControlThread. |
RUN_THREADS | 2 | Iterates through all the J3dThreadData under the control of the MasterControl. The notify() method is called on each thread associated with each J3dThreadData object. |
SET_WORK_FOR_REQUEST_RENDERER | 5 | Sets the requestRenderWorkToDo member to true and calls notify on the MasterControl thread. |
The other arguments are (in order): the array of State Work Threads, the array of Render Work Threads, and the array of Request Render Work Threads. As you can see in the following pseudocode, Java 3D has the ability to call the doWork
method on each worker thread directly. This enables Java 3D to perform the work of multiple threads within a single thread.
For all Render Work Threads
If the Thread needs to be run (J3dThreadData member),
Check whether the View should be rendered based on its Minimum Frame
Cycle Time
Update the OrientatedShape3Ds in each View
If specified lock the geometry from updates,
If the CPU limit is 1, call the doWork method of the J3dThreadData’s
J3dThread directly
Otherwise call the runMonitor method (NOTIFY) to notify the thread
If specified release the lock on the geometry,
If specified, grab the current time and put it into the View’s RenderBin
Next Rendering Thread
If specified, wait for all Rendering threads to complete
For all State Work Threads
If the CPU limit is 1, call the doWork method of the J3dThreadData’s J3dThread directly
Otherwise call the runMonitor method (NOTIFY) to notify the thread
Next State Thread
If specified, wait for all State threads to complete
For all Request Render Work Threads
If the CPU limit is 1, call the doWork method of the J3dThreadData’s J3dThread directly
Otherwise call the runMonitor method (NOTIFY) to notify the thread
Next State Thread
If specified, wait for all State threads to complete
Update the View Frame Timing Values
Update all the Mirror Objects registered with the MasterControl
Wait for Request Rendering to complete
Update the frame timestamps for each rendered View
Java 3D communicates between its various worker threads using a message dispatch mechanism. Messages are instances of the J3dMessage
class. Each message contains an identifier and a target VirtualUniverse
as well as up to five parameters for the message (generic Objects
). Certainly not the most OO of designs—in fact it reminds me of the WPARAM and LPARAM attributes on the MESSAGE structure used to propagate messages under Windows.
The message identifiers are defined in table 18.5.
Message | Identifier |
---|---|
INSERT_NODES | 0 |
REMOVE_NODES | 1 |
RUN | 2 |
TRANSFORM_CHANGED | 3 |
UPDATE_VIEW | 4 |
STOP_THREAD | 5 |
COLORINGATTRIBUTES_CHANGED | 6 |
LINEATTRIBUTES_CHANGED | 7 |
POINTATTRIBUTES_CHANGED | 8 |
POLYGONATTRIBUTES_CHANGED | 9 |
RENDERINGATTRIBUTES_CHANGED | 10 |
TEXTUREATTRIBUTES_CHANGED | 11 |
TRANSPARENCYATTRIBUTES_CHANGED | 12 |
MATERIAL_CHANGED | 13 |
TEXCOORDGENERATION_CHANGED | 14 |
TEXTURE_CHANGED | 15 |
MORPH_CHANGED | 16 |
GEOMETRY_CHANGED | 17 |
APPEARANCE_CHANGED | 18 |
LIGHT_CHANGED | 19 |
BACKGROUND_CHANGED | 20 |
CLIP_CHANGED | 21 |
FOG_CHANGED | 22 |
BOUNDINGLEAF_CHANGED | 23 |
SHAPE3D_CHANGED | 24 |
TEXT3D_TRANSFORM_CHANGED | 25 |
TEXT3D_DATA_CHANGED | 26 |
SWITCH_CHANGED | 27 |
COND_MET | 28 |
BEHAVIOR_ENABLE | 29 |
BEHAVIOR_DISABLE | 30 |
INSERT_RENDERATOMS | 31 |
ORDERED_GROUP_INSERTED | 32 |
ORDERED_GROUP_REMOVED | 33 |
COLLISION_BOUND_CHANGED | 34 |
REGION_BOUND_CHANGED | 35 |
MODELCLIP_CHANGED | 36 |
BOUNDS_AUTO_COMPUTE_CHANGED | 37 |
SOUND_ATTRIB_CHANGED | 38 |
AURALATTRIBUTES_CHANGED | 39 |
SOUNDSCAPE_CHANGED | 40 |
ALTERNATEAPPEARANCE_CHANGED | 41 |
RENDER_OFFSCREEN | 42 |
RENDER_RETAINED | 43 |
RENDER_IMMEDIATE | 44 |
SOUND_STATE_CHANGED | 45 |
ORIENTEDSHAPE3D_CHANGED | 46 |
TEXTURE_UNIT_STATE_CHANGED | 47 |
UPDATE_VIEWPLATFORM | 48 |
BEHAVIOR_ACTIVATE | 49 |
The type member refers to one of the predefined message types from the table.
Each J3dMessage
maintains a reference count so that it can clear the references to its arguments when its reference count reaches zero. Messages with a reference count of zero are placed back into a list of free messages, for subsequent reuse. This message instance cache minimizes the number of message objects created by the Java 3D at runtime in an attempt to prevent excessive garbage collection. Interestingly this type of Object pooling is no longer favored as Sun’s HotSpot compiler performs object pooling and reuse automatically.
The MasterControl
method getMessage
will either return a message from the free list if one is available or allocate a new J3dMessage
instance, which will get added to the free list once its reference count reaches zero. The J3dMessage
also maintains a reference to a View
object and contains a thread identifier (bit-field) that identifies the threads that should receive the message, as shown in table 18.6.
Identifier | Java 3D Thread | Java 3D Thread Name |
---|---|---|
0x1 | BEHAVIOR_SCHEDULER | J3D-BehaviorScheduler-INSTANCE# |
0x2 | SOUND_SCHEDULER | J3D-SoundSchedulerUpdateThread-INSTANCE# |
0x4 | INPUT_DEVICE_SCHEDULER | J3D-InputDeviceScheduler-INSTANCE# |
0x10 | RENDER_THREAD | J3D-Renderer-INSTANCE# |
0x40 | UPDATE_GEOMETRY | J3D-GeometryStructureUpdateThread-INSTANCE# |
0x80 | UPDATE_RENDER | J3D-RenderStructureUpdateThread-INSTANCE# |
0x100 | UPDATE_BEHAVIOR | J3D-BehaviorStructureUpdateThread-INSTANCE# |
0x200 | UPDATE_SOUND | J3D-SoundStructureUpdateThread-INSTANCE# |
0x400 | UPDATE_RENDERING_ATTRIBUTES | J3D-RenderingAttributesStructureUpdateThread |
0x1000 | UPDATE_RENDERING_ENVIRONMENT | J3D-RenderingEnvironmentStructureUpdateThread-INSTANCE# |
0x2000 | UPDATE_TRANSFORM | J3D-TransformStructureUpdateThread-INSTANCE# |
The sendMessage
method updates appropriate message queue data structures based on the value of the thread identifier (table 18.7).
Thread Identifier | Effect |
---|---|
UPDATE_RENDERING_ATTRIBUTES | Appends the message to the global (across VirtualUniverses) RenderingAttributesStructure |
UPDATE_GEOMETRY | Appends the message to the VirtualUniverses’ GeometryStructure |
UPDATE_TRANSFORM | Appends the message to the VirtualUniverses’ TransformStructure |
UPDATE_BEHAVIOR | Appends the message to the VirtualUniverses’ BehaviorStructure |
UPDATE_SOUND | Appends the message to the VirtualUniverses’ SoundStructure |
UPDATE_RENDERING_ENVIRONMENT | Appends the message to the VirtualUniverses’ RenderingEnvironmentStructure |
SOUND_SCHEDULER | Appends the message to the View’s SoundScheduler (if a View is not specified, the message is added to the SoundScheduler for all registered Views) |
UPDATE_RENDER | Appends the message to the View’s RenderBin (if a View is not specified, the message is added to the RenderBin for all registered Views that are attached to the specified VirtualUniverse) |
Java 3D reads a number of system properties, some documented and some internal. A list of these properties is also maintained on the J3D.ORG site at http://www.j3d.org/implementation/properties.html.
Table 18.8 lists the system properties that are referenced in the Java code of the Java 3D distribution. Many more system properties are available which are specific to the OpenGL or DirectX versions of Java 3D. Please refer to the J3D.ORG website for the latest information on these properties.
Name | Default | Purpose |
---|---|---|
java.version | None | Check to see whether Java 3D is running under SDK 1.3 |
j3d.sharedctx | False | Use shared display contexts when rendering |
j3d.renderLock | True | Disable the render lock |
j3d.g2ddrawpixel | True | |
j3d.threadLimit | Processors + 1 | Number of concurrent threads that Java 3D can use. |
j3d.deviceSampleTime | 0 | Input device sampling time. |
j3d.debug | False | Switch on Java 3D debug output. Currently only used by the MasterController. |
Javax.media.j3d.compileStats | None | Output scenegraph compilation statistics |
Javax.media.j3d.compileVerbose | None | Output verbose message when compiling scenegraph |
The BehaviorScheduler
is responsible for activating all the Behaviors
registered with a VirtualUniverse
. For active and activated Behaviors
, the processStimulus
method is called on the Behavior
.
The BehaviorScheduler
integrates tightly with the BehaviorStructure
class, which maintains lists of all the Behaviors
that have been created for a VirtualUniverse
instance. The BehaviorStructure
also contains much of the logic to determine when a Behavior
has been activated, whether due to an AWT event, Behavior
ID being posted, Bounds
intersection, Sensor
condition, or a Transform3D
change.
The InputDeviceScheduler
maintains lists of nonblocking and blocking Java 3D InputDevices
. It calls pollAndProcessInput
on each nonblocking InputDevice
.
Name: J3D-Renderer-INSTANCE#
A Renderer
instance is created for each screen device that is to be rendered into. The Renderer
instances are kept in a static Hashtable
in the Screen3D
class. The Renderer
calls into the Canvas3D
instances (second JThreadData
argument) that are available for rendering. If a device supports swapping, there may be multiple Canvas3Ds
in the second argument.
Renderer
uses the first argument, which is one of the GraphicsContext3D
rendering commands (see table 18.9). The Renderer
extracts the messages from the RendererStructure
and calls methods on the GraphicsContext3D
as appropriate.
The complex Renderer
doWork
method implements the main Java 3D rendering loop. It sets up the projection matrices, handles stereoscopic rendering, and performs the main rendering loop; specifically, it:
preRender
on the Canvas3D
renderField
on the Canvas3D
postRender
on the Canvas3D
Table 18.9 lists the rendering commands that are used along with a RendererStructure
instance to determine which methods on the GraphicsContext3D
need to be invoked to execute a given command.
Command | Index |
---|---|
CLEAR | 0 |
DRAW | 1 |
SWAP | 2 |
READ_RASTER | 3 |
SET_APPEARANCE | 4 |
SET_BACKGROUND | 5 |
SET_FOG | 6 |
SET_LIGHT | 7 |
INSERT_LIGHT | 8 |
REMOVE_LIGHT | 9 |
ADD_LIGHT | 10 |
SET_HI_RES | 11 |
SET_MODEL_TRANSFORM | 12 |
MULTIPLY_MODEL_TRANSFORM | 13 |
SET_SOUND | 14 |
INSERT_SOUND | 15 |
REMOVE_SOUND | 16 |
ADD_SOUND | 17 |
SET_AURAL_ATTRIBUTES | 18 |
SET_BUFFER_OVERRIDE | 19 |
SET_FRONT_BUFFER_RENDERING | 20 |
SET_STEREO_MODE | 21 |
FLUSH | 22 |
FLUSH2D | 23 |
SET_MODELCLIP | 24 |
RenderAtoms
are self-contained rendering units that can be passed to the underlying rendering engine. The RenderAtom
contains lights, fog, model clipping information, an Appearance
, and a model transformation matrix. RenderAtoms
can be linked using double linked-list RenderAtom
members within the RenderAtom
class.
Higher level rendering operations are described using the RenderMolecule
class. In addition to maintaining a list of RenderAtoms
, RenderMolecules
are able to remove redundant changes in Appearance
between consecutive RenderAtoms
. In this way, the number of Appearance
state changes (Appearance
, Material
, Transparency
, etc.) performed by the underlying rendering engine is minimized.
The StructureUpdateThread
is a J3dThread
that can be attached to a J3dStructure
object to perform message processing. The StructureUpdateThread
instances are:
- J3D-GeometryStructureUpdateThread
- J3D-RenderStructureUpdateThread
- J3D-BehaviorStructureUpdateThread
- J3D-SoundStructureUpdateThread
- J3D-RenderingAttributesStructureUpdateThread
- J3D-RenderingEnvironmentStructureUpdateThread
- J3D-TransformStructureUpdateThread
- J3D-SoundSchedulerUpdateThread
The StructureUpdateThread
is attached to an instance of a J3dStructure
object, and its doWork
method calls the processMessages
method on the J3dStructure
. The various classes derived from J3dStructure
(such as SoundStructure
) implement structure specific message execution.
The J3D-TimerThread
manages:
WakeupOnElapsedTime
objects, stored in a WakeupOnElaspsedTimeHeap
(sorted, resizable array)
InputDeviceScheduler
(sampling time loaded from System
property)
SoundScheduler
(WakeupOnElapsedTime
every 2 minutes, by default)
The TimerThread
will call the setTriggered
method on each WakeupOnElapsedTime
as appropriate.
SceneGraphObject
is the base class for all the objects that can be added to a Java 3D scenegraph. It includes a number of interesting capabilities and defines some general architectural principals for Java 3D (such as capability bits and the retained delegate class pattern). The attributes of the SceneGraphObject
class are described in more detail next.
A BitSet
is an object that contains the capability bits that have been set on the SceneGraphObject
.
The retained field holds the private Java 3D implementation object for this SceneGraphObject
. The SceneGraphObjectRetained
maintains a reference to its source object and implements several setLive
methods that can be overridden to respond in a Node
specific manner. By having an internal delegate class separate from the public implementation class defined by the specification Sun has more leeway in modifying the implementation without breaking the API or exposing protected or package level access to methods or fields.
This field is true
if this node has been compiled.
This field is true
if this node has been attached to a live scenegraph.
private boolean liveOrCompiled
This field is true
if this node has been attached to a live scenegraph or has been compiled.
This field holds a reference to the User Data object for this scenegraph node.
Some ScenegraphObjects
have a Hashtable
of NodeComponents
associated with them.
Table 18.10 contains a list of Node
types and their identifiers.
Name | Identifier | Name | Identifier |
---|---|---|---|
BACKGROUND | 1 | LINK | 9 |
CLIP | 2 | MORPH | 10 |
LINEARFOG | 3 | SHAPE | 11 |
EXPONENTIALFOG | 4 | BACKGROUNDSOUND | 12 |
AMBIENTLIGHT | 5 | POINTSOUND | 13 |
DIRECTIONALLIGHT | 6 | CONESOUND | 14 |
POINTLIGHT | 7 | SOUNDSCAPE | 15 |
SPOTLIGHT | 8 | VIEWPLATFORM | 16 |
BEHAVIOR | 17 | GROUP | 23 |
SWITCH | 18 | TRANSFORMGROUP | 24 |
BRANCHGROUP | 19 | BOUNDINGLEAF | 25 |
ORDEREDGROUP | 20 | MODELCLIP | 26 |
DECALGROUP | 21 | ALTERNATEAPPEARANCE | 27 |
SHAREDGROUP | 22 | ORIENTEDSHAPE3D | 28 |
Read from ExceptionStrings.properties (inside J3DCORE.JAR).
Appearance0=Appearance: no capability to set material
Appearance1=Appearance: no capability to get material
Appearance2=Appearance: no capability to set texture
Appearance3=Appearance: no capability to get texture
Appearance4=Appearance: no capability to set textureAttributes
Appearance5=Appearance: no capability to get textureAttributes
And so forth…
The native methods within the Java 3D implementation are packaged within J3D.DLL (for Windows) and called using JNI from the Java code. The native code implements a procedural API for both OpenGL and DirectX rendering.
There are many programming tools that can list the signatures of the methods exported from a Windows DLL. The native method listings which follow are useful in that they not only expose where Java 3D calls down into native code but they also provide a blueprint for how an ambitious programmer might patch or hook a native DLL to implement an alternative rendering scheme or produce debugging output.
The following lists are sorted by ordinal (the numeric index of an exported method within a DLL) and arranged by Java 3D class. Prepend java_javax_media_j3d
to the names in the following lists. For example J3D.DLL exports a method called java_javax_media_j3d_Canvas3D_callDisplayList
which implements the method callDisplayList
which was declared as native within the Canvad3D
class.
_Canvas3D_accum@16 _Canvas3D_accumReturn@12 _Canvas3D_callDisplayList@20 _Canvas3D_clear@28 _Canvas3D_clearAccum@28 _Canvas3D_composite@40 _Canvas3D_createContext@28 _Canvas3D_createOffScreenBuffer@28 _Canvas3D_createQueryContext@24 _Canvas3D_ctxUpdateEyeLightingEnable@16 _Canvas3D_decal1stChildSetup@12 _Canvas3D_decalNthChildSetup@12 _Canvas3D_decalReset@16 _Canvas3D_destroyContext@20 _Canvas3D_destroyOffScreenBuffer@20 _Canvas3D_disableFog@12 _Canvas3D_disableModelClip@12 _Canvas3D_endDisplayList@12 _Canvas3D_freeDisplayList@16 _Canvas3D_freeTexture@16 _Canvas3D_getNumCtxLights@12 _Canvas3D_getTextureColorTableSize@12 _Canvas3D_getTextureUnitCount@12 _Canvas3D_newDisplayList@16 _Canvas3D_readOffScreenBuffer@24 _Canvas3D_resetColoringAttributes@32 _Canvas3D_resetLineAttributes@12 _Canvas3D_resetPointAttributes@12 _Canvas3D_resetPolygonAttributes@12 _Canvas3D_resetRenderingAttributes@20 _Canvas3D_resetTexCoordGeneration@12 _Canvas3D_resetTextureAttributes@12 _Canvas3D_resetTextureNative@16 _Canvas3D_resetTransparency@24 _Canvas3D_setBlendFunc@20 _Canvas3D_setDepthBufferWriteEnable@16 _Canvas3D_setDepthFunc@16 _Canvas3D_setFogEnableFlag@16 _Canvas3D_setLightEnables@24 _Canvas3D_setLightingEnable@16 _Canvas3D_setModelViewMatrix@20 _Canvas3D_setProjectionMatrix@16 _Canvas3D_setRenderMode@20 _Canvas3D_setSceneAmbient@24 _Canvas3D_setViewport@28 _Canvas3D_swapBuffers@20 _Canvas3D_syncRender@16 _Canvas3D_texturemapping@48 _Canvas3D_updateMaterial@28 _Canvas3D_useCtx@20 _Canvas3D_useSharedCtx@8
_ColoringAttributesRetained_updateNative@48
_CompressedGeometryRetained_decompressByRef@12 _CompressedGeometryRetained_decompressHW@20 _CompressedGeometryRetained_execute@40
_DirectionalLightRetained_updateLight@40
_ExponentialFogRetained_update@28
_GeometryArrayRetained_buildGA@64 _GeometryArrayRetained_defineByteColorPointer@44 _GeometryArrayRetained_defineDoubleVertexPointer@20 _GeometryArrayRetained_defineFloatColorPointer@44 _GeometryArrayRetained_defineFloatVertexPointer@20 _GeometryArrayRetained_defineNormalPointer@20 _GeometryArrayRetained_defineTexCoordPointer@28 _GeometryArrayRetained_disableGlobalAlpha@24 _GeometryArrayRetained_execute@76 _GeometryArrayRetained_executeInterLeaved@72 _GeometryArrayRetained_executeVA@32 _GeometryArrayRetained_globalAlphaSUN@8 _GeometryArrayRetained_setVertexFormat@20
_GraphicsContext3D_readRasterNative@48
_LineAttributesRetained_updateNative@32
_LinearFogRetained_update@40
_MasterControl_getMaximumLights@8 _MasterControl_getNumberOfProcessor@8 _MasterControl_getThreadConcurrency@8 _MasterControl_initializeJ3D@8 _MasterControl_setThreadConcurrency@12
_MaterialRetained_updateNative@84
_ModelClipRetained_update@52
_NativeConfigTemplate3D_choosePixelFormat@16 _NativeConfigTemplate3D_isDoubleBufferAvailable@24 _NativeConfigTemplate3D_isSceneAntialiasingAvailable@24 _NativeConfigTemplate3D_isStereoAvailable@24
_NativeWSInfo_subclass@12
_PointAttributesRetained_updateNative@20
_PointLightRetained_updateLight@52
_PolygonAttributesRetained_updateNative@32
_RasterRetained_execute@56
_Renderer_freeContext@16
_RenderingAttributesRetained_updateNative@48
_Screen3D_getDisplayParameters@24
_SpotLightRetained_updateLight@72
_TexCoordGenerationRetained_updateNative@76
_Texture3DRetained_bindTexture@20 _Texture3DRetained_updateTextureFields@52 _Texture3DRetained_updateTextureImage@44
_TextureAttributesRetained_updateNative@44 _TextureAttributesRetained_updateTextureColorTableNative@
_TextureRetained_bindTexture@20 _TextureRetained_updateTextureFields@48 _TextureRetained_updateTextureImage@40 _TextureRetained_updateTextureSubImage@44
_TextureUnitStateRetained_updateTextureUnitState@20
_Texture_freeTexture@16
_TransparencyAttributesRetained_updateNative@40
The J3D.DLL Windows library of course also imports methods from other Windows libraries. The list that follows describes the methods that the J3D.DLL library relies upon from other Windows libraries. This information is not particularly relevant except for the imports from OPENGL32.DLL (which is the standard OpenGL library on Windows). By looking at these imports you can see exactly which OpenGL functions the Sun Java 3D requires and uses.
GetLastError GetSystemInfo LCMapStringW RtlUnwind LCMapStringA CloseHandle SetFilePointer SetStdHandle LoadLibraryA SetEnvironmentVariableA GetACP CompareStringW GetOEMCP GetCPInfo CompareStringA GetStringTypeA MultiByteToWideChar GetStringTypeW InterlockedIncrement InterlockedDecrement FlushFileBuffers GetEnvironmentStringsW GetEnvironmentStrings WriteFile FreeEnvironmentStringsA GetModuleFileNameA FreeEnvironmentStringsW GetModuleHandleA GetProcAddress WideCharToMultiByte TlsGetValue SetLastError TlsAlloc TlsSetValue TlsFree HeapReAlloc GetCurrentThreadId VirtualFree HeapCreate VirtualAlloc HeapAlloc GetStartupInfoA HeapDestroy GetStdHandle SetHandleCount GetFileType DeleteCriticalSection InitializeCriticalSection GetCommandLineA HeapFree GetVersion EnterCriticalSection GetCurrentProcess LeaveCriticalSection TerminateProces FormatMessageA ExitProcess
GetSystemMetrics CallWindowProcA SetWindowLongA
ChoosePixelFormat SwapBuffers CreateDCA DeleteObject DescribePixelFormat CreateCompatibleDC SetPixelFormat CreateDIBSection SelectObject DeleteDC
glLogicOp glAlphaFunc glPolygonMode glLightModelfv glPolygonOffset glViewport glLineWidth glMultMatrixd glPointSize glTexGenfv glTexGeni glHint glCullFace glFogfv glPopAttrib glLoadIdentity glPushAttrib glMaterialfv glPolygonStipple glShadeModel glTexParameterfv glTexSubImage2D glStencilOp glStencilFunc glClearStencil glDepthFunc glLightf glLightfv glClipPlane glFogi GlColor4fv glFogf glNormal3fv glTexCoord3fv glColor3fv glTexCoord2fv glNormalPointer glVertex3fv glInterleavedArrays glEnableClientState glColorPointer glVertexPointer glDrawArrays glTexCoordPointer glDisableClientState glDeleteTextures glReadPixels wglGetProcAddress glEndList glDeleteLists glCallList GlFlush glNewList glFinish glDrawBuffer glAccum glClearAccum glBindTexture glClearColor glPixelStorei GlOrtho glTexParameterf glTexEnvf glTexCoord2f glTexImage2D glBegin glGetBooleanv glVertex2f glEnd glBlendFunc glIsEnabled glDisable glRasterPos3f glMatrixMode glLoadMatrixd glDepthMask glPixelZoom glDrawPixels wglShareLists glClear glGetIntegerv glReadBuffer glEnable glColorMaterial wglMakeCurrent wglDeleteContext wglCreateContext glTexEnvi glGetString glTexEnvfv glLightModeli glLineStipple
I hope this quick summary of Sun’s Java 3D implementation has given you an appreciation for how it works and has piqued your interest. Poking around, using fairly simple tools and a little guesswork you can learn a lot–either purely for education or to help performance tune or debug your Java 3D applications.
One of the criticisms of Java 3D has been the lack of information on the implementation of the API. Parts of the Java 3D Specification are vague and the semantics of how changes to the scenegraph are propagated across the runtime, synchronized, and rendered are largely undocumented. I hope this chapter will spur on others at Sun, or elsewhere, to further document some of these more advanced aspects of the implementation.
Since this is the last chapter, I say well done! I’m sure it’s been a hard slog, especially if you are new to Java 3D, but I hope it has been worth it. Don’t hesitate to contact me through the Manning Authors Online forum, or we may run into each other on Sun’s Java 3D email list. May all your capability bits be set correctly!