图形学作业要到deadline了,赶紧写一个
这个算法比之前的算法的工作量都要大,但是只要思路清晰,也不是很难。
1.创建各种需要的数据结构类
//点的类
class Point
{
public:
float x;
float y;
float z;
Point();
~Point();
};
//y表
class YTable
{
public:
int m_IndexOfPolygon;
float m_Ymax;
YTable * next;
YTable();
YTable(int IndexOfPolygon,float Ymax);
~YTable();
};
//边表
class ET
{
public:
float m_Ymax;
float m_Yminx;
float m_Yminz;
float m_DeltaX;
ET *next;
ET();
~ET();
};
//活性边对表
class AET
{
public:
float m_XL;
float m_DeltaXL;
float m_Lmax;
float m_XR;
float m_DeltaXR;
float m_Rmax;
float m_ZL;
int m_PolygonIndex;
float m_DeltaZA;
float m_DettaZB;
AET *next;
AET();
~AET();
};
2.定义我们的扫描线算法的主类
class ScanLine
{
public:
Point pt[MAX_POINT];//存储所有点的信息
int polygon[MAX_POINT][3];//我们的图形是由三角形组成的,保存三角形的顶点编号
int currentPoint;//当前的点的数量
int currentPolygon;//当前三角形的数量
int m_Ymin;//最大的y值
int m_Ymax;//最小的y值
int m_Map[MAX_WIDTH][MAX_LENGTH];//帧缓存
int m_ZB[MAX_WIDTH];//深度缓存
Point color[MAX_POINT];
ScanLine();
~ScanLine();
YTable *m_YTable[MAX_WIDTH];//多边形y表
YTable *m_APT;//活化多边形表
ET *m_ET[MAX_POINT][MAX_LENGTH];//边表
AET *m_AET;//活化边对表
void Draw();
void InitData();//初始化信息,在这里读取我们的点和多边形
void LoadObj();
private:
void CreatYTable();//创建y表
void FindYminAndYmax();//设置m_Ymin和m_Ymax的值
void CalculateNormal(int cntOfPolygon,float normal[]);
};
3.接下来就是按顺序执行我们的算法流程,首先读取obj文件到点和多边形里面
这里我的obj的读法比较简单,只考虑了点和面,发现和纹理等我都没有考虑。
值得注意的是,我们需要的坐标范围是1024*768
因此,当obj文件中的文件坐标过于小或者存在负的时候,需要自行对坐标进行方法以及平移处理
下面是放大100倍的情况,用于绘制后面的球,完整代码是不放大的情况,用来绘制海豚
if (cnt == 0)
pt[currentPoint].x = (atof(strTemp))*100+1024/2;
else if (cnt == 1)
pt[currentPoint].y = (atof(strTemp))*100+768/2;
void ScanLine::LoadObj()
{
FILE *fp;
int index;
printf("请输入绘制的图形序号1:茶壶 2:海豚 3:球 4:花环\n");
scanf("%d", &index);
if(index == 1)
fp = fopen("teapot.obj","r");
else if(index ==2)
fp = fopen("dolphins.obj", "r");
else if (index == 3)
fp = fopen("sphere.obj", "r");
else if (index == 4)
fp = fopen("torus.obj", "r");
char str[100];
char strTemp[100];
int cnt;
int indexOfstrTemp;
if (!fp)
printf("ERROR");
else
{
while (fgets(str, 999, fp) != NULL)
{
cnt = 0;
indexOfstrTemp = 0;
if (str[0] == 'v'&&str[1]!='n'&&str[1]!='t')
{
int i = 2;
if (str[i] == ' ')
i = 3;
for (; ;i++)
if (str[i] == ' '|| str[i]=='\0')
{
strTemp[indexOfstrTemp] = '\0';
indexOfstrTemp = 0;
if (cnt == 0)
pt[currentPoint].x = (atof(strTemp))+1024/2;
else if (cnt == 1)
pt[currentPoint].y = (atof(strTemp))+768/2;
else
{
pt[currentPoint].z = atof(strTemp);
currentPoint++;
}
cnt = (cnt + 1) % 3;
if (str