Reputation: 10721
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
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