龙空技术网

3D渲染,扫描线算法ZBuffer

小芒果闲聊 147

前言:

此时姐妹们对“多边形的扫描线连贯算法”都比较珍视,咱们都需要学习一些“多边形的扫描线连贯算法”的相关知识。那么小编同时在网摘上网罗了一些关于“多边形的扫描线连贯算法””的相关内容,希望咱们能喜欢,朋友们快快来学习一下吧!

数据结构:

CPoint3D: 3维点类

CPolygon: 多边形类

CEdge: 边类

CActiveEdge: 活化边类

CScanLineZbufferProcess: 扫描线ZBuffer算法实现类,包括3ds文件加载,旋转,扫描过程,显示等。

CPoint3D

class CPoint3D{public:    CPoint3D(void);    CPoint3D(double a,double b,double c);    ~CPoint3D(void);    CPoint3D(CPoint3D&rth);    CPoint3D&operator=(CPoint3D&rth);    CPoint GetPoint2D();public:    double x;    double y;    double z;    };CPoint3D::CPoint3D(void){    x=y=z=0;}CPoint3D::CPoint3D(double a,double b,double c){    x=a;y=b;z=c;}CPoint3D::CPoint3D(CPoint3D&rth){    x=rth.x;    y=rth.y;    z=rth.z;}CPoint3D& CPoint3D::operator=(CPoint3D&rth){        x=rth.x;        y=rth.y;        z=rth.z;        return *this;}CPoint CPoint3D::GetPoint2D(){        CPoint p(x,y);        return p;}CPoint3D::~CPoint3D(void){}
CEdge 类
class CEdge{public:    CEdge(void);    CEdge(CEdge &rth);    ~CEdge(void);public:    CEdge&operator=(CEdge &rth);    void Points2Edge(CPoint3D p1, CPoint3D p2);public:    double x;//边的上端点x的坐标    double dx;//相邻两条扫描线交点的x坐标差dx (-1/k)    int dy;//边跨越的扫描线数目    int id;//边所属多边形的编号    int yMax;//    CEdge *next;};CEdge::CEdge(void){    x =0;    dx = 0;    dy = 0;    id =-1;    next = NULL;    yMax = -100000;} CEdge::CEdge(CEdge &rth){    x = rth.x;    dx = rth.dx;    dy = rth.dy;    id = rth.id;    next = rth.next;    yMax = rth.yMax;}CEdge& CEdge::operator=(CEdge &rth){    x = rth.x;    dx = rth.dx;    dy = rth.dy;    id = rth.id;    next = rth.next;    yMax = rth.yMax;    return *this;}CEdge::~CEdge(void){    if(next)        delete next;}void CEdge::Points2Edge(CPoint3D p1, CPoint3D p2){    /*CPoint3D topPoint = p1;    yMax = p1.y;    dy = abs(p1.y-p2.y);*/        dy = abs(p1.y-p2.y);    if(p1.y>p2.y)    {//p1是TOP point        yMax = p1.y;        x = p1.x;        if(dy!=0)        {            dx = (p2.x-p1.x)/(p1.y-p2.y);        }    }    else    {                //p2是TOP point        yMax = p2.y;        x = p2.x;        if(dy!=0)        {            dx = (p1.x-p2.x)/(p2.y-p1.y);        }    }    dy+=1;}
CEdgeList
class CEdgeList{public:    CEdgeList(void);    ~CEdgeList(void);public:    int ymax;    CEdge *head;};CEdgeList::CEdgeList(void){    ymax = -1;    head= NULL;}CEdgeList::~CEdgeList(void){}
CActiveEdge
class CActiveEdge{public:    CActiveEdge(void);    ~CActiveEdge(void);public:    double xl;//左交点的x坐标    double dxl;//(左交点边上)两相邻扫描线交点的x坐标之差    int dyl;//以和左交点所在边相交的扫描线数为初值,    double xr;//右交点的x坐标    double dxr;//(右交点边上)两相邻扫描线交点的x坐标之差    int dyr;//以和右交点所在边相交的扫描线数为初值,    double zl;//左交点处多边形所在平面的深度值;    double dzx;//沿扫描线向右走过一个像素时,多边形所在平面的深度增量。对于平面方程,dzx=-a/c(c≠0);    double dzy;//沿y方向向下移过一根扫描线时,多边形所在平面的深度增量。对于平面方程,dzy=b/c(c≠0);    int id;//交点对所在的多边形的编号;    CActiveEdge *next;};CActiveEdge::CActiveEdge(void){    dxl =0;    dxr=0;    dyl=0;    dyr=0;    dzx=0;    dzy=0;    xl=0;    xr=0;    zl=0;    next =NULL;    id =-1;}CActiveEdge::~CActiveEdge(void){}
CPolygon
//这里的多边形都是三角形,方便计算class CPolygon{public:    CPolygon(void);    CPolygon(CPolygon &rth);    void Point2Face(CPoint3D p1, CPoint3D p2, CPoint3D p3);    void Point2Face(CPoint3D *p,int npoints);    void get_dy();    CEdge* getEdgeList();//获取边表    void   ClearHorizontalEdge();//清除水平边.平行X的边    ~CPolygon(void);public:    CPolygon&operator=(CPolygon &rth);public:    double a,b,c,d;//多边形所在平面的方程系数ax+by+cz+d=0    int id;//多边形的编号    int dy;//多边形跨越的扫描线数目    COLORREF color;//多边形的颜色        int yMax;    int nPoints;//点数    CPolygon *next;    CPoint3D *point;//按顺序的点,要求前三个不能是共线的点};#include "StdAfx.h"#include "Polygon.h"CPolygon::CPolygon(void){    a = 0;    b = 0;    c = 0;    d = 0;    id =-1;    dy = 0;    color = RGB(255,255,255);//默认底色为白    next = NULL;    nPoints = 0;    yMax = -100000;}CPolygon::CPolygon(CPolygon &rth){    a = rth.a;    b = rth.b;    c = rth.c;    d = rth.d;    id = rth.id;    dy = rth.dy;    color = rth.color;    next = rth.next;}CPolygon& CPolygon::operator=(CPolygon &rth){    a =rth.a;    b =rth.b;    c =rth.c;    d = rth.d;    id = rth.id;    dy = rth.dy;    color = rth.color;    point = rth.point;    nPoints = rth.nPoints;    next = rth.next;    return *this;}//三点不共线下求平面方程参数void CPolygon::Point2Face(CPoint3D p1, CPoint3D p2, CPoint3D p3){        double x1 = p1.x, y1 = p1.y, z1 = p1.z;    double x2 = p2.x, y2 = p2.y, z2 = p2.z;    double x3 = p3.x, y3 = p3.y, z3 = p3.z;    a = (y2-y1)*(z3-z1)-(y3-y1)*(z2-z1);    b = (x3-x1)*(z2-z1)-(x2-x1)*(z3-z1);    c = (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1);    d = -(a*x1+b*y1+c*z1);}//void CPolygon::Point2Face(CPoint3D *p,int npoints){    point = p;    nPoints = npoints;    Point2Face(p[0],p[1],p[2]);}//求出dyvoid CPolygon::get_dy(){   CPoint3D *p  = point;   int yMin  = 100000;   for(int i=0;i<nPoints;i++)   {       CPoint3D *tp = p++;       if(yMax < tp->y)           yMax = tp->y;       if(yMin>tp->y)           yMin = tp->y;   }   dy = yMax - yMin + 1;}//获取边表CEdge* CPolygon::getEdgeList(){    CEdge* pHead = NULL;// = new CEdge();    /*pHead->Points2Edge(point[0], point[1]);    pHead->id = id;*/    CEdge* pOld = NULL;// = pHead;    for(int i=0;i<nPoints;i++)    {        int j = (i+1)%nPoints;        if(point[i].y== point[j].y)//水平边不加入边表            continue;        CEdge* pt = new CEdge();        pt->Points2Edge(point[i], point[j]);        pt->id = id;        pt->next = NULL;        if(pHead==NULL)        {            pHead = pt;            pOld =  pt;        }        else        {            pOld->next = pt;            pOld = pt;        }    }    return pHead;}void CPolygon::ClearHorizontalEdge(){}CPolygon::~CPolygon(void){    if(next)        delete next;}

CPolygonList

#pragma once#include "Polygon.h"class CPolygonList{public:    CPolygonList(void);    ~CPolygonList(void);public:    int yMax;//多边形的最大y坐标    CPolygon *head;};CPolygonList::CPolygonList(void){    yMax = -1;    head = NULL;}CPolygonList::~CPolygonList(void){}
CScanLineZbufferProcess
class CScanLineZbufferProcess{public:    CScanLineZbufferProcess(void);    ~CScanLineZbufferProcess(void);public:    int nWidth,nHeight;//显示屏幕的尺寸    CPaintDC *pDC;    CPolygonList *PolygonList;//分类的多边形表    CEdgeList *EdgeList;//分类边表    CPolygonList *ActivePolygonList;//活化分类的多边形表    CActiveEdge *ActiveEdgeList;//活化分类边表    COLORREF *FrameBuffer;//帧缓冲器    double *ZBuffer;//z缓冲器    COLORREF BackGroundColor;//背景色    double minZ;//最小z值public:    void InitBuffer(int width,int height,CPaintDC *pdc);    //void InitPolygonListEdgeList();        void SortEdge(CEdge* pEdge);    bool AddActivePolygonList(int y);//添加新多边形进活化多边形表    void UpdateActivePolygonList();//更新多边形进活化多边形表    bool AddActiveEdgeList(int y);//添加新边堆到活化边表    void UpdateActiveEdgeList( int y);//更新新边对中的一边,由于一边结束,而多边形还在扫描区域,删除一条边,加入新边    bool IsInActivePolygonList(int id);//指定的多边形是否在活化多边形表中    COLORREF GetPolygonColor(int id);//获取多边形的颜色    void UpdateZBufferColor(int y);    void Scan();    void Show();    void OnX(double angle, CPoint3D *p);    void OnY(double angle, CPoint3D *p);        void AddFace(CPoint3D *pFacePoint,int npoints, COLORREF faceColor);//增加面    int faceid;public:    Lib3dsFile *model;    bool Load3ds(char *argv);//加载3ds文件    void render_node(Lib3dsNode *node);     bool bInit;    float m_Scale;//缩放比例    float m_Max;    void getScalFor3dsFile(char *argv);    void get_nodeMax(Lib3dsNode *node) ;    void Clear();//清除所有数据    bool m_bYZ;    bool m_EdgeShow;    double angle_x;//绕x轴旋转角度    double angle_y;//绕y轴旋转角度
#include "StdAfx.h"#include "ScanLineZbufferProcess.h"#include <math.h>CScanLineZbufferProcess::CScanLineZbufferProcess(void){    faceid = -1;    BackGroundColor = RGB(255,255,255);//背景为白色    minZ = -100000;    bInit = false;    m_bYZ = false;//false:Y轴在上,Z轴为深度  true:Z轴在上,Y轴为深度    angle_x = 0.0;    angle_y = 0.0;    m_EdgeShow = false;}CScanLineZbufferProcess::~CScanLineZbufferProcess(void){    Clear();}//清除所有数据void CScanLineZbufferProcess::Clear(){    for(int y = nHeight/2; y>-nHeight/2;y--)//从上往下扫描    {        try        {            //删除多边形表            CPolygon *oldPolygon = PolygonList[y+nHeight/2].head;//y是当前的扫描线y值            if(oldPolygon)                delete oldPolygon;            PolygonList[y+nHeight/2].head = NULL;                        CEdge* tpEdge = EdgeList[y+nHeight/2].head;//删除边表            if(tpEdge)                delete tpEdge;            EdgeList[y+nHeight/2].head = NULL;                    }        catch(...)        {        }    }    //清除FrameBuffer、ZBuffer    int nCount = nWidth*nHeight;    for(int i=0;i<nCount;i++)    {        FrameBuffer[i] = BackGroundColor;        ZBuffer[i] = minZ;    }    faceid = -1;    angle_x = 0.0;    angle_y = 0.0;}//初始化buffervoid CScanLineZbufferProcess::InitBuffer(int width,int height,CPaintDC *pdc){    faceid = -1;    nWidth = width;    nHeight = height;    pDC = pdc;        int nCount = nWidth*nHeight;    FrameBuffer = new COLORREF[nCount];    ZBuffer = new double[nCount];    for(int i=0;i<nCount;i++)    {        FrameBuffer[i] = BackGroundColor;        ZBuffer[i] = minZ;    }    PolygonList = new CPolygonList[nHeight+1];    EdgeList = new CEdgeList[nHeight+1];    bInit = true;}//增加面void CScanLineZbufferProcess::AddFace(CPoint3D *pFacePoint,int npoints, COLORREF faceColor){    CPolygon *face = new CPolygon();    face->Point2Face(pFacePoint, 3);    face->id = ++faceid;    face->color = faceColor;    face->get_dy();    if(face->c!=0)    {//与xoy面没有投影的面去掉        face->next = PolygonList[face->yMax+nHeight/2].head;        PolygonList[face->yMax+nHeight/2].head = face;//多边形表        CEdge *pEdge = face->getEdgeList();//边表        SortEdge(pEdge);    }}//将边按照yMax存入相应的边表void CScanLineZbufferProcess::SortEdge(CEdge* pEdge){    CEdge* tpEdge = pEdge;    do    {        CEdge* tOldpEdge = tpEdge->next;        if(tpEdge->yMax+nHeight/2<=nHeight)//去除Ymax超过边界的值        {            tpEdge->next = EdgeList[tpEdge->yMax+nHeight/2].head;            EdgeList[tpEdge->yMax+nHeight/2].head = tpEdge;//坐标原点在画板中心            EdgeList[tpEdge->yMax+nHeight/2].ymax = tpEdge->yMax;        }        tpEdge = tOldpEdge;            }while(tpEdge);}//step1 添加活化多边形表bool CScanLineZbufferProcess::AddActivePolygonList(int y){    if(PolygonList[y+nHeight/2].head!=NULL)    {        CPolygon *tPolygon = ActivePolygonList->head;        while(tPolygon && tPolygon->next)        {            tPolygon = tPolygon->next;        }        CPolygon *oldPolygon = PolygonList[y+nHeight/2].head;//y是当前的扫描线y值        while(oldPolygon)        {            if(oldPolygon->c!=0)            {                CPolygon *tnewPolygon = new CPolygon();                *tnewPolygon = *oldPolygon;                if(ActivePolygonList->head==NULL)                {                    ActivePolygonList->head = tnewPolygon;                }                else                {                    tPolygon->next = tnewPolygon;                 }                tPolygon = tnewPolygon;            }            oldPolygon = oldPolygon->next;        }        return true;//有新多边形加入    }    return false;}//更新活化多边形表,删除不再扫描区域的多边形void CScanLineZbufferProcess::UpdateActivePolygonList(){    //活化多边形表中的元素修改        CPolygon *tPolygon = ActivePolygonList->head;        CPolygon *tOldPolygon = tPolygon;        while(tPolygon)        {                        tPolygon->dy -=1;//每一个多边形的dy:dy = dy-1                        if(tPolygon->dy<=0)//当dy <=0时,该多边形要从多边形活化表中删除            {                if(ActivePolygonList->head==tPolygon)                    ActivePolygonList->head = tPolygon->next;//删除第一个节点                else                {                    tOldPolygon->next = tPolygon->next;                }            }            else            {//不删除,才需更新上一个指针              tOldPolygon = tPolygon;            }            tPolygon = tPolygon->next;        }}//有新多边形加入时添加新边对到活化边表bool CScanLineZbufferProcess::AddActiveEdgeList(int y){    CPolygon* tPolygon = PolygonList[y+nHeight/2].head;    while(tPolygon)    {        int i=0;        CEdge* tpEdge = EdgeList[y+nHeight/2].head;//这里的多边形都是三角形,方便计算        CActiveEdge* tActiveEdge = new CActiveEdge();        while(tpEdge)        {            if(tpEdge->id==tPolygon->id)            {                if(tpEdge->dy<=1)//是水平线                {                  tpEdge = tpEdge->next;                  continue;                }                if(i==0)                {                    tActiveEdge->id = tPolygon->id;                    tActiveEdge->dxl = tpEdge->dx;                    tActiveEdge->dyl = tpEdge->dy;                    tActiveEdge->xl = tpEdge->x;                    tActiveEdge->dzx = -(tPolygon->a / tPolygon->c);                    tActiveEdge->dzy = tPolygon->b / tPolygon->c;                    tActiveEdge->zl = -( tPolygon->a * tpEdge->x  + tPolygon->b*y +tPolygon->d )/tPolygon->c;                    i++;                }                else                {                    if((tActiveEdge->xl + tActiveEdge->dxl) > (tpEdge->x+tpEdge->dx))                    {//左右两边交换                        tActiveEdge->dxr = tActiveEdge->dxl;                        tActiveEdge->dyr = tActiveEdge->dyl;                        tActiveEdge->xr = tActiveEdge->xl;                        tActiveEdge->dxl = tpEdge->dx;                        tActiveEdge->dyl = tpEdge->dy;                        tActiveEdge->xl = tpEdge->x;                    }                    else                    {                        tActiveEdge->dxr = tpEdge->dx;                        tActiveEdge->dyr = tpEdge->dy;                        tActiveEdge->xr = tpEdge->x;                    }                                        /******************加入活化表*****************************/                    if(ActiveEdgeList==NULL||ActiveEdgeList->id==-1)                        ActiveEdgeList = tActiveEdge;                    else                    {                        tActiveEdge->next = ActiveEdgeList;//插入表头                        ActiveEdgeList = tActiveEdge;                    }                    /*******************end 加入活化表**************************/                    i = 0;                    break;//寻找下一个多边形                }            }            tpEdge = tpEdge->next;        }        tPolygon = tPolygon->next;            }    return true;}//更新活化边表void CScanLineZbufferProcess::UpdateActiveEdgeList(int y){    CActiveEdge *tActiveEdgeList = ActiveEdgeList;    CActiveEdge *tOldActiveEdgeList = tActiveEdgeList;    while(tActiveEdgeList&&tActiveEdgeList->id!=-1)    {        tActiveEdgeList->dyl -=1; tActiveEdgeList->dyr -=1;                tActiveEdgeList->xl +=tActiveEdgeList->dxl; tActiveEdgeList->xr +=tActiveEdgeList->dxr;//边和下一条扫描线交点的x值        tActiveEdgeList->zl += tActiveEdgeList->dzx * tActiveEdgeList->dxl + tActiveEdgeList->dzy;        //若dyl或dyr小于0,相应的边就要从一个边对        if(tActiveEdgeList->dyl<=0||tActiveEdgeList->dyr<=0)        {            if(IsInActivePolygonList(tActiveEdgeList->id))            {                tOldActiveEdgeList = tActiveEdgeList;//保存为前向节点                 //还在活化多边形表中,选择修改边对,删除原来的,加入新边                CEdge *tpEdge = EdgeList[y+nHeight/2].head;                while(tpEdge)                {                    if(tpEdge->id==tActiveEdgeList->id)                    {                        if(tActiveEdgeList->dyl<=0)                        {                            //更新左边                            tActiveEdgeList->dxl = tpEdge->dx;                            tActiveEdgeList->dyl = tpEdge->dy;                            tActiveEdgeList->xl = tpEdge->x;                        }                        else                        {//更新右边                            tActiveEdgeList->dxr = tpEdge->dx;                            tActiveEdgeList->dyr = tpEdge->dy;                            tActiveEdgeList->xr = tpEdge->x;                        }                        break;                    }                    tpEdge = tpEdge->next;                }                            }            else            {                //删除该边对                if(tActiveEdgeList == ActiveEdgeList)                {                    //表头                    ActiveEdgeList = tActiveEdgeList->next;                    tOldActiveEdgeList = ActiveEdgeList;                                     }                else                {                    tOldActiveEdgeList->next = tActiveEdgeList->next;                }            }        }        else        {            tOldActiveEdgeList = tActiveEdgeList;//保存为前向节点         }        tActiveEdgeList = tActiveEdgeList->next;//下一个边对    }}//获取多边形颜色值COLORREF CScanLineZbufferProcess::GetPolygonColor(int id){     CPolygon *tPolygon = ActivePolygonList->head;    while(tPolygon)    {        if(tPolygon->id == id)        {            return tPolygon->color;        }        tPolygon = tPolygon->next;    }    return this->BackGroundColor;//没找到返回背景色}//指定的多边形是否在活化多边形表中bool CScanLineZbufferProcess::IsInActivePolygonList(int id){     CPolygon *tPolygon = ActivePolygonList->head;    while(tPolygon)    {        if(tPolygon->id == id)        {            return true;        }        tPolygon = tPolygon->next;    }    return false;}//step2 增量式的深度更新void CScanLineZbufferProcess::UpdateZBufferColor(int y){    CActiveEdge *tActiveEdgeList = ActiveEdgeList;    while(tActiveEdgeList && tActiveEdgeList->id!=-1)    {        double Zx = tActiveEdgeList->zl;        for(int x = tActiveEdgeList->xl;x<=tActiveEdgeList->xr;x++)        {            if(abs(x)>nWidth/2)            {                Zx += tActiveEdgeList->dzx;                continue;            }            int index = (nHeight/2-y)*nWidth + nWidth/2+x;                        if(Zx > ZBuffer[index])            {                ZBuffer[index] = Zx;//更新深度值                if(m_EdgeShow)                {                    if( x == (int)tActiveEdgeList->xl || x==(int)tActiveEdgeList->xr)                        FrameBuffer[index] = RGB(255,255,255);//边界线都是白色                    else                    {                        FrameBuffer[index] = GetPolygonColor(tActiveEdgeList->id);//更新颜色                    }                }                else                {                   FrameBuffer[index] = GetPolygonColor(tActiveEdgeList->id);//更新颜色                }            }                        Zx += tActiveEdgeList->dzx;        }        tActiveEdgeList = tActiveEdgeList->next;//下一个边对    }}//扫描void CScanLineZbufferProcess::Scan(){    ActivePolygonList = new CPolygonList();//活化多边形表    ActiveEdgeList = new CActiveEdge();//活化边表    for(int y = nHeight/2; y>-nHeight/2;y--)//从上往下扫描    {        try        {            //step1 添加新的多边形进活化多边形表,有新多变形加入时添加边对进活化边表            AddActivePolygonList(y);            AddActiveEdgeList(y);            //step2 增量式的深度更新            UpdateZBufferColor(y);                        //活化多边形表中的元素修改            UpdateActivePolygonList();            //step3 活化边表中的元素修改:修改后的活化边表是下一条扫描线的活化边表            UpdateActiveEdgeList(y);        }        catch(...)        {            AfxMessageBox(_T("出错!"));        }    }}//显示FrameBuffer图形void CScanLineZbufferProcess::Show(){//dc 的原点在(nWidth/2,nHeight/2)]    for(int y=nHeight/2; y>-nHeight/2; y--)    {        for(int x=-nWidth/2; x<nWidth/2; x++)        {            int index = (nHeight/2-y)*nWidth + nWidth/2+x;            pDC->SetPixel(x,y,FrameBuffer[index]);        }    }        }void CScanLineZbufferProcess::OnX(double angle, CPoint3D *p){            float x=p->x;        float y=cos(angle)*p->y-sin(angle)*p->z;        float z=sin(angle)*p->y+cos(angle)*p->z;        *p = CPoint3D((int)x,(int)y,(int)z);    }void CScanLineZbufferProcess::OnY(double angle, CPoint3D *p){        float y=p->y;        float x=cos(angle)*p->x-sin(angle)*p->z;        float z=sin(angle)*p->x+cos(angle)*p->z;        *p = CPoint3D((int)x,(int)y,(int)z);}/***************************************load 3ds********************************************/void CScanLineZbufferProcess::render_node(Lib3dsNode *node) {    Lib3dsNode      *p;    Lib3dsMesh      *mesh;    Lib3dsFace      *face;    Lib3dsMaterial  *mat;    Lib3dsMeshInstanceNode *meshData;    // 递归       for (p=node->childs; p!=0; p=p->next)    {        render_node(p);       }    if (strcmp(node->name,"$$$DUMMY")==0)//检查是否是mesh    {        return;    }    if (!node->user_id)    {        mesh = lib3ds_file_mesh_for_node(model, node);                 if (!mesh || !mesh->vertices) return;        COLORREF faceColor = BackGroundColor;        for (int fi=0; fi<mesh->nfaces; ++fi)        {            face = &(mesh->faces[fi]);            mat = 0;            CPoint3D pFacePoint[3];            for(int i=0;i<3;i++)            {                float a = mesh->vertices[face->index[i]][0]/m_Scale;                   float b = mesh->vertices[face->index[i]][1]/m_Scale;                 float c = mesh->vertices[face->index[i]][2]/m_Scale;                 if(abs(a)>=nWidth/2||abs(b)>=nHeight/2)                    goto next;                if(!this->m_bYZ)                {                   pFacePoint[i] = CPoint3D(a,b,c);                }                else                {                    pFacePoint[i] = CPoint3D(a,c,b);//YZ轴对调                }                OnX(this->angle_x, &pFacePoint[i]);//绕x轴旋转                OnY(this->angle_y, &pFacePoint[i]);//绕y轴旋转            }            if (face->material>=0 && face->material<model->nmaterials)            {                mat=model->materials[face->material];                faceColor = RGB(mat->diffuse[0]*255, mat->diffuse[1]*255, mat->diffuse[2]*255);            }            else            {                faceColor = BackGroundColor;            }            AddFace(pFacePoint,3, faceColor);next:     continue;        }    }}//加载3ds文件bool CScanLineZbufferProcess::Load3ds(char *argv){    getScalFor3dsFile(argv);//计算缩放比例         model = lib3ds_file_open(argv);//加载点位     if (!model) {        //fprintf(stderr, "***ERROR***\nLoading file failed: \n");        //exit(1);         AfxMessageBox(_T("打开3ds文件出错\n"));        return false;    }     Lib3dsNode *nod;     for (nod=model->nodes; nod!=NULL; nod=nod->next)     {         if(nod->type==LIB3DS_NODE_MESH_INSTANCE)         {            render_node(nod);         }     }        lib3ds_file_free(model);     return true;}/*************************************end load3ds****************************************//***************************************获取3ds文件的缩放比例**********************************************/void CScanLineZbufferProcess::getScalFor3dsFile(char *argv){    m_Scale = 1.0;//默认是1    m_Max = 0;    model = lib3ds_file_open(argv);     if (!model) {        //fprintf(stderr, "***ERROR***\nLoading file failed: \n");        //exit(1);         AfxMessageBox(_T("打开3ds文件出错\n"));        return;    }     Lib3dsNode *nod;     for (nod=model->nodes; nod!=NULL; nod=nod->next)     {         if(nod->type==LIB3DS_NODE_MESH_INSTANCE)         {            get_nodeMax(nod);         }     }        lib3ds_file_free(model);     if(m_Max!=0)     {        m_Scale = 2*m_Max / (nHeight-5);     }}void CScanLineZbufferProcess::get_nodeMax(Lib3dsNode *node) {    Lib3dsNode      *p;    Lib3dsMesh      *mesh;    Lib3dsFace      *face;    Lib3dsMaterial  *mat;    Lib3dsMeshInstanceNode *meshData;    // 递归       for (p=node->childs; p!=0; p=p->next)    {        get_nodeMax(p);       }    if (strcmp(node->name,"$$$DUMMY")==0)//检查是否是mesh    {        return;    }    if (!node->user_id)    {        mesh = lib3ds_file_mesh_for_node(model, node);                 if (!mesh || !mesh->vertices) return;        COLORREF faceColor = BackGroundColor;        for (int fi=0; fi<mesh->nfaces; ++fi)        {            face = &(mesh->faces[fi]);            mat = 0;            CPoint3D pFacePoint[3];            for(int i=0;i<3;i++)            {                float a = mesh->vertices[face->index[i]][0];                   float b = mesh->vertices[face->index[i]][1];                 float c = mesh->vertices[face->index[i]][2];                     if(abs(a)>m_Max)                    m_Max = abs(a);                if(abs(b)>m_Max)                    m_Max = abs(b);                if(abs(c)>m_Max)                    m_Max = abs(c);            }                    }    }}/*****************************************end********************************************/

0人点赞

图形学

标签: #多边形的扫描线连贯算法