0

I'm trying to draw the cursor position, with a square, when mouse moving.

I'm using SharpGL and the OpenGLControl, but there is a delay between cursor arrow and the drawn square.

On MouseMove event I store a square centered in the mouse position (mapped in _pointCursor that is a list of vertex), then in the Draw event of the control, I actually draw it:

private void DrawPointers(OpenGL gl)
{
    if (_pointCursor == null)
        return;
    SetColor(gl, Color.LightGray);
    gl.Begin(OpenGL.GL_LINE_LOOP);
    foreach (var item in _pointCursor)
    {
        gl.Vertex(item.X, item.Y, item.Z);
    }
    gl.End();

}

Is there any trick,configuration or strategy in order to avoid this delay?

I think the problem is how everything is drawn. If I remove DrawAxis() and DrawGrid() there is not more delay. In this case it can depend on my drawing strategy, I use a lot of gl.Begin() and gl.End().

Another thing is that DrawGrid() and DrawAxis() continues to draw a fixed background. I don't use shaders.

This is the code:

private void MouseDrawCursors(XglVertex v)
{
    if ((_view == ViewType._2D) && ((_status == EditStatus.Idle) || (_status == EditStatus.DrawLine)))
    {
        _pointCursor = v.DrawSquare(0.1f); //Return a list of vertex
        _pointCross = v.DrawCross(20); //Return a list of vertex
    }
}

private void openGLControl1_MouseMove(object sender, MouseEventArgs e)
{
    if (_gl == null)
        return;

    double worldX = 0;
    double worldY = 0;
    double worldZ = 0;
    _gl.GetWorldCoords(e.X, e.Y, ref worldX, ref worldY, ref worldZ);
    XglVertex v = new XglVertex((float)worldX, (float)worldY, (float)worldZ);

    MouseDrawCursors(v);
}

private void Draw()
{
    if (_gl == null)
        return;

    //Enable 3D
    if (_view == ViewType._2D)
        _gl.Disable(OpenGL.GL_DEPTH_TEST);
    else
        _gl.Enable(OpenGL.GL_DEPTH_TEST);
    _gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

    //Enable  Aplpha
    _gl.Enable(OpenGL.GL_BLEND);
    _gl.BlendFunc(OpenGL.GL_SRC_ALPHA, OpenGL.GL_ONE_MINUS_SRC_ALPHA);

    #region Projection

    _gl.MatrixMode(OpenGL.GL_MODELVIEW);
    _gl.LoadIdentity();

    _gl.Scale(Params.ScaleFactor, Params.ScaleFactor, Params.ScaleFactor);
    _gl.Translate(Params.X, Params.Y, Params.Z);

    if (_status == EditStatus.Rotate)
        _arc_ball_effect.ArcBall.TransformMatrix(_gl);
    else
        _gl.Rotate(Params.XAngle, Params.YAngle, Params.ZAngle);

    _gl.MatrixMode(OpenGL.GL_PROJECTION); //matrice di proiezione
    _gl.LoadIdentity(); //ripristina matrice identità

    float worldWidth = Params.Width;
    float worldHeight = Params.Height;
    float near = Params.Near;
    float far = Params.Far;

    _gl.Viewport(0, 0, openGLControl1.Width, openGLControl1.Height);

    if (_aspect_ratio >= 1.0)
        _gl.Ortho(0, (worldWidth * _aspect_ratio), 0, worldHeight, near, far);
    else
        _gl.Ortho(0, worldWidth, 0, (worldHeight / _aspect_ratio), near, far);

    #endregion

    if (Params.ShowPointers)
        DrawPointers(_gl);

    if (Params.ShowAxis)
        DrawAxis(_gl);

    if (Params.ShowGrid)
        DrawGrid(_gl);

    _gl.Flush();
}

private void DrawPointers(OpenGL gl)
{
    if (_pointCursor == null)
        return;

    if (_pointCursor.Count == 0)
        return;

    SetColor(gl, Color.LightGray);
    gl.Begin(OpenGL.GL_LINE_LOOP);
    foreach (var item in _pointCursor)
    {
        gl.Vertex(item.X, item.Y, item.Z);
    }
    gl.End();


    if (_pointCross == null)
        return;
    SetColor(gl, Color.LightGreen);
    gl.Begin(OpenGL.GL_LINES);
    foreach (var item in _pointCross)
    {
        gl.Vertex(item.X, item.Y, item.Z);
    }
    gl.End();

}


private void DrawGrid(OpenGL gl)
{
    if (_gl == null)
        return;

    if (_grid == null)
        return;

    if (!Params.ShowGrid)
        return;

    SetColor(gl, _grid.GridColor);

    if (_grid.EnableXY)
    {
        gl.Begin(OpenGL.GL_POINTS);
        foreach (var p in _grid.XY)
        {
            gl.Vertex(p.X, p.Y, p.Z);
        }
        gl.End();
    }

    if (_grid.EnableYZ)
    {
        gl.Begin(OpenGL.GL_POINTS);
        foreach (var p in _grid.YZ)
        {
            gl.Vertex(p.X, p.Y, p.Z);
        }
        gl.End();
    }

    if (_grid.EnableZX)
    {
        gl.Begin(OpenGL.GL_POINTS);
        foreach (var p in _grid.ZX)
        {
            gl.Vertex(p.X, p.Y, p.Z);
        }
        gl.End();
    }
}
Tostone
  • 95
  • 1
  • 9
  • I don't think that your delay come from this function. You should move this call inside your render loop, not in an event handler – Erwan Daniel May 26 '20 at 13:34
  • the render loop is managed by the cotrol event OpenGLDraw. The control is a SharpGL control called openGLControl. The procedure DrawPonters is located there. – Tostone May 26 '20 at 16:01
  • If you print the value in the mouse event handler do you get the same delay ? – Erwan Daniel May 26 '20 at 16:57
  • Yes if I display the mouse coords in world units it takes time. Maybe the issue is that I convert the screen coordinates pixel in world coordinates, I draw a square in world coordinates and it takes time. – Tostone May 27 '20 at 07:48
  • No, the conversion should be instantaneous. Could you post your update/render method ? As well as your mouse even handler ? – Erwan Daniel May 27 '20 at 11:12
  • gl.Vertex() may slow you down. Filling a vertex buffer and drawing it in one call will be faster. VSync is another source of input lag. You can try deactivating vsync in your app. – OutOfBound May 27 '20 at 15:16
  • OutOfBound. Consider that I have block of vertex that are drawn as triangles or quads or points . Could you please remaind me to an example? thks – Tostone May 29 '20 at 15:00

0 Answers0