【OpenGL基础篇】——使用面向对象方法封装OpenGL函数(一)

OpenGL是一个开源的图形库,既可开发二维图形软件,也可开发三维图形软件。许多知名应用就是基于OpenGL开发出来,如著名的Artoolkit和Unity3D。

GLUT是代表OpenGL应用工具包,英文全称为OpenGL Utility Toolkit,是一个和窗口系统无关的软件包,它由Mark Kilgard在SGI时写的。作为AUX库的功能更强大的替代品,用于隐藏不同窗口系统API的复杂性。(百度百科)

因为OpenGL的API是底层图形库API,使用起来还是有些复杂,所以,我打算使用面向对象的方法将OpenGL和GLUT库的函数封装成一个图形类库,顺便学习一下计算机图形学(这学期的课)的基础知识以及面向对象的编程方法。懂了这些底层的东西,对理解Unity3D这样的游戏引擎也有好处。

使用的是GLUT,所以只实现了一些简单的功能,以后慢慢扩展,这只是(一)。

虽然是使用C++来编写类库,但还是融入了一点Java的东西,比如,类库中的所有类都是Object的子类(用于实现多态)。

下面是Object类:

/*******************************************************************
*文件名:Object.h
*功能:声明Object类,此类是GL类库里所有类的父类(即Java中的那个Object)
********************************************************************/
#ifndef _OBJECT_H_
#define _OBJECT_H_

#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

/*类声明*/
class Object
{
public:
	//默认构造函数
	Object() {
		className = "Object";
	}
	//返回类名
	virtual string toString(){
		return this->className;
	}
	//显示界面
	virtual void show() {
		//虚函数,留待继承,以实现多态
	}
	//创造对象
	virtual void create(){

	}
	//删除对象
	virtual void destory() {

	}
protected:
	string className;	//类名
};
#endif


然后是一个 Window类,就是窗口(以前学MFC等语言时,最怕的就是API和可选择解决方案多,所以我在这里只写了少数几个函数,毕竟只是为了学习)

/**********************************************************
*文件名:Window.h
*功能:封装了窗口操作的Window类
***********************************************************/

#ifndef _WINDOW_H_
#define _WINDOW_H_

#include "Object.h"
#include "OpenGL\glut.h"
#include <vector>
using std::vector;

class Window : protected Object {

public:
	//默认构造函数
	Window();
	//输入窗口名的构造函数
	Window(string title);
	//同时设置窗口名称、位置和大小的构造函数
	Window(string title, int x, int y, int width, int height);
	//显示界面
	void show();
	//创建窗口
	void create();
	//添加组件,在窗口显示时会依次在窗口里显示出来
	void add(Object* object);
	//删除对象
	void destory();
	
private:
	string title;				//窗口标题
	int xPosition, yPosition;	//窗口坐标
	int width, height;			//窗口大小
	vector<Object*> objectVector;

	//初始化函数
	void init(){
		this->setTitle(string("未命名窗口"));
		int x = 100, y = 100, width = 800, height = 600;
		this->setPostion(x, y);
		this->setWidthAndHeight(width, height);
		this->className = "Window";
		this->isCreated = false;
	}

public:
	//设置窗口标题
	void setTitle(string t);
	//获取窗口标题
	string getTitle();
	int getWidth(){
		return this->width;
	}
	int getHeight() {
		return this->height;
	}
	//设置窗口位置
	void setPostion(int x, int y);
	//设置窗口大小
	void setWidthAndHeight(int width, int height);
	//判断窗口是否被创建
	bool isCreated;
	//对象名
	string toString() {
		return this->className;
	}

private:
	//绘制界面
	void Paint(void);
	
};

#endif


下面是实现的Cpp文件:

#include "Window.h"

Window::Window(){
	
}

Window::Window(string t){
	this->init();
	this->setTitle(t);
}

Window::Window(string t , int x, int y, int width, int height){
	this->init();
	this->setTitle(t);
	this->setPostion(x, y);
	this->setWidthAndHeight(width, height);
}

void Window::setTitle(string t) {
	this->title = t;
}

void Window::setPostion(int x, int y) {
	this->xPosition = x;
	this->yPosition = y;
}

void Window::setWidthAndHeight(int w, int h) {
	this->width = w;
	this->height = h;
}

void Window::create() {
	glutInitWindowPosition(this->xPosition, this->yPosition);	//设置窗口位置
	glutInitWindowSize(this->width, this->height);				//设置窗口大小
	glutCreateWindow(this->title.c_str());//创建一个名为title的窗口
	this->isCreated = true;
	gluOrtho2D(0.0, (double)this->getWidth(),
<span style="white-space:pre">		</span>(double)this->getHeight(), 0.0); //正交的投影矩阵,坐标以左上角为原点
}

