OpenGL 基础图形绘制与投影变换

本文参考《Computer Graphics Using OpenGL》,第一个例子绘制了

1. 参数定义的House

2. a flurry of filled rectangles

3. Sierpinski曲线

含有鼠标和键盘响应函数onmouse和onkeyboard。


/************************************************************************/
/* CreateTime:2013-2-18
**Author:@Rachel Zhang
**Discription: Draw Parameter House, Flurry and Sierpinski
**3rd-party:OpenGL*/
/************************************************************************/

#include "GL/glut.h"
#include "stdlib.h"
#include <iostream>
using namespace std;
#define screenHeight 480

class GLintPoint{
public: 
	GLint x, y;
};

// Create a number between 0 and m(a number which will be given)
// the input m must be less than 32767 according to P49 in <Computer Graphics Using OpenGL>
int random(int m)
{
	return rand()%m;
}

void drawDot (GLint x, GLint y)
{
	glPointSize(3);
	glBegin(GL_POINTS);
	glVertex2i(x,y);
	glEnd();
}

typedef struct
{
	GLfloat r, g, b;
} GLfloatRGBColour;

GLfloatRGBColour colour[8] = { {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f},
{1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};

void setPenColour(GLfloatRGBColour newColour)
{
	glColor3f(newColour.r, newColour.g, newColour.b);
}

/************************************************************************/
/*                                Draw Functions                                      */
/************************************************************************/
void parameterizedHouse(GLintPoint peak, GLint width, GLint height)
	// the top of house is at the peak; the size of house is given
	//  by height and width
{
	glBegin(GL_LINE_LOOP);
	glVertex2i(peak.x,             peak.y);  // draw shell of house 
	glVertex2i(peak.x + width / 2, peak.y - 3 * height /8);
	glVertex2i(peak.x + width / 2,  peak.y -     height);
	glVertex2i(peak.x - width / 2, peak.y -     height);
	glVertex2i(peak.x - width / 2, peak.y - 3 * height /8);	
	glEnd();
}

void drawFlurry(int num, int Width, int Height)
	// draw num random rectangles in a Width by Height rectangle 
{
	for (int i = 0; i < num; i++) 
	{
		GLint x1 = random(Width);			// place corner randomly 
		GLint y1 = random(Height);
		GLint x2 = random(Width); 		// pick the size so it fits 
		GLint y2 = random(Height);
		GLfloat lev = random(10)/10.0;		// random value, in range 0 to 1 
		glColor3f(lev,lev,lev);			// set the gray level 
		glRecti(x1, y1, x2, y2);			// draw the rectangle
	}
	glFlush();
}  

void drawSierpinski(GLintPoint corner[3])
{ 
	int i, index, tcolour=0;
	GLintPoint point;
	point = corner[random(3)];
	drawDot(point.x, point.y);

	for (i = 0; i < 1000; i++)
	{
		index = random(3);
		point.x = (point.x + corner[index].x)/2;
		point.y = (point.y + corner[index].y)/2;  
		tcolour = (++tcolour)%7;       // col = (col + 1) mod 7;
		setPenColour(colour[tcolour]);
		drawDot(point.x, point.y);
	}
}

/************************************************************************/
/*                         Mouse Listener and keyboard Listener                    */
/************************************************************************/
void myMouse(int button, int state, int x, int y)
{
	static GLintPoint corners[3];
	static int numCorners;

	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		corners[numCorners].x = x;
		corners[numCorners].y = screenHeight - y - 1;
		if (++numCorners == 3)
		{
			drawSierpinski(corners);
			numCorners = 0;
		}
	}
	else if (button==GLUT_RIGHT_BUTTON)
		glClear(GL_COLOR_BUFFER_BIT);
	glFlush();
}

void onKeyBoard(unsigned char key,int mousex, int mousey)
{
	switch (key)
	{
	case 'q':
		exit(0);
	case 'r':
		static GLintPoint corners[3];
		for (int i=0;i<3;i++)
		{
			corners[i].x = random(640);
			corners[i].y = random(screenHeight);
		}
		drawSierpinski(corners);
	default:
		break;
	}
}

// Initialization 
void Init(void)     
{
	glClearColor(1.0,1.0,1.0,0.0); // Set white background color
	glColor3f(0.0f,0.0f,0.0f);    // Set the drawing color
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0,640.0,0.0,480.0);
}

void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);       //clear the screen
	GLintPoint Mypoint = {200,100};
	parameterizedHouse(Mypoint,100,100);
	drawFlurry(4,100,100);
	glFlush();
}

