对应 任务:五、实现自己的三角形线框显示算法,能够将三角形的各个顶点经过坐标变换后变换到屏幕坐标,并以连线的方式将三角形的各个边显示出来。要求连线不使用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;
}
【效果图】
【另一种方法】
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
效果图