void Window::Paint(void)
{
	int size = this->objectVector.size();
	for (int i = 0; i < size; i++)
	{
		objectVector.at(i)->show();
	}
}

void Window::show() {
	this->Paint();
}

//添加组件,在窗口显示时会依次在窗口里显示出来
void Window::add(Object* object){
	objectVector.push_back(object);
}

void Window::destory() {
	int size = this->objectVector.size();
	for (int i = 0; i < size; i++)
	{
		cout << "destory:" + objectVector.at(i)->toString() << endl;
		delete objectVector.at(i);
	}
	cout << "destory:" + this->toString() << endl;
}

然后是一个颜色 Color类,暂时只支持RGB模式,从现在起,我会尽量把声明和定义都写在一个文件里,就像Java那样。

/**************************************************
文件名:Color.h
功能:颜色类,用于指定颜色
***************************************************/
#ifndef _COLOR_H_
#define _COLOR_H_
#include "Object.h"
class Color : protected Object {
public:
	Color(){
		Color(0, 0, 0);
		this->className = "Color";
	}
	Color(int r, int g, int b) {
		this->R = (double)r / 255;
		this->G = (double)g / 255;
		this->B = (double)b / 255;
	}
public:
	double R, G, B;
};
#endif

接下来就是绘图里面最重要的了—— Point,有了点,才能有一切

/**********************************************************
文件名:Point.h
功能:实现屏幕上的坐标点
***********************************************************/
#ifndef _POINT_H
#define _POINT_H
#include "Object.h"
#include "Color.h"
#include "OpenGL\glut.h"
class Point : protected Object {
public:
	Point() {
		setPoint(0, 0, Color(0, 0, 0));
		this->className = "Point";
	}
	Point(int x, int y) {
		setPoint(x, y, Color(0, 0, 0));
	}
	Point(int x, int y , Color color) {
		setPoint(x, y, color);
	}

	void setPoint(int x, int y){
		setPoint(x, y, Color(0, 0, 0));
	}

	void setPoint(int x, int y,Color color){
		this->X = x;
		this->Y = y;
		this->color = color;
	}

	void show() {
		glColor3d(color.R, color.G, color.B);
		glBegin(GL_POINTS);
		glVertex2i(this->X, this->Y);
		glEnd();
	}
public:
	int X;
	int Y;
	Color color;
};
#endif


最后就是最重要的应用程序 Application类了,这个类用于添加窗口以及图像重绘刷新

/*********************************************************
*文件名:Application.h
*功能:用于创建应用程序
**********************************************************/

#ifndef _APPLICATION_H_
#define _APPLICATION_H_

#include "Object.h"
#include "OpenGL\glut.h"
#include "Window.h"
#include <vector>
using std::vector;

class Application : protected Object {
public:
	Application(){
		className = "Application";
	}
	~Application(){
		destory();
	}
	static vector<Window> windowVector;		//窗口的静态线性表
	//初始化GLUT
	static void init(int argc, char *argv[]){
		glutInit(&argc, argv);
		
		//设置显示模式
		glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	}
	//添加组件
	static bool add(Window object) {
		if (object.isCreated) {
			windowVector.push_back(object);
			return true;
		}
		return false;
	}
	void show(){
		if (windowVector.size() > 0) {
			glutDisplayFunc(&Paint);
			//进入显示循环(无此句则程序执行结束)
			glutMainLoop();
		}
		Paint();
	}
	void destory() {
		for (int i = 0; i < windowVector.size(); i++) {
			windowVector[i].destory();
		}
		cout << "destory:" + this->toString()<<endl;
	}
private:
	static void Paint(){
		glClear(GL_COLOR_BUFFER_BIT);			//清除窗口屏幕
		for (int i = 0; i < windowVector.size(); i++) {
			windowVector[i].show();
		}
		glFlush();//刷新绘图命令
	}
};
vector<Window> Application::windowVector;
#endif

下面是一个测试文件,只画了一条紫色虚线:

#include "Window.h"
#include "Color.h"
#include "Point.h"
#include "Application.h"
//隐藏控制台窗口
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

int main(int argc ,char* argv[]) {

	int w = 400, h = 300;
	Window window(string("Hello"), 100, 100, w, h);
	window.create();

	Point* p;
	for (int i = 0; i < 70; i++) {
		p = new Point(200,10+4*i,Color(255,0,255));
		window.add((Object*)p);
	}
	Application* app = new Application();
	app->init(argc, argv);
	app->add(window);
	app->show();
	delete app;
	return 0;
}

出来的效果如下图:

【OpenGL基础篇】——使用面向对象方法封装OpenGL函数(一)_第1张图片

黑色的屏幕中间有一条紫色的虚线。

今天的代码漏了很多重要的东西,比如窗口背景颜色的设定等,以后随着学习的慢慢深入,会一一添加。

你可能感兴趣的:(编程,面向对象,application,应用程序,OpenGL)