Everts
Everts

Reputation: 10721

OpenGl, drawing multiple triangle objects C#

So I have a Triangle class and I want to draw instance of my triangles but for some reasons, only one gets drawn and the logic behind it is beyond me.

I have been looking around but all I found is examples where all triangles are drawn on the same file.

This is the Triangle class:

 public class Triangle:IGameObject
 {
    Vector3 position;
    int speed;

    public Triangle(int speed, Vector3 vec) {
        this.speed = speed;
        position = new Vector3(vec);
    }
    public void Update() { }

    public void Render()
    {
        Gl.glPushMatrix();
        Gl.glRotated(speed*Time.deltaTime,speed*Time.deltaTime,speed*Time.deltaTime,speed*Time.deltaTime);

        Gl.glBegin(Gl.GL_TRIANGLE_STRIP);

            Gl.glColor3f(1.0f, 0.0f, 0.0f);
            Gl.glVertex3d(position.x, 0, 0);
            Gl.glColor3d(0.0, 1.0, 0.0);
            Gl.glVertex3d(position.y, 0, 0);
            Gl.glColor3d(0.0, 0.0, 1.0);
            Gl.glVertex3d(0, position.z, 0);

        Gl.glEnd();
        Gl.glPopMatrix();
    }
}

Here is the Form.cs

public partial class Form1 : Form
{
    Triangle _trA = new Triangle(100, new Vector3(0.1f,-0.2f,0.2f));
    Triangle _trB = new Triangle(50, new Vector3(0.5f, 0.3f, -0.1f));
    public Form1()
    {
        InitializeComponent();
        _openGLControl.InitializeContexts();

        if (_fullscreen)
        {
            FormBorderStyle = FormBorderStyle.None;
            WindowState = FormWindowState.Maximized;
        }
        else {
            ClientSize = new Size(1280,720);
        }
    }

    void GameLoop()
    {
        Gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
        _trA.Render();
        _trB.Render();
        _openGLControl.Refresh();
    }
}

I think I have seen that I should clear the matrix after (or before) using it for the object but cannot figure that out.

Any ideas?

Upvotes: 1

Views: 2167

Answers (1)

Boris Dalstein
Boris Dalstein

Reputation: 7788

There are different issues:

glPush/glPop

You should call

Gl.glPushMatrix();

at the beginning of your Render() method, and

Gl.glPopMatrix();

at the end.

Otherwise the glRotated() get accumulated across all your calls. Calling glPushMatrix() duplicate your current ModelView matrix, then you can apply the rotation, and glPopMatrix() restore the previous one.

glLoadIdentity

You have to reset the ModelView matrix at the beginning of the GameLoop, by calling:

Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();

This prevent any modification to accumulate from the previous frames.

Accumulates Time.deltaTime

I would guess that Time.deltaTime is the time, in seconds, that has past since your last frame. This is likely a constant, and then speed*Time.deltaTime is a constant too, so you always display the triangle rotated with the same angle, hence there is no movement. You should create a angle member, and increase it by calling angle += speed * Time.deltaTime at each GameLoop call.

glRotated

The three last arguments of glRotated indicate the axis of rotation around the one you are turning. Since you are using a 2D scene, I assume you want this axis to be the one the camera is looking at. Then you should use the axis (0,0,1) instead of (angle,angle,angle).

Conclusion

Taking into account all these elements, your code should be:

public class Triangle:IGameObject
{
    Vector3 position;
    int speed;
    double angle;

    public Triangle(int speed, Vector3 vec) {
        this.speed = speed;
        position = new Vector3(vec);
        angle = 0;
    }
    public void Update()
    { 
        angle += speed*Time.deltaTime;
    }

    public void Render()
    {
        Gl.glPushMatrix();
        Gl.glRotated(angle,0,0,1);

        Gl.glBegin(Gl.GL_TRIANGLE_STRIP);

            Gl.glColor3f(1.0f, 0.0f, 0.0f);
            Gl.glVertex3d(position.x, 0, 0);
            Gl.glColor3d(0.0, 1.0, 0.0);
            Gl.glVertex3d(position.y, 0, 0);
            Gl.glColor3d(0.0, 0.0, 1.0);
            Gl.glVertex3d(0, position.z, 0);

        Gl.glEnd();
        Gl.glPopMatrix();
    }
}

void GameLoop()
{
    // Update the scene
    _trA.Update();
    _trB.Update();

    // Draw the scene
    Gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
    Gl.glMatrixMode(Gl.GL_MODELVIEW);
    Gl.glLoadIdentity();
    _trA.Render();
    _trB.Render();
    _openGLControl.Refresh();
}

Upvotes: 3

Related Questions