gama-platform / gama.old

Main repository for developing the 1.x versions of GAMA
GNU General Public License v3.0
304 stars 99 forks source link

Enhancement: provide a support for the absolute positioning of elements in a display #1326

Closed AlexisDrogoul closed 7 years ago

AlexisDrogoul commented 8 years ago

GAMA already provides 3 variables (accessible as units), specific for each display, which represent:

In order to position elements (like legends, buttons, etc.) in an absolute way, it would be great to have, at least:

So that layers, but also drawing operations, can specify an absolute positioning and sizing (e.g. draw "Hello" at: {° viewport_x + 100 °px, °viewport_y + 100 °px} size: 20°px;).

AlexisDrogoul commented 8 years ago

As it turns out, providing these "units" is more complicated than it seemed to be first. Objects to be drawn on the screen need to belong to the world and be included within its bounds and there is no way the current layers can be drawn "outside" the world. All positions (even absolute) are computed from the 0,0 top-left coordinates of the world in the view : when the world display is smaller than the view, which is always almost the case at the beginning, absolute coordinates can become negative, which is non-renderable (at least in the current Java2D display: it might be possible in OpenGL, though).

What I propose instead is to have a special kind of layer, called "legend", which would be displayed differently than the others as it would always be considered as having its coordinates computed from the top-left coordinates of the view (and not the display). "legend" is just a proposal, though. It can be called "absolute" or "overlay" (this one is already taken, so as to display information in the bottom overlay, but it can be extended to accept a complete layer information).

Nicolas Marilleau (@gnoubi), who was asking this feature, what is your feeling about this ?

ptaillandier commented 8 years ago

In addition, it could very nice to be able to access to the level of zoom in an aspect. It will allow to modify the way the agent is displayed according to this level.

AlexisDrogoul commented 8 years ago

Yes, giving access to the zoom level (as a float value, where 1.0 = 100%) is quite easy to do. However, I'm still waiting for Nicolas (@gnoubi)'s answer before committing anything.

gnoubi commented 8 years ago

It seems good !!!

but how the legend of agent species will be defined ? an aspect defines a display of an agent. In the case of a legend, an aspect is for agents of with a same characteristic. Maybe the statement « species coucou aspect:toto » should evolve ?

Nicolas Marilleau UMI 209 UMMISCO Institut de Recherche pour le Développement Chercheur invité DISC/ Femto-ST Université de Franche-Comté

32 rue Henri Varagnat 93143 Bondy Cedex tel : 01.48.02.79.01 mobile : 06.88.33.49.06

Le 13 déc. 2015 à 13:13, Alexis Drogoul notifications@github.com a écrit :

As it turns out, providing these "units" is more complicated than it seemed to be first. Objects to be drawn on the screen need to belong to the world and be included within its bounds and there is no way the current layers can be drawn "outside" the world. All positions (even absolute) are computed from the 0,0 top-left coordinates of the world in the view : when the world display is smaller than the view, which is always almost the case at the beginning, absolute coordinates can become negative, which is non-renderable (at least in the current Java2D display: it might be possible in OpenGL, though).

What I propose instead is to have a special kind of layer, called "legend", which would be displayed differently than the others as it would always be considered as having its coordinates computed from the top-left coordinates of the view (and not the display). "legend" is just a proposal, though. It can be called "absolute" or "overlay" (this one is already taken, so as to display information in the bottom overlay, but it can be extended to accept a complete layer information).

