[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Newsgroup Home]
|
[news.eclipse.gef3d] Re: Draw3d Program
|
Madhu,
On 2009-04-01 04:44:28 +0200, madhu.samuel@xxxxxxxxxxxx (Madhu Samuel) said:
Thanks for these information. But, its too much information for me to
understand the draw3d. Still I need to get the grasp of 3-dimensional
thoughts! :)
I focused on the layout manager problem. Besides that, drawing figures
in 3D is very similar to drawing figures in 2D. In Draw3D, we have
introduced an interface called Graphics3D. This interface is similar to
the Graphics interface of SWT used for drawing 2D content, its methods
are more ore less 1:1 copies of OpenGL commands. Unfortunately, this is
work in progress and this interface is likely to be changed in future
versions, but we will keep you informed then. The idea in Draw3D is as
follows:
Notation hint: I will use "paint" for 2D drawing and "render" for 3D
drawing, "drawing" is used for both cases.
First of all: 3D figures, that is implementations of the IFigure3D
interface (or usually the abstract base class Figure3D) are also 2D
figures, since they implement the IFigure interface as well (Figure3D
extends Figure!). As a consequence, 3D figures are drawn the same way
as 2D figures are drawn: Some command (such as repairDamage() or
repaint(..)) calls the IFigure#paint(Graphics) method. Currently, no
dirty regions are supported by Draw3D, repainting always repaints the
whole scene (I'm not sure if it will ever be possible to support dirty
regions in a 3D editor). But this is not that important. The important
thing is that 3D figures are handled by Draw3D (actually, it's more
Draw2D which does that) just as 2D figures are. As a matter of fact, 3D
figures may be children of 2D figures and vice versa; and indeed we use
2D layers which contain 3D figures. So, when Draw2D repaints the
figures, the IFigure#paint(Graphics) method of a figure is called, and
sooner or later, a IFigure calls the paint-method of its children. This
is only background information, since this is all handled by Draw2D/3D.
Now, in Draw3D, sooner or later a 2D figure calls the paint(Graphics)
method of a 3D figure. This is the paint-method of Figure3D:
public void paint(Graphics i_graphics) {
paintBorder(i_graphics); // --> does nothing at the moment (huh, we
have to add a bug report about that)
paintClientArea(i_graphics); // --> this is the 2D Figure method
paintFigure(i_graphics); // --> see below
}
The paintClientArea() is not overridden, it is the original Figure
method which (besides other things) calls the paint-method on the
children of a figure. But what happens next? It's clear that a 3D
figure cannot be drawn using the 2D-interface Graphics. The interesting
thing here is paintFigure():
protected void paintFigure(Graphics i_graphics) {
helper.paintFigure(i_graphics);
}
We have encapsulated that painting-to-rendering problem in a class
called Figure3DHelper, every Figure3D has a helper (we simply
decomposed the functionality).
That is, Figure3D calls Figure3DHelper#paintFigure(Graphics), here is
the code of this method:
public void paintFigure(Graphics i_graphics) {
Graphics3D g3d = RenderContext.getContext().getGraphics3D();
g3d.deactivateGraphics2D();
IFigure3D figure = m_figuresFriend.figure;
figure.render();
figure.postrender();
}
Remark: The helper's friend figure is the figure containing the helper,
we called it "friend" sine the helper accesses some non-public figure
methods (and we emulated the C++ friend construct).
The "trick" here is that Draw3D uses a Thread-local singleton called
RenderContext. This render context holds all information necessary for
the 3D rendering. Since we are reusing Draw3D's paint mechanism, the
parameters which could be passed on during the drawing process are
limited by the paint(Graphics) method to a single Graphics instance. In
order to have access to the 3D stuff, we are using this singleton. This
is a little bit tricky, but this enables 2D figures and 3D figures to
be "mixed".
Fortunately, this is not too important for you. The important thing is
that eventually IFigure3D#render() and IFigure3D#postrender() are
called. Huh... maybe we are going to remove the postrender() method
(and move all code in postrender() to render()....
OK, the important thing for you is the following: If you implement a
custom 3D figure, you have to extend Figure3D and override the render()
method. Within this method, you can get get access to the render
context via this statement:
RenderContext renderContext = RenderContext.getContext();
To retrieve the Graphics3D instance you will have to use:
Graphics3D g3d = RenderContext.getContext().getGraphics3D();
You can have a look at the existing figures in order to see how we use
these things. A good example will be CuboidFigureShape (which is used
by VertexFigure3D).
Before looking at the Graphcis3D interface, I want to highlight the
different modes (renderContext#getMode()). There are two modes: COLOR
and PAINT. COLOR is used for drawing the picking buffer. The picking
buffer is used for retrieving a figure under the mouse cursor based on
a unique color (this is a standard 3D technique). In order to create
the picking buffer, each figure (which is to be selectable or pickable)
has to be rendered in a unique color, and this is what this mode is
used for. So, in order to make your figure pickable, you have to
support that. The idea is that you maybe can simplify the rendering in
case of COLOR mode and only draw the outline of the figure in a unique
color (this color is retrieved using
RenderContext#getColor(IFigure3D)). Mode PAINT is for actually
rendering on the screen.
Now, there are two possibilities: You can either use Shapes to compose
your figure (as we are doing in most cases), or you can render the
figure yourself.
Remark: We have planned to provide more shapes in the future,
contributions are welcome!
If you render the figure yourself (or write your own shapes), you have
to use the Graphics3D interface and its methods (Graphics3DDraw
contains the OpenGL like methods, Graphics3DUtil the GLU things;
Graphics3D extends them both). The good thing about that is that it
provides nearly all OpenGL methods, so reading the red book is a good
idea! There are a lot of 3D tutorials on using OpenGL available in the
internet, and since we are using the same API, you can use these
tutorials.
I hope that this short introduction into Draw3D will help you. The
following list will give you some hints regarding pitfalls and future
design changes:
- Textures: If you are planing to use textures, have a look at
Figure3DHelper#paintChildren2D(Graphics). This is where we draw 2D
children of a 3D figure as a texture.
- render() vs. postrender(): In previous versions of GEF3D, the
render() method was called before the 2D content was painted, thus we
needed postrender() to set the texture with the 2D content. Since we
have changed that, we probably going to remove "postrender" and put
code found there to "render".
- Transparency: Transparency is not really supported by OpenGL, for
transparency effects, you have to sort the elements by yourself.
Fortunately Draw3D already does this. If you have a transparent figure,
have a look at the interface TransparentObject, this is used for
example in GraphFigure3D.
- Position3D: OpenGL uses only matrices for positioning elements. We
are using Position3D. If you would have used a matrix in OpenGL, you
probably have to use Position3D here. Internaly, Position3D can be
converted into a matrix (or buffer or what ever) used by the renderer.
You have to keep that in mind when reading OpenGL tutorials.
- Graphics3D interface: In previous versions of Draw3D, we directly
used LWJGL for rendering. We have refactored that and introduced the
Graphics3D interface in order to support different rendering libraries
(see
http://jevopisdeveloperblog.blogspot.com/2009/03/gef3d-goes-x3d.html ).
The refactoring is not finished yet, I'm afraid. For example, we are
thinking of introducing more high-level primitives or special shapes.
This is "future" work. But I assume that we are not going to remove
methods from Graphics3D, so your code will be compatible with newer
versions. But I cannot guarantee that. There are maybe some OpenGL
methods not available in Graphics3D. In that case simply post a message
here, and we'll likely add the method then---we have currently only
added the methods which are actually used by our test applications.
Hope this will help me to start with 3D. Is there any other good
tutorials which I need to refer?
I'm planing to write a tutorial in May. ;-) So long you will have to
ask questions here.
BTW, when the gef3d examples are executed, the background (or space)
has 4 partitions. What is the significance for this? Can I have 3-d
models without this background?
Huh, I assume you are referring to the coordinate axes? You can disable
them in the preferences.
Cheers
Jens