I get triangle vertex data and Normal vector data from a stl file, but when I render it with code like this
for(uint32_t i = 0 ;i < mVertexCnt - 9;){
int z = i/9;
glBegin(GL_TRIANGLES);
glNormal3f(mNorm[3*z], mNorm[3*z+1], mNorm[3*z+2]);
glVertex3f(mVertix[i]/100,mVertix[i+1]/100,mVertix[i+2]/100); //1
glVertex3f(mVertix[i+3]/100,mVertix[i+4]/100,mVertix[i+5]/100); //1
glVertex3f(mVertix[i+6]/100,mVertix[i+7]/100,mVertix[i+8]/100); //1
i += 9;
glEnd();
}
the result is like
I think it is because the because normal vector direction is opposite to light direction.
my question is does OpenGL can handle itself. Ignore this direction issue and show the right light in every direction.
anyone know about it?
The light setting is like this:
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glMaterialfv(GL_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_BACK, GL_SHININESS, mat_shininess);
//灯光设置
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); //散射光属性
glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); //镜面反射光
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Light_Model_Ambient); //环境光参数
glEnable(GL_LIGHTING); //开关:使用光
glEnable(GL_LIGHT0); //打开0#灯
When the light model should be applied to both sides of a polygon, then you have to enable GL_LIGHT_MODEL_TWO_SIDE (see glLightModel) By default GL_LIGHT_MODEL_TWO_SIDE is 0.
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
But note this does not cause that the best fitting direction normal vector is found magically. It just causes that the normal vector of back facing polygons is inverted. Whether a polygon (triangle) is back face, is determined by the Winding order of the vertices in the projection on the viewport. Whether clockwise or counterclockwise polygons are meant to be front facing, can be set by glFrontFace.
Related
I'm trying to change the field of view in my scene when touching F2 and F3.
For this I have in my specialKey function this:
void specialKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_F2:
changeFOV = true;
fovScale = 0.05;
break;
case GLUT_KEY_F3:
changeFOV = true;
fovScale = -0.05;
break;
}
I have a timed function that call myDisplay each milisecond and in that function I do:
if(changeFOV){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
fovAngle += fovScale;
gluPerspective(fovAngle, screenWidth/screenHeight, 2, 200);
glTranslatef(camera.x, camera.y, camera.z);
glMatrixMode(GL_MODELVIEW);
changeFOV = false;
}
Now the first time I press F2 or F3, the scene gets small to the size of one pixel (aprox) but if I keep pressing F3 the scene gets closer and closer and then it works correctly (F2 and F3).
fovAngle is 60.0f at the beginning (The scene looks good without pressing F2 or F3).
This is my init() function:
void init() {
glInitNames();
gluPerspective(fovAngle, screenWidth/screenHeight, 2, 200);
glTranslatef(camera.x, camera.y, camera.z);
glClearColor(0, 0, 0, 1);
glViewport(0.0, 0.0, screenWidth, screenHeight);
glutInitWindowSize(screenWidth, screenHeight);
string windowName = "AMAZING 3D MODELING - ";
windowName += (sceneMode ? "Scene" : "Camera");
glutCreateWindow(windowName.c_str());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glMaterialfv(GL_FRONT, GL_AMBIENT, object_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, object_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, object_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, object_shine);
glutDisplayFunc(displayFunc);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutSpecialFunc(specialKey);
glutKeyboardFunc(keyboard);
glutTimerFunc(2, idle, 1);
glutMainLoop();
}
Any thoughts?
(if more code is needed please ask and I will edit the question)
The main problem is that you're calling GL functions before you have an OpenGL context. The context is created as part of glutCreateWindow(), so all your OpenGL calls, like your whole initial projection setup, need to be moved after glutCreateWindow().
You also seem to be missing a call to glutInit(), which should be at the very start. I'm surprised that your code works at all without it.
The camera translation should normally be in modelview matrix mode. It won't change the resulting position of your geometry, but the lighting will be wrong otherwise.
The reason this behaves the way it does is most likely that your camera is very far away. Since the projection/camera is not set up on the initial rendering, it is not applied, and the geometry appears. Then the first time the projection/camera are applied, everything gets very small because you're looking at it from very far away. Then, as you make the FOV smaller, the size of the geometry increases.
So what you need to do is:
Add call to glutInit() at the start.
Move all initialization calls after glutCreateWindow().
Set camera translation in modelview mode.
Move camera closer.
I would put the transformation setup in a function that you can call both at init time, and when it changes. The function would contain something like this:
void setTransformations() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fovAngle, screenWidth/screenHeight, 2, 200);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(camera.x, camera.y, camera.z);
}
Then you call it during init:
glutCreateWindow(...);
setTransformations();
and when the FOV changes:
if (changeFOV) {
fovAngle += fovScale;
changeFOV = false;
setTransformations();
}
I want to add a Light source to my OpenGl code.
I have added following code to my init function...
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightf(GL_LIGHT0, GL_POSITION,(50.0,0.0,0.0,1.0));
Moreover I have drawn a quad:
glBegin(GL_QUADS);
glNormal3f(0.0,0.0,1.0);
glVertex3f(0.0,0.0,20.0);
glVertex3f(0.0,10.0,20.0);
glVertex3f(10.0,10.0,20.0);
glVertex3f(10.0,0.0,20.0);
glEnd();
But no matter what value I use for the Position,
the lighting doesn't change at all...
glLightf(GL_LIGHT0, GL_POSITION,(50.0,0.0,0.0,1.0));
^^^^^^^^^^^^^^^^^^
(50.0,0.0,0.0,1.0) in this context will evaluate to the last expression in the list (1.0). Probably not what you want.
You need to use a real array and glLightfv() to specify light positions:
GLfloat pos[] = { 50.0, 0.0, 0.0, 1.0 };
glLightfv( GL_LIGHT0, GL_POSITION, pos );
anyone can teach me how to draw 2 objects, for example a cube and a sphere, in origin (0, 0, 0) and when i move the cube, the sphere just remains in the origin. same with moving the sphere, the cube remains..
using keyboardfunc.
if (!LightSwitch)
{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glPushMatrix();
glTranslatef(CubeX, CubeY, CubeZ);
glColor3f(1.0, 0.0, 0.0);
glPushAttrib(GL_LIGHTING_BIT | GL_CURRENT_BIT);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Green);
glutSolidCube(2.0);
glPopAttrib();
glPopMatrix();
glEnd();
}
if (!LightSwitch1)
{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1);
glPushMatrix();
glTranslatef(AxisX, AxisY, AxisZ);
glColor3f(1.0, 0.0, 0.0);
glPushAttrib(GL_LIGHTING_BIT | GL_CURRENT_BIT);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Blue);
glutSolidSphere(2.0, 10.0, 5.0);
glPopAttrib();
glPopMatrix();
}
glEnd();
I'm no expert, but I believe that by having separate glPushMatrix() / glPopMatrix() blocks for the sphere and the cube, you are giving each object its own local coordinate system. This is why they transform independent of each other.
If you want to move them together, you need to specify glTranslate() outside your glPushMatrix() / glPopMatrix() first:
glTranslatef(translation....); // Translates the whole scene
glPushMatrix();
glTranslatef(the sphere); // Sphere & cube locations changeable via keyb.
glTranslatef(the cube);
glPopMatrix();
If you want to, say, rotate the cube with respect to the sphere (ie., make the center of the sphere the origin of the cube's coordinate system), make a new glPushMatrix()/glPopMatrix() block nested within the first block:
glPushMatrix();
glTranslatef(the sphere);
glPushMatrix();
glRotatef(the cube); // Rotate about specific axis of the sphere
glPopMatrix();
glPopMatrix();
I believe your code is correct for drawing the sphere at location Axis and the cube at location Cube. You say you are using a keyboard func and it is moving them both together when you want to move just one. I believe you are updating both sets of variables in your keyboard function. Try printing out CubeXYZ and AxisXYZ and make sure you're getting the right thing.
I need to draw an object with triangles and a sphere. My object has its own material properties that I define them with glMaterialfv. Sphere is just a sphere with a color. However, some part of my object(it is one of its polygons) is colored with sphere's color. How can I solve this problem?
my object function
void drawObject()
{glDisable(GL_COLOR_MATERIAL);
for(int i=0;i<j;i++)
{ glBegin(GL_TRIANGLES);
glNormal3f(..);
glVertex3f(..);
glNormal3f(..);
glVertex3f(..);
glNormal3f(..);
glVertex3f(..);
GLfloat ambientValues[]={..};
GLfloat specularValues[]={..};
GLfloat diffuseValuse[]={..};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,ambientValues);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,diffuseValues);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specularValues);
glEnd();
}
}
Two mistakes here: Materials muse be set before the drawing operation. And glMaterialfv is not valid within a glBegin/glEnd block. BTW, you shouldn't use immediate mode (glBegin/glEnd) in the first place. Its use has been discouraged for well over 15 years now.
I have loaded an object, and when I draw the object, I set the color to green..
After drawing the object, I draw lines in red.
It all worked out fine. The problem arise when I input lighting properties.
When I create a light source, everything where the light projects becomes white.
Why does the lighting over writes my color? And how do I solve this problem?
Thanks in advance..
The code you have would help in diagnosing the problem. This sounds like a problem with setting up the materials for the items (which define how they interact with the lights).
You may want to look into the glColorMaterial function. The following snippet of code will set this up:
GLfloat mat_specular[] = {0.3, 0.3, 0.3, 1.0};
GLfloat mat_shininess[] = { 10.0 };
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);