Jump to content
  • Advertisement
Sign in to follow this  
mathematical

OpenGL OpenGL - Render Plane equation

This topic is 960 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, i'm trying to figure out how to render a plane. My internal plane representation consists of a normal, and distance from origin

Vector3 Normal;
float Distance;

Given this, i've tried the following to render the plane:

GL.PushMatrix();

GL.Translate(Normal.X * Distance, Normal.Y * Distance, Normal.Z * Distance);
GL.Rotate(Normal.Y * 360f, 0f, 1f, 0f);
GL.Rotate(Normal.X * 360f, 1f, 0f, 0f);
GL.Rotate(Normal.Z * 360f, 0f, 0f, 1f);

GL.Begin(PrimitiveType.Quads);
    GL.Vertex3(-1, 1, 0);
    GL.Vertex3(-1, -1, 0);
    GL.Vertex3(1, -1, 0);
    GL.Vertex3(1, 1, 0);
GL.End();

GL.PopMatrix();

While this seems to work, i have doubts that it will with all angles... (Reason being the rotation order).

 

So, my question, is there a better way to derive a plane to be rendered?

 

I'm using C# and OpenTK to render this.

Please don't comment that i should be using more modern OpenGL, that is not constructive to the question i'm asking.

Share this post


Link to post
Share on other sites
Advertisement

Your doubts are valid, but the reason is wrong. The vertices are placed onto the local x/y plane, hence the normal is along the direction of the local z axis. Putting (0,0,1) into your rotation code and considering that rotation by 360° is identical to rotation by 0°, you correctly see the front of your plane. However, just using normals along x (1,0,0) or y (0,1,0) or so with your rotation code still give you the same vertices, since all transformations are the same. Changing the order of rotation does not make any difference then.

 

Actually, using a normal and a distance lets several degrees of freedom in an open state. Rendering a plane with vertices need those degree of freedom to be fixed. What I mean is that you need a definition of

a) an origin of the plane, so that there is a point with local co-ordinates (0,0,0), 

b) an orientation angle around the normal (think of the rolling angle of a camera; the normal gives you just 2 of the 3 angles).

 

You solved a) by using the point

   origin := (0,0,0) + distance * normal

 

You solve b) by just picking an angle, i.e. so that rolling is zero.

 

So with these fixes you have a position and an orientation as a direction and "no rolling". Let's express "no rolling" as

   up_vector := (0,1,0)
And instead of a pure direction, let's use it as difference vector from the origin to a tip point

   center_point := origin + normal * 1

 

Now (with the origin and the center point and the up vector), what we have here are the ingredients for the gluLookAt function! Although being described as a function to compute a view matrix, the function actually just builds a transformation matrix with a translation and rotations so that the z axis points in a specific direction.

 

The math behind the gluLookAt function isn't complicated and leaving OpenGL's matrix stack behind is ever a Good Thing TM, but I assume you may be happy with the sketched solution. Otherwise feel free to ask :)

Edited by haegarr

Share this post


Link to post
Share on other sites

I think this is what you are describing:

Vector3 forward = new Vector3(Normal.X, Normal.Y, Normal.Z);
Vector3 up = new Vector3(0f, 1f, 0f);
Vector3 right = Vector3.Cross(forward, up);
up = Vector3.Cross(right, forward);

Matrix4 rot = new Matrix4(right.X, up.X, -forward.X, 0.0f,
    right.Y, up.Y, -forward.Y, 0.0f,
    right.Z, up.Z, -forward.Z, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f);
Matrix4 trans = Matrix4.Translate(Normal * Distance);

Matrix4 result = rot * trans;

GL.PushMatrix();
GL.LoadMatrix(result.OpenGL);

GL.Begin(PrimitiveType.Quads);
GL.Vertex3(-1, 1, 0);
GL.Vertex3(-1, -1, 0);
GL.Vertex3(1, -1, 0);
GL.Vertex3(1, 1, 0);
GL.End();

GL.Begin(PrimitiveType.Points);
GL.Color3(1f, 1f, 0f);
GL.Vertex3(0f, 0f, 0f);
GL.Color3(1f, 0f, 1f);
GL.Vertex3(Normal.X * Distance, Normal.Y * Distance, Normal.Z * Distance);
GL.End();

GL.PopMatrix();

This however does not seem to work either. I can't even get the reference points rendering once i load the matrix generated above :(

 

Am i missing a step in this?

Share this post


Link to post
Share on other sites

I don't know how your framework linearizes matrices, so this code snippet
   Matrix4 rot = new Matrix4(...) 

may or may not be correct.

 

But there is a noticeable difference in transformation computation between your 1st and your 2nd post. In the 1st post you compute

    Mi+1 := Mi * T * R

with M being the transformation matrix on the stack, T being the translation and R the rotation. The snippet in your 2nd post computes

    Mi+1 := I * R * T

instead, where I is the identity matrix. Notice that (a) the matrix being formerly on the top of the stack is now ignored, and that (b) the order of translation and rotation is exchanged.

 

Hence try to change this line

   Matrix4 result = rot * trans;

into 

   Matrix4 result = trans * rot;

 
Further, if the former stack matrix should play a role, instead of 
   GL.LoadMatrix(result.OpenGL);
use
   GL.MultMatrix(result.OpenGL);

Share this post


Link to post
Share on other sites

Wow, GREAT CATCH! Rookie mistake on my part! You where correct in both cases, first i multiplied the matrix instead of loading; and the multiplication order did need to be reversed also. The matrix constructor was correct. Thank you so much for the help, it works flawlesly now!

 

For anyone who might be interested, my final code ended up being:

// Debug Normal
GL.Color3(1f, 1f, 0f);
GL.Begin(PrimitiveType.Lines);
GL.Vertex3(0f, 0f, 0f);
GL.Vertex3(Normal.X * 500, Normal.Y * 500, Normal.Y * 500);
GL.End();

GL.Color3(1f, 1f, 1f);
Vector3 forward = new Vector3(Normal.X, Normal.Y, Normal.Z);
Vector3 up = new Vector3(0f, 1f, 0f);
Vector3 right = Vector3.Cross(forward, up);
up = Vector3.Cross(right, forward);

Matrix4 rot = new Matrix4(right.X, up.X, -forward.X, 0.0f,
    right.Y, up.Y, -forward.Y, 0.0f,
    right.Z, up.Z, -forward.Z, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f);
Matrix4 trans = Matrix4.Translate(Normal * Distance);

Matrix4 result = trans * rot;

GL.PushMatrix();
GL.MultMatrix(result.OpenGL);

// Draw Plane
GL.Begin(PrimitiveType.Quads);
GL.Vertex3(-1, -1, 0);
GL.Vertex3(-1, 1, 0);
GL.Vertex3(1, 1, 0);
GL.Vertex3(1, -1, 0);
GL.End();

// Debug Points
GL.Begin(PrimitiveType.Points);
GL.Color3(1f, 1f, 0f);
GL.Vertex3(0f, 0f, 0f);
GL.Color3(1f, 0f, 1f);
GL.Vertex3(Normal.X * Distance, Normal.Y * Distance, Normal.Z * Distance);
GL.End();

GL.PopMatrix();

Tough my math lib is a bit wonky, you might need to adjust.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!