3D Modeling by means of JavaBeans
E.M.GrinkrugDepartment of Software Engineering
MoscowStateUniversity – Higher School of Economics
Moscow, Russia
e-mail:
Workshop on computer science and information technologies CSIT’2010, Moscow – Saint-Petersburg, Russia, 2010
1
Abstract[1]
The paper presents JavaBeans component model usage to implement 3D modeling and visualization in Java. An extensible subset of Virtual Reality Modeling Language is implemented as lightweight JavaBeans library that can be used in Java Applets and applications. The architectural approach used to build the library is described and illustrated.
Keywords: Virtual Reality Modeling Language, 3D applet, JavaBeans.
1. Introduction
This paper describes the use of the JavaBeans component model in 3D-modeling – specifically, we discuss how to support 3D-models creation, behavior and visualization by means of JavaBeans components.
According to [1], last years Java programming language is the leading programming language because of its popularity. Many 3D-modeling tools and products are implemented in Java. The Java programming community has developed Java3D library [2] that supports 3D-objects behavior and visualization, but the Java3D library suffers from some disadvantages, namely: it is significantly large, it is not fully documented (mainly, in multi-threading point of view), and does not fully correspond to the main multi-platform principle of the Java machine, performing rendering by OpenGL or DyrectX.
We present the implementation of 3D-modeling tools using standard JavaBeans-components and propose an approach to enhance the abilities for existing 3D-modeling languages by means of the components usage. As a starting point in our discussion, we use a subset of basic node types found in Virtual Reality Modeling Language (VRML) [3], that is the ISO-standard. The subset of object types, that is similar to those of VRML node types, is extended with new supplementary object types aimed at enhancing our abilities for 3D-modeling and visualization.
As a practical result of our work, we have developed the extensible JavaBeans-components library that can be used in any JavaBeans-components container, similar to BDK [4, 5] in its ability to create, run, customize, and visualize various 3D-models. The library can be used to create Java applets and applications, that use 3D-models visualization, without any need for additional plugins and installations.
We did not have a goal of implementing the support in its entirety for VRML and/or X3D (its successor language, based on XML-syntax) [6], according to their standards. The subset of their functional means, being extended with new components and implementation principles, is suitable for our discussion of JavaBeans-components usage for 3D-modeling and visualization, for estimation of the advantages and disadvantages of the approach we used, and for practical applications of the component library created.
2. 3D Modeling
As it was pointed out by one of the VRML creators [7], “Java and VRML are perfect complements. Java is all about how things behave but says very little about how they appear. VRML is all about appearances, without speaking to how things behave. You could say that VRML is, while Java does.They need each other”.
The usage of the most popular JavaBeans component model for 3D-modeling is not represented enough in existing literature and Java programming practice. Java3D library and X3D implementation Xj3D, based on that library [2, 8], do not pay enough attention to the component-oriented issues. Standard VRML implementations can support Java API of two kinds: External Authoring Interface (EAI) and Script Authoring Interface (SAI). EAI provides for external control over the 3D-models, that are incapsulated in a VRML Browser notion. SAI allows to have Java-implemented nodes in VRML scene graph, that are to be inherited from the abstract Script base class to participate in the scene behavior. Limited abilities for Java-programs to manipulate with 3D-models and their visualization in standard VRML browsers are rooted in non-Java implementations of the browsers. Existing Java-implementations of different VRML subsets are aimed to solve just a practical task of the 3D-models visualization in Java-applets (e.g. BS Contact J3D applet [9]), or use some proprietary component model (as in Demicron WireFusion [10]). Usually, only the whole visualized 3D-model can be made acccessible as a JavaBeans component. Last time JavaFX platform for Rich Internet Applications [11] was developed. JavaFX Script [12] – the declarative language for GUI description seems to be close ideologically with VRML, but is compiled into Java-bytecodes. So far, there are no attempts to have 3D-modeling and visualization abilities in JavaFX, apart from Java3D usage [13].
In VRML 3D-model is defined by directed acyclic graph (DAG) of Node-objects. Node-object is an instance of one of the predefined base types and/or an instance of user-defined type. There are two ways to define new node type in VRML: 1) – by use of script nodes providing their implementation codes (in Java or JavaScript language, according to VRML Standard), and 2) – by defining composed node types (prototypes in VRML terms), that are composed using previously defined node types. Each node instance contains a set of typed fields, where all field types are predefined in VRML Standard and can be classified as scalar or vector types. There are field types that allow to hold references to another node instances, and that is how graph of the model (scene graph in VRML terms) is defined. The graph must be traversable, i.e. must be a DAG. It should not necessary be a tree since it can contain nodes (or subgraphs) referrenced (shared) by two or more nodes. That feature allows for sharing the same data in different contects and for optimizing the size of declarative descriptions in transferred files. All node types are classified according to their goals and usage: there are geometry description nodes, visual features description nodes, sensor nodes, etc. Some nodes directly determine 3D-model visualization result, while others do that implicitly or are not used for visualization at all.
Fields in a node instance are defined by the node type. A field can contain a value of the predefined type and can be used for input only (eventIn in VRML terms), output only (eventOut, generating event when assigned) or for both of that access types. Apart from nodes graph, there can be event routes graph defined in a model. The event from output field of a node can be routed (in unicast or multicast manner) to input field(s), provided the types of output and input fields are compatible.
3. Implementing 3D-models using JavaBeans
Now we consider the description of 3D-model, its behavior and visualization by means of JavaBeans-components. We decribe the implementation principles and discuss their advantages and disadvantages.
In the implementation under discussion, each node type is implementaed as JavaBean-component to be instantiable in standard BeanBox container (e.g. the one from BDK1.1 [5]). Named field of the node corresponds to the JavaBean property having the same name and the proper value type. The properties have correspondent setters and/or getters and are described using JavaBean PropertyDescriptors (or IndexedPropertyDescriptors) that standard JavaBeans introspection provides. The event passing and propagation is supported by implementing eventOut(s) as boundproperties, generating PropertyChangeEvent(s). The Route notion of VRML is implemented as property change event adaptor.
Doing that way, we diverge from VRML rules slightly (providing Java API, that is different from EAI and SAI mentioned above), but we get some useful advantages: no problems with using graph nodes in Java programming and ability to use the whole JavaBeans-component related tools and frameworks (the BeanBox-like instruments). In particular, it allows for universal implementation of VRML-files parser, based on JavaBeans-components abilities. Moreover, we do not impose limitations on usable node types set and their field types (in contrast with VRML). BeanBox-like container is readily able to play a role of a visual tool for modeling, debugging and testing 3D-models with their visual presentations. Component-based approach helps to optimize results deployment by providing acually used components only (thus minimizing applet size).
A disadvantage of the approach comes from a static nature of JavaBeans component model, where all components must be Java classes (created using compilation or bytecodes generation and loadable by JVM class loader). There are ways to enhance the component model so that it becomes possible to define composed component types declaratively and in object-oriented manner, but detailed discusion of these issues are beyond the scope of the this paper, where we intentionally deal with standard JavaBeans component model only.
The object graph of the model consisting from instances of the correspondent component types, can be built programmatically, visually (by means of BeanBox-like container), or it can be read from its declrative description. Since we deal with serialization and deserialization of the object graph, all correspondent means, found in Java, can be used (base Java serialization and deserialization, XML encoding and decoding, etc.). We can use JavaBeans-related way to read VRML files, that makes it possible to import existing VRML-defined models or use ones exported from 3DSMax, the main 3D-designers tool, having VRML export features.
4. Parser for VRML subset
There are various ways to deserialize a model into JavaBeans-components instances graph from its declarative description (e.g. from VRML-file). The simpliest way is to implement correspondent method in each JavaBean component, but it requires predefined interafce implementation, that is a limitation by itself and increases the size of each component implementation. Starting from JDK 1.4, objects composed from JavaBeans components instances can be serialized/deserialized with XMLEncoder/XMLDecoder without having to implement special methods in the components themselves [14]. That mechanism (as a whole JavaBeans component model) is based on reflection features and expects that components provide getters (for serialization) and setters (for deserialization) for all the properties of the components. XMLDecoder expects that XML-file to be read contains encoded sequence of actions to be pereformed for having deserialized object in memory. XML-file in that case is much more verbose than VRML-encoded file, since the latter contains not the actions to do, but the resulting state of the graph.
To read the model graph, consisting of JavaBeans compolnent instances, from a VRML-file we use another universal way to implement VRML subset parser. The parser is managed by the sourse VRML text and by the structure of the JavaBeans components. Sourse text is read to get a node type name, find a correspondent JavaBean component and instantiate it. Then, the loop of reading name-value pairs in the node declaration scope is performed. Each name is treated as a propertyName, having a property value type from the correspondent JavaBean’s property descriptor. The value for the property name is read as the value of that type, and is used as the correspondent property setter’s parameter. That means – the value reading is controlled by the correspondent property value type; array values (for indexed properties) are read by the loop, that knows elements type for the indexed property.
Values of known property types are read:
- by getting primitive Java types values from strings;
- by reding values to be used as parameters to call a constructor that returns the value to be set for a property (and each value is read by recursive usage of the procedure);
- by recursive usage of the whole procedure written above, in case the property value has the type of JavaBean component representing a graph node.
The parser maintains a table of named graph nodes (to support DEF/USE VRML semantics similar to the idref construct of XML) used to implement sharing of the named component instances in multiple contexts, and creates ROUTE objects as property change events adaptors.
This parser organization is universal enough (it uses nothing except standard JavaBeans related meta-information), is compact, and serves for reading any DAG composable from extendable set of JavaBeans components instances.
5. Model and its behavior
The model graph is represented by the instance of container, that encapsulates JavaBean-components instances implementing, in particular, VRML nodes. We use two kinds of containers (that are JavaBeans components by themselves). SpaceContainer defines 3D-space with its coordinate system (and it is inherited from JavaBean Transform that corresponds to theTransform node of VRML). ActiveSpaceContainer adds a time related functionality to the SpaceContainer notion (it defines dynamics of the model behavior in its separate thread of control). For instance, the thread is used to support VRML TimeSensors used in the model to implement time based behavior (animation). It serves as notion of 3Dspace-time).
Usually VRML-browser implementations are based on sequential architecture, having a loop that consists of event-cascade execution (forced initially by some sensors in the model), updating state of the model graph and traversing the graph (may be mutiple times) to render it for 3D visualization. Each traversing pass builds stack that contains context-related information that is needed for calculations (e.g. for 3D-rendering).
When implementing a model by JavaBeans components, we use explicit context tree that is built for the model graph nodes. In a working model, each model graph node has its contexts that are organized into context trees. The context tree is rooted from the container instance and reflects all the model graph topology changes, being in correspondence with the graph. This approach helps to optimize time needed to build a stack with related context-dependent information while traversing the graph on each pass (by cost of some memory expenses that seems to be reasonable for Java implementation). Moreover, the context tree has its natural geometry interpretation: vertexes of triangles in 3D-surface are all contexts of points defining the surface (neighboring triangles share common points). Each context-tree node has a reference to the graph node (the one whose context it represents), a reference to its parent context and a set of references to its child contexts, if any.
In the current component library implementation, to build the context-tree for the given DAG, each component, that expects context-related feaatures, can be asked to create its context instance (for a given parent context). Each context-tree node (an object of type inherited from base NodeContext) binds the graph node context with its parent and child contexts. The reference used for binding can be “sensitive reference”: when it refer to an object that can change its state, the reference gets notification on that change (and thus takes part in property change events propagation, intiated from an event cascade used to support the model behavior in a model graph).
Concrete NodeContext implementations for a base components are defined by the components specifics. For example, Transform component (corresponding to the Transform VRML node) has correspondent TransformContext, and its instance in the context-tree contains coordinates transformation matrix relative to the root (world) coordinate system. Similar correspondent context types are provided by all components that expect their behavior and/or visualization dependent on context-dependent data (that otherwaise are to be collected while traversing the model graph). On other hand, context independent components can omit their participation in context-tree or just limit themselves with the base functionality of the NodeContext. The presence of the context-tree helps to control model graph acyclicity requirement when the model graph topology is changing dynamically (with correspondent corrections of the context-tree).
The model behavior is supported by event-driven calculations in the model graph nodes, implemented as JavaBeans-component instances, that accept and propagate property change events along established event routes. Initial stimulus for the event cascade propagation is an instance of some sensor component, generated the initial event. Event propagation is implemented by binding properties of component instances, and exit from the event cascade execution is controlled by standard property change events propagation rules for JavaBeans components (new event is generated only when the property value changes). All JavaBeans-components for a model graph nodes are implemented to be thread-safe; synchronized accessor methods are used for all their properties. ActiveSpaceContainer instance has its own thread, that can be started to represent separate time flow in the (3D) space of the container. An object of a model can be used not only in different contexts of a given container instance, but in different container instances as well (may be, having their own threads of control). Thread safe implementation ensures correct model behavior and visualization under all circumstances.
6. Model visualization
The root of the context-tree for a scene graph is the context of the root container (scene graph container). This context-tree represents the instance of the whole model with its behavior in the container instance in accordabce with event routing graph. Each context-tree can provide its view for further use, rendering and visualization. So, a kind of model-view-controller approach is applied for 3D-modeling and visualization.