void main(int argc,char *argv[])
{
	glutInit(&argc, argv);  // Initialize the toolkit
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);  // Set display mode
	glutInitWindowPosition(100, 150);  // Set window pozition on screen
	glutInitWindowSize(640, 480);      // Set window size
	glutCreateWindow("parameterizedHouse, Flurry and drawSierpinski"); // Open the screen window
	glutDisplayFunc(myDisplay); // Register redraw function 
	glutMouseFunc(myMouse);
	glutKeyboardFunc(onKeyBoard);
	Init();
	glutMainLoop();  // Go into a perpetual loop
}

效果图:

OpenGL 基础图形绘制与投影变换_第1张图片


第二个例子绘制了这样一系列图形:

OpenGL 基础图形绘制与投影变换_第2张图片


在其中有空间投影变换,主要应用了三个函数:

投影变换函数glViewport(), 矩阵平移函数glTranslated() 和正射投影函数 glOrtho()

上图实现代码参考《计算机图形学-用OpenGL实现第2版》:

#include <windows.h>  //suitable when using Windows 95/98/NT
#include <gl/Gl.h>
#include <gl/Glu.h>
#include <gl/glut.h>
//<<<<<<<<<<<<<<<<<<< axis >>>>>>>>>>>>>>
void axis(double length)
{ // draw a z-axis, with cone at end
	glPushMatrix();
	glBegin(GL_LINES);
	glVertex3d(0, 0, 0); glVertex3d(0,0,length); // along the z-axis
	glEnd();
	glTranslated(0, 0,length -0.2); 
	glutWireCone(0.04, 0.2, 12, 9);
	glPopMatrix();
}	
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<< displayWire >>>>>>>>>>>>>>>>>>>>>>
void displayWire(void)
{
	glMatrixMode(GL_PROJECTION); // set the view volume shape
	glLoadIdentity();
	glOrtho(-2.0*64/48.0, 2.0*64/48.0, -2.0, 2.0, 0.1, 100);//正射投影函数
	glMatrixMode(GL_MODELVIEW); // position and aim the camera
	glLoadIdentity();
	gluLookAt(2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);//define viewpoint transformation

	//Draw axis
	glClear(GL_COLOR_BUFFER_BIT); // clear the screen
	glColor3d(0,0,0); // draw black lines
	axis(0.5);					 // z-axis
	glPushMatrix(); 
	glRotated(90, 0,1.0, 0);
	axis(0.5);					// y-axis
	glRotated(-90.0, 1, 0, 0);
	axis(0.5);					// z-axis
	glPopMatrix();	

	//Draw Cube
	glPushMatrix();
	glTranslated(0.5, 0.5, 0.5); // multiply by a translation matrix, define center (0.5, 0.5, 0.5)
	glutWireCube(1.0);
	glPopMatrix();

	//Draw Sphere
	glPushMatrix();	
	glTranslated(1.0,1.0,0);	// sphere at (1,1,0)
	glutWireSphere(0.25, 10, 8);
	glPopMatrix();	

	//Draw Cone
	glPushMatrix();	
	glTranslated(1.0,0,1.0);	// cone at (1,0,1)
	glutWireCone(0.2, 0.5, 10, 8);
	glPopMatrix();

	//Draw Teapot
	glPushMatrix();
	glTranslated(1,1,1);
	glutWireTeapot(0.2); // teapot at (1,1,1)
	glPopMatrix();

	//Draw Torus
	glPushMatrix();
	glTranslated(0, 1.0 ,0); // torus at (0,1,0)
	glRotated(90.0, 1,0,0);
	glutWireTorus(0.1, 0.3, 10,10);
	glPopMatrix();

	//十二面体
	glPushMatrix();
	glTranslated(1.0, 0 ,0); // dodecahedron at (1,0,0)
	glScaled(0.15, 0.15, 0.15);
	glutWireDodecahedron();
	glPopMatrix();

	glPushMatrix();
	glTranslated(0, 1.0 ,1.0); // small cube at (0,1,1)
	glutWireCube(0.25);
	glPopMatrix();

	glPushMatrix();
	glTranslated(0, 0 ,1.0); // cylinder at (0,0,1)
	GLUquadricObj * qobj;
	qobj = gluNewQuadric();
	gluQuadricDrawStyle(qobj,GLU_LINE);
	gluCylinder(qobj, 0.2, 0.2, 0.4, 8,8);
	glPopMatrix();
	glFlush();
}

//<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );
	glutInitWindowSize(640,480);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("Transformation testbed - wireframes");
	glutDisplayFunc(displayWire);
	glClearColor(1.0f, 1.0f, 1.0f,0.0f);  // background is white
	glViewport(0, 0, 640, 480);//投影变换函数
	glutMainLoop();
}




Reference:

http://www.oocities.org/uniq_friq/c_files/openGL/1lab/dots.htm



你可能感兴趣的:(OpenGL 基础图形绘制与投影变换)