我正试图将灯光,材料和阴影放到我的机器人手臂上,但遗憾的是发生了一些奇怪的事情(请编译或看下图),现在我仍然烦恼于
1)未显示正确的光照和反射属性以及材料属性
2)没有画过阴影,虽然我已经在函数“void showobj(void)”中完成了阴影投射
我很感激,如果有人可以提供帮助,我已经为它工作了2天没有进展:(
以下是我的代码
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <GL/glut.h>
#include "gsrc.h"
#include <Windows.h>
const double PI = 3.14159265;
// angles to rotate the base, lower and upper arms of the robot arm
static GLfloat theta, phi, psi = 0.0;
//Starting time
double startT;
//Time Diff variable
double dif,startTime,endTime,deltaT;
//define n
double n = 3;
//Set the parameters of the light number one
GLfloat Xs = 35.0;
GLfloat Ys = 35.0;
GLfloat Zs = 35.0;
//Shadow color
GLfloat shadowcolor[] = {0.0,0.0,0.0};
//initialize the window and everything to prepare for display
void init_gl() {
//set display color to white
glClearColor(1,1,1,0);
//clear and enable z-buffer
glClear (GL_DEPTH_BUFFER_BIT);
glEnable (GL_DEPTH_TEST);
//clear display window
glClear(GL_COLOR_BUFFER_BIT);
}
//Draw the base of the robot arm
void draw_base(){
glPushMatrix();
//to create the quadric objects
GLUquadric *qobj,*qobjl,*qobju;
qobj = gluNewQuadric();
qobjl = gluNewQuadric();
qobju = gluNewQuadric();
//set the color of the cylinder
glColor3f(1.0,0.0,0.0);
//Re-position the cylinder (x-z plane is the base)
glRotatef(-90,1.0,0.0,0.0);
//Draw the cylinder
gluCylinder(qobj, 30.0, 30.0, 40.0, 40.0, 40.0);
//Draw the upper disk of the base
gluDisk(qobju,0,30,40,40);
glPushMatrix();
//Change the M(lowdisk<updisk)
glTranslatef(0,0,40);
glColor3f(0,0,0);
//Draw the lower disk of the base
gluDisk(qobjl,0,30,40,40);
glPopMatrix();
glPopMatrix();
}
/***********************Texture Work Starts************************************/
//Load the raw file for texture
/* Global Declarations */
#define IW 256 // Image Width
#define IH 256 // Image Height
//3D array to store image data
unsigned char InputImage [IW][IH][4];
// Read an input image from a .raw file with double
void ReadRawImage ( unsigned char Image[][IH][4] )
{
FILE *fp;
int i, j, k;
char* filename;
unsigned char temp;
filename = "floor.raw";
if ((fp = fopen (filename, "rb")) == NULL)
{
printf("Error (ReadImage) : Cannot read the file!!\n");
exit(1);
}
for ( i=0; i<IW; i++)
{
for ( j=0; j<IH; j++)
{
for (k = 0; k < 3; k++) // k = 0 is Red k = 1 is Green K = 2 is Blue
{
fscanf(fp, "%c", &temp);
Image[i][j][k] = (unsigned char) temp;
}
Image[i][j][3] = (unsigned char) 0; // alpha = 0.0
}
}
fclose(fp);
}
/****************************Texture Work Ends***************************************/
/****************************Light and Shadows***************************************/
void lightsrc(){
GLfloat light1PosType [] = {Xs, Ys, Zs, 1.0};
//GLfloat light2PosType [] = {0.0, 100.0, 0.0, 0.0};
glLightfv(GL_LIGHT1, GL_POSITION, light1PosType);
//glEnable(GL_LIGHT1);
//glLightfv(GL_LIGHT2, GL_POSITION, light2PosType);
//glEnable(GL_LIGHT2);
GLfloat whiteColor[] = {1.0, 1.0, 1.0, 1.0};
GLfloat blackColor[] = {0.0, 0.0, 0.0, 1.0};
glLightfv(GL_LIGHT1, GL_AMBIENT, blackColor);
glLightfv(GL_LIGHT1, GL_DIFFUSE, whiteColor);
glLightfv(GL_LIGHT1, GL_SPECULAR, whiteColor);
glEnable(GL_LIGHT1);
glEnable( GL_LIGHTING );
}
/****************************Light and Shadows work ends***************************************/
//Draw the 2x2x2 cube with center (0,1,0)
void cube(){
glPushMatrix();
glTranslatef(0,1,0);
glutSolidCube(2);
glPopMatrix();
}
//Draw the lower arm
void draw_lower_arm(){
glPushMatrix();
glScalef(15.0/2.0,70.0/2.0,15.0/2.0);//scale half is enough (some part is in the negative side)
cube();
glPopMatrix();
}
//Draw the upper arm
void draw_upper_arm(){
glPushMatrix();
glScalef(15.0/2.0,40.0/2.0,15.0/2.0);//scale half is enough (some part is in the negative side)
cube();
glPopMatrix();
}
void drawCoordinates(){
glBegin (GL_LINES);
glColor3f (1,0,0);
glVertex3f (0,0,0);
glVertex3f (600,0,0);
glColor3f (0,1,0);
glVertex3f (0,0,0);
glVertex3f (0,600,0);
glColor3f (0,0,1);
glVertex3f (0,0,0);
glVertex3f (0,0,600);
glEnd();
}
//To draw the whole robot arm
void drawRobot(){
//Robot Drawing Starts
//Rotate the base by theta degrees
glRotatef(theta,0.0,1.0,0.0);
//Draw the base
draw_base();
//M(B<La)
glTranslatef(0.0,40.0,0.0);
//Rotate the lower arm by phi degree
glRotatef(phi,0.0,0.0,1.0);
//change the color of the lower arm
glColor3f(0.0,0.0,1.0);
//Draw the lower arm
draw_lower_arm();
//M(La<Ua)
glTranslatef(0.0,70.0,0.0);
//Rotate the upper arm by psi degree
glRotatef(psi,0.0,0.0,1.0);
//change the color of the upper arm
glColor3f(0.0,1.0,0.0);
//Draw the upper arm
draw_upper_arm();
//Drawing Finish
glutSwapBuffers();
}
void showobj(void) {
//set the projection and perspective parameters/arguments
GLint viewport[4];
glGetIntegerv( GL_VIEWPORT, viewport );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 45, double(viewport[2])/viewport[3], 0.1, 1000 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(-200, 300, 200, 0, 0, 0, 0,1,0 );
// get the rotation matrix from the rotation user-interface
glMultMatrixf(gsrc_getmo() );
//Clear the display and ready to show the robot arm
init_gl();
//put the light source
lightsrc();
//Draw coordinates
drawCoordinates();
//give material properties
GLfloat diffuseCoeff[] = {0.2, 0.4, 0.9, 1.0}; // kdR= 0.2, kdG= 0.4, kdB= 0.9
GLfloat specularCoeff[] = {1.0, 1.0, 1.0, 1.0}; //
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuseCoeff);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularCoeff);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 100.0 ); // ns= 25
//Draw the ground floor
glColor3f(0.4,0.4,0.4);
glPushMatrix();
glRotatef(90,1,0,0);
glRectf(-500,-500,500,500);
glPopMatrix();
int i,j;
GLfloat M[4][4];
for (i=0; i<4; i++){
for (j=0; j<4; j++){
M[i][j] = 0;
}
M[0][0]=M[1][1]=M[2][2]=1;
M[2][3]=-1.0/Zs;
}
//Start drawing shadow
drawRobot(); // draw the objects
glPushMatrix( ); // save state
glMatrixMode(GL_MODELVIEW);
glTranslatef(Xs, Ys, Zs);// Mwc←s
glMultMatrixf(M[4]);// perspective project
glTranslatef(-Xs, -Ys, -Zs);// Ms←wc
glColor3fv (shadowcolor);
//Draw the robot arm
drawRobot();
glPopMatrix(); // restore state
//Shadow drawing ends
glFlush ();
}
//To animate the robot arm
void animate(void)
{
//get the end time
endTime = timeGetTime();
//float angle;
//calculate deltaT
deltaT = (endTime - startTime); //in msecs
//float test;
float deltaTSecs = deltaT/1000.0f; //in secs
//apply moving equation
psi = (90.0) * 0.50 * (1-cos((deltaTSecs/(n+1)) * PI));
glutPostRedisplay ();
}
void main (int argc, char** argv)
{
glutInit(&argc, argv);
//DOUBLE mode better for animation
// Set display mode.
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition( 50, 100 ); // Set top-left display-window position.
glutInitWindowSize( 400, 300 ); // Set display-window width and height.
glutCreateWindow( "Robot arm : my first self-learning opengl program" ); // Create display window.
// Register mouse-click and mouse-move glut callback functions
// for the rotation user-interface.
//Allow user to drag the mouse and view the object
glutMouseFunc( gsrc_mousebutton );
glutMotionFunc( gsrc_mousemove );
//record the starting time
startTime = timeGetTime();
// Display everything in showobj function
glutDisplayFunc(showobj);
//Perform background processing tasks or continuous animation
glutIdleFunc(animate);
glutMainLoop();
}
答案 0 :(得分:1)
你的屏幕闪烁,因为你在drawRobot()中调用了glutSwapBuffers()。这会使您的屏幕重绘两次,一次是在绘制机器人时,另一次是在绘制阴影时。此外,您在最后的drawRobot()和glPopMatrix()开头缺少glPushMatrix()。你需要把它放在那里,否则它会影响渲染(阴影将随着手臂的上部链接移动)。
然后,您指定阴影矩阵错误。我们试试这个:
int i,j;
GLfloat M[4][4];
for (i=0; i<4; i++){
for (j=0; j<4; j++){
M[i][j] = 0;
}
}
M[0][0]=M[1][1]=M[2][2]=1;
M[2][3]=-1.0/Zs;
drawRobot(); // draw the objects
//Start drawing shadow
glEnable(GL_CULL_FACE);
glDisable(GL_LIGHTING); // want constant-color shadow
glPushMatrix( ); // save state
glMatrixMode(GL_MODELVIEW);
glTranslatef(Xs, Ys, Zs);// Mwc←s
glMultMatrixf(&M[0][0]);// perspective project
glTranslatef(-Xs, -Ys, -Zs);// Ms←wc
glColor3fv (shadowcolor);
//Draw the robot arm
drawRobot();
glPopMatrix(); // restore state
glDisable(GL_CULL_FACE);
glEnable(GL_LIGHTING); // enable again ...
//Shadow drawing ends
另外,你可以看到我已经在阴影周围添加了GL_CULL_FACE,这是为了避免深度战斗。这或多或少在技术上修复了它。
但仍然 - 阴影位置计算不正确。让我们试着看projection shadows。
首先,我们需要有地平面和光线的位置:
float g[] = {0, 1, 0, 0}; // ground plane
float l[] = {20, 300, 50, 1}; // light position and "1"
这是平面方程和均匀光位置(正常3D位置,用“1”填充)。然后你丢弃你的阴影矩阵设置(glTranslatef(),glMultMatrixf()和glTranslatef())并调用myShadowMatrix(g,l),所以它变成:
glPushMatrix( ); // save state
glMatrixMode(GL_MODELVIEW);
float g[] = {0, 1, 0, 0}; // ground plane
float l[] = {20, 300, 50, 1}; // light position and "1"
myShadowMatrix(g, l);
glColor3fv (shadowcolor);
//Draw the robot arm
drawRobot();
glPopMatrix(); // restore state
这大部分都有效。仍然有很多z-fighting正在进行,阴影有四种不同的颜色。至于颜色,停止在drawRobot()中调用glColor3f(),对于z-fighting,请使用:
glPolygonOffset(-1, -1);
glEnable(GL_POLYGON_OFFSET_FILL);
// before
// draw shadow
glDisable(GL_POLYGON_OFFSET_FILL);
// afterwards
这使得一个漂亮的平面阴影演示:)。干杯......
SW。