[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