Advertisement

2d Lighting

Started by June 21, 2004 01:31 PM
9 comments, last by abvenia 20 years, 5 months ago
My program uses 2d circles; but the lighting doesn't affect them. I know that I have to set up normals for them; I think between the glBegin() and glEnd(). Just can't seem to find a good example for calculating and setting the normals. Thanks!
If you have the normals setup properly along with the lights they should light just fine. Why don't you post some of your code? You may have set something wrong somewhere.
Advertisement
Quote: Original post by Monder
If you have the normals setup properly along with the lights they should light just fine. Why don't you post some of your code? You may have set something wrong somewhere.


I don't have the normals set up right; that's the problem. All I could find on the net is some examples with a triangle; using the cross product of its verticies. I'm not sure how to apply it to a circle, or what to do about the Z-Component since it is 2d.
for circle normal = normalize( circle_center - vertex );
You should never let your fears become the boundaries of your dreams.
Quote: Original post by _DarkWIng_
for circle normal = normalize( circle_center - vertex );


So just normalize the center co-ords minus a point on the parimeter?
Quote: Original post by abvenia
So just normalize the center co-ords minus a point on the parimeter?

Something like that. But you might go the other way around.

for each vertex {  normal.x = cos( angle );  normal.y = sin( angle );  normal.z = 0;  vertex = normal*radius + center;  do other stuff}
You should never let your fears become the boundaries of your dreams.
Advertisement
If your circle is only 2D (ie all points of the circle are coplanar) then I'd simply put a constant normal over the surface.
For instance :
void renderCircle(GLfloat radius, GLfloat xcenter, GLfloat ycenter, int slices){  glNormal3f(0,0,1.f);  glBegin(GL_TRIANGLE_FAN);  for (int i = 0 ; i <= slices ; ++i)  {    double angle = 2.*M_PI*i/(double)slices;    GLfloat x = xcenter + radius*cos(angle);    GLfloat y = ycenter + radius*sin(angle);    glVertex2f(x,y);  }  glEnd();}


Yes it will look flat, but ... it is flat since it's a 2D surface :)

DarkWing's solution gives probably more colorful results, but less realistic (physically speaking). Just pick the one you prefer !
I think I can adapt your (vincoof) function for what I'm doing. I have circles being drawn parrallel to each plane; so instead of rotating before the function call; I'll either store the plane in a global; or include it in the parameters. That way; I can both do the rotation in the call; and manually set (since its only 3 different ones) the normal.


[ADDED]

This is the modified function... It does not seem to be working. (BTW; I'm pretty new to this; so if there is a real obvious error; let me know ;) )

void drawCircle(float radius, int face)
//face specifies which plane it is parallel to. xy=1, xz=2, yz=3
//factor is a toggle between 1 and -1; just to make sure I didn't get it bass-ackwards
{
glBegin(GL_POLYGON);
switch(face){
case -1: glNormal3f(0.0,0.0,1.0*factor);break;
case -2: glNormal3f(0.0,1.0*factor,0.0);break;
case -3: glNormal3f(1.0*factor,0.0,0.0);break;
case 1: glNormal3f(0.0,0.0,-1.0*factor);break;
case 2: glNormal3f(0.0,-1.0*factor,0.0);break;
case 3: glNormal3f(-1.0*factor,0.0,0.0);break;
}
for (i=0; i < 360; i++)
{
float degInRad = i*DEG2RAD;
glVertex2f(cos(degInRad)*radius,sin(degInRad)*radius);
}

glEnd();
}

[Edited by - abvenia on June 22, 2004 8:06:50 AM]
First, I don't get what the 'factor' term is for.
Normals should always be normalized, so don't scale them. Or if you have to scale them, use glEnable(GL_NORMALIZE);

Secondly, you should always set your normal orthogonal to your plane. So if your circle is in the XY plane, normals should be pointing in the Z direction (be it positive or negative). If you call glRotate before calling drawCircle your normals will be rotated as well as your vertices.
I hope vincoof has answered your question but I have a couple of stylistic comments to make:

face is symbolic value. face = 1 means absolutely nothing to somebody just reading through your code. Use symbolic constants instead of numerical constants, i.e.:
const int FACE_NEGATIVE_Z = -1;const int FACE_POSITIVE_Z = 1;// etc.

and then you can switch based on the symbolic values:
switch (face){	case FACE_NEGATIVE_Z: whatever(); break;	case FACE_NEGATIVE_X: whatever(); break;	// etc.}

Secondly:
void drawCircle(float radius, int face){	// code	for (i=0; i < 360; i++)	{		// code	}	// code}

Where is i defined? Wait a minute. Surely you haven't created a global to use as your loop variable?!?! Oh dear, I think I'm going to... [sick] (sorry, just wanted to use that smiley [smile]). Global variables are evil*! There is absolutely no need to use a global for a loop variable, make it local instead:
void drawCircle(float radius, int face){	// code	for (int i=0; i < 360; i++)	{		// code	}	// code}


Finally, I hope that DEG2RAD is a const variable and not a #define, because we all know that #defines are evil*!

Enigma

* Yes, I know I'm overstating the case again, global variables and macros do have their uses.

This topic is closed to new replies.

Advertisement