Nicolas Marilleau (@gnoubi https://github.com/gnoubi), who was asking this feature, what is your feeling about this ?

— Reply to this email directly or view it on GitHub https://github.com/gama-platform/gama/issues/1326#issuecomment-164252918.

AlexisDrogoul commented 8 years ago

No, I dont want to create a real legend. What can be put in such a layer is completely free. You can even redraw the whole world inside it. It's just a portion (or several portions) of the screen that will be unaffected by the displacement, zoom or (3D) rotations of the display. After that, you organize it as you want. I'm still not completely sure how to handle this, however, either with pure SWT/AWT controls or reusing the existing IGraphics. If you already want to create a legend (up to 3 elements), the overlay layer is what you're looking for.

AlexisDrogoul commented 8 years ago

The #zoom or (°zoom) unit has been added in the latest commit. Its value is a positive float, where 1.0 represents the "normal" zoom level (i.e. 100%).

See this little snippet here:

model pixel

experiment Exp type: gui
{
    output
    {
        display "Display"
        {
            graphics "example"
            {
                draw world.shape;
                draw "Zoom: " + int(°zoom * 100) + "%" color: # black font: font("Serif", 20, # bold);
            }

        }

    }

}
gnoubi commented 8 years ago

It seems good for me does the proposed method allow to display specific agent in the graphics ?

AlexisDrogoul commented 8 years ago

I have committed a first "complete" implementation for the new Java2D display (the one accessible using the experimental keyword instead of java2D). I have tried to make it work at the same time for OpenGL displays, but no luck and I will need some help — an implementation has been done in JOGLRenderer, ModelScene and LayerObject (with an orthographic projection), but nothing gets displayed and I dont understand why. @agrignard , can you help me on this ? The main part is in the draw() method of LayerObject.

The syntax for testing this overlay is quite simple, and equivalent to that of graphics. See this little snippet here (which builds an automatic legend):

model trial

global
{
    init
    {
        create species2 number: 20;
        create species3 number: 10;
        create species4 number: 20;
    }

}

species base
{
    rgb color;
    aspect default
    {
        draw shape color: color;
    }

}

species species3 parent: base
{
    rgb color <- #red;
    geometry shape <- triangle(4);
}

species species2 parent: base
{
    rgb color <- #blue;
    geometry shape <- square(5);
}

species species4 parent: base
{
    rgb color <- #green;
    geometry shape <- circle(2.5);
}

experiment OVERLAY type: gui
{
    output
    {
        display Grid type: opengl
        {
            overlay position: { 5, 5 } size: { 180 °px, 100 °px } background: # black transparency: 0.5 border: #black rounded: true
            {
                float y <- 30°px;
                loop spec over: base.subspecies
                {
                    base a <- one_of(spec);
                    draw a scaled_to {10°px,10°px} at: { 20°px, y } color: a.color border: #white;
                    draw spec.name + " (" + length(spec) + ")" at: { 40°px, y + 4°px } color: # white font: font("SansSerif", 18, #bold);
                    y <- y + 20°px;
                }

            }

            species species2;
            species species3;
            species species4;
        }

    }

}
capture 2016-02-26 a 09 16 15

The overlay correctly remains on top of everything and is not affected by the zoom or displacement of the other layers.

Many enhancements remain to be done, however:

But the most urgent thing is to make it work for OpenGL and I'm completely lost on this. Thanks in advance for any help !

agrignard commented 8 years ago

I remember that it was already an issue a long time ago and it has been remove as soon as the overlay option was available.

I will try to see what we can do in Opengl. As fa as I remember I think we have to create a texture and then display it with a fix size on top of the canvas but it was not so trivial.

Isn't there a way to do more or less the same of what has been done with the overlay option?

Just to be sure we agree that in the draw method there is "nothing" (except loadIdentity, pushmatrix, bla bla) now ?

AlexisDrogoul commented 8 years ago

No, it's not completely true: the draw method contains everything. If the layer is an overlay (in the block beginning by if (overlay)) then it pushes the GL world into an orthographic projection, and after that does the same thing as the other layers (drawing geometries, texts, etc.). The orthographic projection is then reversed at the end (again by a block beginning by if (overlay).

It should normally work (from what I've read on diverse sites on Internet), but nothing gets drawn at all...

agrignard commented 8 years ago

Well it seems to be the right solution indeed but nothing is drawn at all because NOTHING is drawn at all no?

if you add this for example just after glLoadIdentity:

float width=10;
float height = 10;
gl.glColor3f(0.0f, 0.0f, 0.0f);
gl.glBegin(GL2.GL_POLYGON); // draw using quads
  gl.glVertex3d(-width , height , 0.0d);
  gl.glVertex3d(width , height , 0.0d);
  gl.glVertex3d(width , -height , 0.0d);
  gl.glVertex3d(-width , -height , 0.0d);
gl.glEnd();

It draws a fix black rectangle.

So where are the data that we want to draw?

Should we use a structure like ISceneObjetcs like geometries, images , ressources and strings to have something like overlays.draw(gl, picking && isPickable()) ?

AlexisDrogoul commented 8 years ago

Well… Let's take a look at the method (I've removed the uninteresting part):

We dive into the 2D world if the layer is an overlay:


        if ( overlay ) {
            gl.glDisable(GL.GL_DEPTH_TEST);
            gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
            gl.glPushMatrix();
            gl.glLoadIdentity();
            gl.glOrtho(0.0, renderer.data.getEnvWidth(), renderer.data.getEnvHeight(), 0.0, -1.0,
                renderer.getMaxEnvDim());
            gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
            gl.glLoadIdentity();
        }

Then we draw what needs to be drawn in this layer (geometries, images, whatever):

        gl.glPushMatrix();
        gl.glTranslated(offset.x, -offset.y, offset.z);
        gl.glScaled(scale.x, scale.y, scale.z);
        gl.glEnable(GL.GL_TEXTURE_2D);
        images.draw(gl, picking && isPickable());
        gl.glDisable(GL.GL_TEXTURE_2D);
        resources.draw(gl, picking && isPickable());
        geometries.draw(gl, picking && isPickable());
        strings.draw(gl, picking && isPickable());
        gl.glPopMatrix();
        gl.glPushMatrix();
        dems.draw(gl, picking && isPickable());
        gl.glPopMatrix();

Then we go back to 3D world:

        if ( overlay ) {
            // Making sure we can render 3d again
            gl.glEnable(GL.GL_DEPTH_TEST);
            gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
            gl.glPopMatrix();
            gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
        }

And we leave to let another layer draw itself.

So we _do_ draw something (at least we should).

agrignard commented 8 years ago

Mmm yes indeed... strange... So it's like there was nothing (no images, no strings, no geometries...) in this layer whereas it works in JAVA2D so there should be something on the screen...

agrignard commented 8 years ago

When we remove the if(overlay){....} to draw this layer it in the normal way there is also nothing... So I have the feeling that something is missing in the filling of the IScenObjects. This layer looks empty at least for the opengl rendering...

AlexisDrogoul commented 8 years ago

Yes. Strange indeed. However, there is something (I can inspect the 3 geometries and 3 strings).

AlexisDrogoul commented 8 years ago

I've finally made some progress on this one but it's far from perfect as I'm still fighting with OpenGL projections... At least, we now display something in OpenGL. overlay - users drogoul documents git gama msi gama models models features overlay overlay gaml 2016-08-07 21-50-56

agrignard commented 7 years ago

It seems to be broken again with OpenGL.

Try for instance in Ant Foraging (Complex) . I also try on my own model where I'd like to display some overlay information.

No idea when it stops to work.

AlexisDrogoul commented 7 years ago

Actually, it has never worked (only briefly) in OpenGL. I give up on this one.

AlexisDrogoul commented 7 years ago

The new fixed OpenGL pipeline has revived some hope to close this issue. I will work on it and report here.

AlexisDrogoul commented 7 years ago

Good news. The OpenGL implementation is showing some progress, at last. A few things to iron, subtle bugs to fix, and we should be ready soon...

complete - users drogoul documents git gama msi gama models models toy models ants foraging and sorting models ant foraging 2017-07-22 00-41-32

AlexisDrogoul commented 7 years ago

Solved for OpenGL, at last. It is not completely satisfactory, because of the difference of architecture and logic between Java2D and OpenGL, which translate into differences in the two implementations, but at least, something is displayed more or less at the right place and with the right proportions in OpenGL. Feel free to open new issues regarding the glitches and possible bugs of this new implementation.