对应 任务:五、实现自己的三角形线框显示算法,能够将三角形的各个顶点经过坐标变换后变换到屏幕坐标,并以连线的方式将三角形的各个边显示出来。要求连线不使用Windows API,而是利用自己的2D Line算法,例如:2DDA算法。

#include<windows.h>
#include<iostream>
#include<vector>
#include <GL/glut.h>
using namespace std;
struct node
{
	float x, y, z;
};
vector<node> G;

vector<node> Get_Point()
{
	vector<node> G;
	G.push_back({ 0, 0, 0 });
	G.push_back({ 0.1, 0.1, 0.1 });
	G.push_back({ 0.2, 0.2, 0.2 });
	return G;
}

void Display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glPointSize(2.0f);
	glBegin(GL_POINTS);

	//    printf("%d\n", G.size());
	//    G = Get_Point();
	for (int i = 0; i < G.size(); ++i) {
		cout << G[i].x << " " << G[i].y << " " << G[i].z << endl;
		glVertex3f(G[i].x / 100, G[i].y / 100, G[i].z / 100);
	}
	glEnd();
	glFlush();
}

void init(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(1000, 1000);
	glutCreateWindow("Three Window");
}


inline int round1(const float a) { return int(a + 0.5); }

void lineDDA(int x0, int y0, int xEnd, int yEnd) {
	int dx = xEnd - x0, dy = yEnd - y0, steps, k;
	float xIncrement, yIncrement, x = x0, y = y0;
	steps = max(fabs(dx), fabs(dy));

	xIncrement = float(dx) / float(steps);
	yIncrement = float(dy) / float(steps);
	cout << "xIncrement: " << xIncrement << " yIncrement: " << yIncrement << endl;
	int id = 1;
	node tmp;
	tmp.x = round1(x);
	tmp.y = round1(y);
	tmp.z = ++id;
	G.push_back(tmp);
	for (k = 0; k < steps; k++) {
		x += xIncrement;
		y += yIncrement;
		tmp.x = round1(x);
		tmp.y = round1(y);
		tmp.z = ++id;
		G.push_back(tmp);
	}
}



int main(int argc, char* argv[])
{
	init(argc, argv);
	//    lineDDA(10, 10, 75, 75);
	lineDDA(0, 0, 10, 10);
	lineDDA(0, 0, 0, 10);
	lineDDA(0, 10, 10, 10);
	glutDisplayFunc(&Display);
	glutMainLoop();
	return 0;
}

【效果图】

OpenGL底层API实现之路3----画一个三角形_ios

【另一种方法】

main.cpp

#include<windows.h>
#include<iostream>
#include<stdio.h>
#include <GL/glut.h>
#include<vector>
#include"opengl_math.h"
#include "node.h"
using namespace std;
const float Width = 500, Height = 500;

DirectionalLight m_directionalLight;

//坐标数组集
vector<node> G;
/*
	函数名:Draw_Point
	功能:根据颜色、坐标画点
*/
void Draw_Point(Vector3f Color, Vector3f Position)
{
	glColor3f(Color[0], Color[1], Color[2]);
	glVertex3f(Position[0], Position[1], Position[2]);
}
/*
	函数名:Check_Point
	功能:检查坐标是否超出窗口大小
*/
bool Check_Point(float x, float y, float z = 0)
{
	if (x > Width / 2 || x < -Width / 2 || y > Height / 2 || y < -Height / 2) {
		printf("ERROR:坐标超出窗口大小 坐标为:(%f, %f, %f), 窗口取值区间为x:[%f, %f], y:[%f, %f]", x, y, z, -Width / 2, Width / 2, -Height / 2, Height / 2);
		exit(0);
		return 0;
	}
	else {
		return 1;
	}
}


/*
	函数名:Render
	功能:绘图
*/
void Render()
{
	m_directionalLight.AmbientIntensity *= 1.1f;
	glClear(GL_COLOR_BUFFER_BIT);
	glPointSize(2.0f);
	glBegin(GL_POINTS);

	
	for (int i = 0; i < G.size(); ++i) {
		Vector3f tmp;
		LoadVector3(tmp, G[i].x, G[i].y, G[i].z);
		Draw_Point(m_directionalLight.Color, tmp);
	}
	

	glEnd();
	glFlush();
}


/*
	函数名:round1
	功能:四舍五入函数
*/
inline int round1(const float a) { return int(a + 0.5); }

/*
	函数名:lineDDA
	功能:lineDDA算法画线
*/
void lineDDA(int x0, int y0, int xEnd, int yEnd) {
	int dx = xEnd - x0, dy = yEnd - y0, steps, k;
	float xIncrement, yIncrement, x = x0, y = y0;
	steps = max(fabs(dx), fabs(dy));

	xIncrement = float(dx) / float(steps);
	yIncrement = float(dy) / float(steps);
	cout << "xIncrement: " << xIncrement << " yIncrement: " << yIncrement << endl;
	int id = 1;
	node tmp;
	tmp.x = round1(x);
	tmp.y = round1(y);
	tmp.z = 0;
	G.push_back(tmp);
	for (k = 0; k < steps; k++) {
		x += xIncrement;
		y += yIncrement;
		tmp.x = round1(x);
		tmp.y = round1(y);
		tmp.z = 0;
		G.push_back(tmp);
	}
}

/*
	函数名:Create_Point_Buffer
	功能:预处理坐标数组
*/

void Create_Points_Buffer()
{
	lineDDA(0, 0, 200, 200);
	lineDDA(200, 200, 0, 200);
	lineDDA(0, 200, 0, 0);
	

	//坐标标准化
	for (int i = 0; i < G.size(); ++i) {
		Check_Point(G[i].x, G[i].y);
		Transform_Coordinates(G[i].x, G[i].y, Width, Height);
		printf("%f %f\n", G[i].x, G[i].y);
	}

}

void init(int argc, char* argv[])
{
	glutInit(&argc, argv);
	Create_Points_Buffer();

	glutInitDisplayMode(GLUT_RGB);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(Width, Height);
	glutCreateWindow("Windows");
}



int main(int argc, char* argv[])
{
	init(argc, argv);
	LoadVector3(m_directionalLight.Color, 1.0f, 0.0f, 0.0f);
	m_directionalLight.AmbientIntensity = 0.1f;
	glutDisplayFunc(&Render);

	glutMainLoop();
	return 0;
}

node.h

#ifndef __NODE_H
#define __NODE_H

#include "opengl_math.h"
/*
	环境光的结构体
*/
struct DirectionalLight
{
	Vector3f Color;
	float AmbientIntensity;
};
/*
	坐标点的结构体
*/
struct node
{
	float x, y, z;
};

#endif 

opengl_math.h

#ifndef __OPENGL_MATH_H
#define __OPENGL_MATH_H
typedef float Vector3f[3];

/*
	函数名:LoadVector3
	功能:给三维坐标赋值
*/
void LoadVector3(Vector3f a, float x, float y, float z)
{
	a[0] = x, a[1] = y, a[2] = z;
}

/*
	函数名:Transform_Standard_Coordinates
	功能:将坐标大小转化为2 * 2 的坐标系内
*/
void Transform_Coordinates(float &x, float &y, const float Width, const float Height)
{
	x = x * 2 / Width;
	y = y * 2 / Height;
}

#endif // DEBUG

效果图

OpenGL底层API实现之路3----画一个三角形_#include_02