歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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
}

效果圖:

第二個例子繪制了這樣一系列圖形:

在其中有空間投影變換,主要應用了三個函數:

投影變換函數glViewport(), 矩陣平移函數glTranslated() 和正射投影函數 glOrtho()

上圖實現代碼參考《計算機圖形學-用OpenGL實現第2版》:

計算機圖形學(第三版)高清中文版 PDF 下載 見 http://www.linuxidc.com/Linux/2013-08/88723.htm

#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

OGLplus教程學習筆��� -- Outline http://www.linuxidc.com/Linux/2014-07/104835.htm

OpenGL編程指南(原書第7版)中文掃描版PDF 下載 http://www.linuxidc.com/Linux/2012-08/67925.htm

OpenGL 渲染篇 http://www.linuxidc.com/Linux/2011-10/45756.htm

Ubuntu 13.04 安裝 OpenGL http://www.linuxidc.com/Linux/2013-05/84815.htm

OpenGL三維球體數據生成與繪制【附源碼】 http://www.linuxidc.com/Linux/2013-04/83235.htm

Ubuntu下OpenGL編程基礎解析 http://www.linuxidc.com/Linux/2013-03/81675.htm

如何在Ubuntu使用eclipse for c++配置OpenGL http://www.linuxidc.com/Linux/2012-11/74191.htm

《OpenGL超級寶典》學習筆記 http://www.linuxidc.com/Linux/2013-10/91414.htm

Copyright © Linux教程網 All Rights Reserved