Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » GEF3D » Draw3d Program
Draw3d Program [message #2136] Tue, 24 March 2009 16:16 Go to next message
Madhu Samuel is currently offline Madhu Samuel
Messages: 199
Registered: July 2009
Senior Member
Hello Jens,


Can you please provide a simple draw3d program, say a program which
displays a cube in the 3d space. This would help to understand the concept
of how a draw3d program works?

In Draw2d we have layouts to keep the child IFigure objects. In Draw3d how
are the Figure3d objects placed?


Thanks,
Madhu


Re: Draw3d Program [message #2167 is a reply to message #2136] Tue, 24 March 2009 17:51 Go to previous messageGo to next message
Jens von Pilgrim is currently offline Jens von Pilgrim
Messages: 294
Registered: July 2009
Senior Member
Madhu,

On 2009-03-24 17:16:08 +0100, madhu.samuel@in.bosch.com (Madhu Samuel) said:
> Can you please provide a simple draw3d program, say a program which
> displays a cube in the 3d space. This would help to understand the
> concept of how a draw3d program works?
>
> In Draw2d we have layouts to keep the child IFigure objects. In Draw3d
> how are the Figure3d objects placed?

Draw3D works exactly the same way Draw2D does. As in Draw2D, figures
can be placed directly or using a layout (preferred, but not used in
the GEF3D examples yet).

How is a 3D figure placed? There is a method IFigure3D.getPosition3D().
You can call the setters of Position3D in order to place a figure in
3D. Actually, you can place a 3D figure using setBounds() (or setSize()
or setLocation(), but you can only set the x and y positions then, of
course (since you can use these 2D methods, it actually is possible to
use a 2D layout in order to arrange 3D figures).

It is recommended using a LayoutManager, and LayoutManagers are working
exactly as they do in Draw2D. Unfortunately, we haven't implemented any
LayoutManagers yet, since we are placing the figures directly (shame on
us ;-) ). There is an XYZLayoutManager, but is isn't implemented yet.
So you'll have to write a LayoutManager yourself.

OK, there is one layout manager ready: The SurfaceLayout. It is used in
GraphFigure3D (in the example). It is not a "complete" layout manager,
but it can be "added" to an existing layout manager. What it does is
pretty simple: It sets the z coordinate of a figure in order to place a
3D child on top of the surface of its parent. Why is that necessary? In
Draw3D, the x- and y-axis are oriented just as in 2D. The origin is on
the top-left, the x-axis is oriented from left to right and the y-axis
from top to bottom. Well, in 3D you can look around with a camera, but
forget about that for the moment. In most 3D systems, the coordinate
systems is oriented differently, that is the origin is at the
bottom-left corner of the screen, and the y-axis points upwards. In
order to make the coordinate system of the 3D system similar to the 2D
one, we flipped the system (that is we rotated it around the x-axis).
Are you familiar with coordinate systems and 3D? It's not that
complicated. Simply use your right hand (see
http://en.wikipedia.org/wiki/Right-handed_coordinate_system ). Now,
"rotate" your hand until your thumb looks to the right (the x-axis) and
your forefinger downwards (the y-axis) (Warning: I'm not liable for any
injuries ;-) ). This is the coordinate system of Draw3D (I hope you can
recognize my ASCII art):

+------> X
|\
| \
| \
v _|
Y Z

As you will notice, the middle finger (the z-axis) is looking backward
(at you). This is true for Draw3D, too. This has consequences for
placing figures in 3D: In order to place a figure with depth=50 on a
surface (for example the x-y-plane), it has to be placed at z=-50. The
SurfaceLayout does that for you. The surface layout certainly is only
useable for 3D children, since 2D children are always "placed" on the
surface of their 3D parent.

Of course, Draw3D is not limited to the SurfaceLayout, as the interface
Position3D suggests you can rotate and place 3D figures everywhere you
want. The MultiEditorModelContainerFigure places their children on top
of each other, again we are not using a layout here, and we have to fix
this. (Our examples are quick and dirty hacks for testing the
functionality. So we didn't used any layout since it is easier to
follow the effect of placing a figure without it...)

Cheers

Jens
Re: Draw3d Program [message #2197 is a reply to message #2167] Wed, 01 April 2009 02:44 Go to previous messageGo to next message
Madhu Samuel is currently offline Madhu Samuel
Messages: 199
Registered: July 2009
Senior Member
Hello Jens,


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 started to read the OpenGL red book @
http://fly.cc.fer.hr/~unreal/theredbook/


Hope this will help me to start with 3D. Is there any other good tutorials
which I need to refer?


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?


Regards,
Madhu


Jens v.P. wrote:

> Madhu,

> On 2009-03-24 17:16:08 +0100, madhu.samuel@in.bosch.com (Madhu Samuel) said:
>> Can you please provide a simple draw3d program, say a program which
>> displays a cube in the 3d space. This would help to understand the
>> concept of how a draw3d program works?
>>
>> In Draw2d we have layouts to keep the child IFigure objects. In Draw3d
>> how are the Figure3d objects placed?

> Draw3D works exactly the same way Draw2D does. As in Draw2D, figures
> can be placed directly or using a layout (preferred, but not used in
> the GEF3D examples yet).

> How is a 3D figure placed? There is a method IFigure3D.getPosition3D().
> You can call the setters of Position3D in order to place a figure in
> 3D. Actually, you can place a 3D figure using setBounds() (or setSize()
> or setLocation(), but you can only set the x and y positions then, of
> course (since you can use these 2D methods, it actually is possible to
> use a 2D layout in order to arrange 3D figures).

> It is recommended using a LayoutManager, and LayoutManagers are working
> exactly as they do in Draw2D. Unfortunately, we haven't implemented any
> LayoutManagers yet, since we are placing the figures directly (shame on
> us ;-) ). There is an XYZLayoutManager, but is isn't implemented yet.
> So you'll have to write a LayoutManager yourself.

> OK, there is one layout manager ready: The SurfaceLayout. It is used in
> GraphFigure3D (in the example). It is not a "complete" layout manager,
> but it can be "added" to an existing layout manager. What it does is
> pretty simple: It sets the z coordinate of a figure in order to place a
> 3D child on top of the surface of its parent. Why is that necessary? In
> Draw3D, the x- and y-axis are oriented just as in 2D. The origin is on
> the top-left, the x-axis is oriented from left to right and the y-axis
> from top to bottom. Well, in 3D you can look around with a camera, but
> forget about that for the moment. In most 3D systems, the coordinate
> systems is oriented differently, that is the origin is at the
> bottom-left corner of the screen, and the y-axis points upwards. In
> order to make the coordinate system of the 3D system similar to the 2D
> one, we flipped the system (that is we rotated it around the x-axis).
> Are you familiar with coordinate systems and 3D? It's not that
> complicated. Simply use your right hand (see
> http://en.wikipedia.org/wiki/Right-handed_coordinate_system ). Now,
> "rotate" your hand until your thumb looks to the right (the x-axis) and
> your forefinger downwards (the y-axis) (Warning: I'm not liable for any
> injuries ;-) ). This is the coordinate system of Draw3D (I hope you can
> recognize my ASCII art):

> +------> X
> |
> |
> |
> v _|
> Y Z

> As you will notice, the middle finger (the z-axis) is looking backward
> (at you). This is true for Draw3D, too. This has consequences for
> placing figures in 3D: In order to place a figure with depth=50 on a
> surface (for example the x-y-plane), it has to be placed at z=-50. The
> SurfaceLayout does that for you. The surface layout certainly is only
> useable for 3D children, since 2D children are always "placed" on the
> surface of their 3D parent.

> Of course, Draw3D is not limited to the SurfaceLayout, as the interface
> Position3D suggests you can rotate and place 3D figures everywhere you
> want. The MultiEditorModelContainerFigure places their children on top
> of each other, again we are not using a layout here, and we have to fix
> this. (Our examples are quick and dirty hacks for testing the
> functionality. So we didn't used any layout since it is easier to
> follow the effect of placing a figure without it...)

> Cheers

> Jens


Re: Draw3d Program [message #2228 is a reply to message #2197] Wed, 01 April 2009 10:37 Go to previous messageGo to next message
Jens von Pilgrim is currently offline Jens von Pilgrim
Messages: 294
Registered: July 2009
Senior Member
Madhu,

On 2009-04-01 04:44:28 +0200, madhu.samuel@in.bosch.com (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
Re: Draw3d Program [message #2256 is a reply to message #2228] Wed, 01 April 2009 14:33 Go to previous message
Madhu Samuel is currently offline Madhu Samuel
Messages: 199
Registered: July 2009
Senior Member
Thanks Jen for the very detailed explanation. This is helpful.

Re: Draw3d Program [message #561154 is a reply to message #2136] Tue, 24 March 2009 17:51 Go to previous message
Jens von Pilgrim is currently offline Jens von Pilgrim
Messages: 294
Registered: July 2009
Senior Member
Madhu,

On 2009-03-24 17:16:08 +0100, madhu.samuel@in.bosch.com (Madhu Samuel) said:
> Can you please provide a simple draw3d program, say a program which
> displays a cube in the 3d space. This would help to understand the
> concept of how a draw3d program works?
>
> In Draw2d we have layouts to keep the child IFigure objects. In Draw3d
> how are the Figure3d objects placed?

Draw3D works exactly the same way Draw2D does. As in Draw2D, figures
can be placed directly or using a layout (preferred, but not used in
the GEF3D examples yet).

How is a 3D figure placed? There is a method IFigure3D.getPosition3D().
You can call the setters of Position3D in order to place a figure in
3D. Actually, you can place a 3D figure using setBounds() (or setSize()
or setLocation(), but you can only set the x and y positions then, of
course (since you can use these 2D methods, it actually is possible to
use a 2D layout in order to arrange 3D figures).

It is recommended using a LayoutManager, and LayoutManagers are working
exactly as they do in Draw2D. Unfortunately, we haven't implemented any
LayoutManagers yet, since we are placing the figures directly (shame on
us ;-) ). There is an XYZLayoutManager, but is isn't implemented yet.
So you'll have to write a LayoutManager yourself.

OK, there is one layout manager ready: The SurfaceLayout. It is used in
GraphFigure3D (in the example). It is not a "complete" layout manager,
but it can be "added" to an existing layout manager. What it does is
pretty simple: It sets the z coordinate of a figure in order to place a
3D child on top of the surface of its parent. Why is that necessary? In
Draw3D, the x- and y-axis are oriented just as in 2D. The origin is on
the top-left, the x-axis is oriented from left to right and the y-axis
from top to bottom. Well, in 3D you can look around with a camera, but
forget about that for the moment. In most 3D systems, the coordinate
systems is oriented differently, that is the origin is at the
bottom-left corner of the screen, and the y-axis points upwards. In
order to make the coordinate system of the 3D system similar to the 2D
one, we flipped the system (that is we rotated it around the x-axis).
Are you familiar with coordinate systems and 3D? It's not that
complicated. Simply use your right hand (see
http://en.wikipedia.org/wiki/Right-handed_coordinate_system ). Now,
"rotate" your hand until your thumb looks to the right (the x-axis) and
your forefinger downwards (the y-axis) (Warning: I'm not liable for any
injuries ;-) ). This is the coordinate system of Draw3D (I hope you can
recognize my ASCII art):

+------> X
|\
| \
| \
v _|
Y Z

As you will notice, the middle finger (the z-axis) is looking backward
(at you). This is true for Draw3D, too. This has consequences for
placing figures in 3D: In order to place a figure with depth=50 on a
surface (for example the x-y-plane), it has to be placed at z=-50. The
SurfaceLayout does that for you. The surface layout certainly is only
useable for 3D children, since 2D children are always "placed" on the
surface of their 3D parent.

Of course, Draw3D is not limited to the SurfaceLayout, as the interface
Position3D suggests you can rotate and place 3D figures everywhere you
want. The MultiEditorModelContainerFigure places their children on top
of each other, again we are not using a layout here, and we have to fix
this. (Our examples are quick and dirty hacks for testing the
functionality. So we didn't used any layout since it is easier to
follow the effect of placing a figure without it...)

Cheers

Jens
Re: Draw3d Program [message #561168 is a reply to message #2167] Wed, 01 April 2009 02:44 Go to previous message
Madhu Samuel is currently offline Madhu Samuel
Messages: 199
Registered: July 2009
Senior Member
Hello Jens,


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 started to read the OpenGL red book @
http://fly.cc.fer.hr/~unreal/theredbook/


Hope this will help me to start with 3D. Is there any other good tutorials
which I need to refer?


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?


Regards,
Madhu


Jens v.P. wrote:

> Madhu,

> On 2009-03-24 17:16:08 +0100, madhu.samuel@in.bosch.com (Madhu Samuel) said:
>> Can you please provide a simple draw3d program, say a program which
>> displays a cube in the 3d space. This would help to understand the
>> concept of how a draw3d program works?
>>
>> In Draw2d we have layouts to keep the child IFigure objects. In Draw3d
>> how are the Figure3d objects placed?

> Draw3D works exactly the same way Draw2D does. As in Draw2D, figures
> can be placed directly or using a layout (preferred, but not used in
> the GEF3D examples yet).

> How is a 3D figure placed? There is a method IFigure3D.getPosition3D().
> You can call the setters of Position3D in order to place a figure in
> 3D. Actually, you can place a 3D figure using setBounds() (or setSize()
> or setLocation(), but you can only set the x and y positions then, of
> course (since you can use these 2D methods, it actually is possible to
> use a 2D layout in order to arrange 3D figures).

> It is recommended using a LayoutManager, and LayoutManagers are working
> exactly as they do in Draw2D. Unfortunately, we haven't implemented any
> LayoutManagers yet, since we are placing the figures directly (shame on
> us ;-) ). There is an XYZLayoutManager, but is isn't implemented yet.
> So you'll have to write a LayoutManager yourself.

> OK, there is one layout manager ready: The SurfaceLayout. It is used in
> GraphFigure3D (in the example). It is not a "complete" layout manager,
> but it can be "added" to an existing layout manager. What it does is
> pretty simple: It sets the z coordinate of a figure in order to place a
> 3D child on top of the surface of its parent. Why is that necessary? In
> Draw3D, the x- and y-axis are oriented just as in 2D. The origin is on
> the top-left, the x-axis is oriented from left to right and the y-axis
> from top to bottom. Well, in 3D you can look around with a camera, but
> forget about that for the moment. In most 3D systems, the coordinate
> systems is oriented differently, that is the origin is at the
> bottom-left corner of the screen, and the y-axis points upwards. In
> order to make the coordinate system of the 3D system similar to the 2D
> one, we flipped the system (that is we rotated it around the x-axis).
> Are you familiar with coordinate systems and 3D? It's not that
> complicated. Simply use your right hand (see
> http://en.wikipedia.org/wiki/Right-handed_coordinate_system ). Now,
> "rotate" your hand until your thumb looks to the right (the x-axis) and
> your forefinger downwards (the y-axis) (Warning: I'm not liable for any
> injuries ;-) ). This is the coordinate system of Draw3D (I hope you can
> recognize my ASCII art):

> +------> X
> |
> |
> |
> v _|
> Y Z

> As you will notice, the middle finger (the z-axis) is looking backward
> (at you). This is true for Draw3D, too. This has consequences for
> placing figures in 3D: In order to place a figure with depth=50 on a
> surface (for example the x-y-plane), it has to be placed at z=-50. The
> SurfaceLayout does that for you. The surface layout certainly is only
> useable for 3D children, since 2D children are always "placed" on the
> surface of their 3D parent.

> Of course, Draw3D is not limited to the SurfaceLayout, as the interface
> Position3D suggests you can rotate and place 3D figures everywhere you
> want. The MultiEditorModelContainerFigure places their children on top
> of each other, again we are not using a layout here, and we have to fix
> this. (Our examples are quick and dirty hacks for testing the
> functionality. So we didn't used any layout since it is easier to
> follow the effect of placing a figure without it...)

> Cheers

> Jens


Re: Draw3d Program [message #561185 is a reply to message #2197] Wed, 01 April 2009 10:37 Go to previous message
Jens von Pilgrim is currently offline Jens von Pilgrim
Messages: 294
Registered: July 2009
Senior Member
Madhu,

On 2009-04-01 04:44:28 +0200, madhu.samuel@in.bosch.com (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
Re: Draw3d Program [message #561197 is a reply to message #2228] Wed, 01 April 2009 14:33 Go to previous message
Madhu Samuel is currently offline Madhu Samuel
Messages: 199
Registered: July 2009
Senior Member
Thanks Jen for the very detailed explanation. This is helpful.

Previous Topic:Draw3d Program
Next Topic:Problem getting Draw3d to draw something
Goto Forum:
  


Current Time: Mon Sep 22 04:30:46 GMT 2014

Powered by FUDForum. Page generated in 0.05359 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software