画个梨(JAVA)

半边数据结构存储图型,平面、平滑明暗处理

面法向量:

void Mesh3D::ComputePerFaceNormal(HE_face* hf)
{
    //图形学课程上机作业
    //请在此处添加计算面法向代码
    point a, b, c;
    a = hf->pedge_->pvert_->position();//得到三角形三点
    b = hf->pedge_->pnext_->pvert_->position();
    c = hf->pedge_->pnext_->pnext_->pvert_->position();
    point m1, m2;//得到两条向量
    m1 = b - a;
    m2 = c - a;
    hf->normal_[0] = m1[1] * m2[2] - m1[2] * m2[1];//叉乘得到面法向量
    hf->normal_[1] = m1[2] * m2[0] - m2[2] * m1[0];
    hf->normal_[2] = m1[0] * m2[1] - m2[0] * m1[1];
    hf->normal_[0] = hf->normal_[0] / (sqrt(hf->normal_[0] * hf->normal_[0] + hf->normal_[1] * hf->normal_[1] + hf->normal_[2] * hf->normal_[2]));//进行单位化
    hf->normal_[1] = hf->normal_[1] / (sqrt(hf->normal_[0] * hf->normal_[0] + hf->normal_[1] * hf->normal_[1] + hf->normal_[2] * hf->normal_[2]));
    hf->normal_[2] = hf->normal_[2] / (sqrt(hf->normal_[0] * hf->normal_[0] + hf->normal_[1] * hf->normal_[1] + hf->normal_[2] * hf->normal_[2]));
}

 点法向量:

void Mesh3D::ComputePerVertexNormal(HE_vert* hv)
{
    //图形学课程上机作业
    //请在此处添加计算点法向代码
    HE_edge* firstedge = hv->pedge_;//第一条边
    HE_face* face_ = firstedge->pface_;//第一个面
    Mesh3D::ComputePerFaceNormal(face_);//调用函数计算这个面的法向量
    hv->normal_[0] = 0;//初始化为0
    hv->normal_[1] = 0;
    hv->normal_[2] = 0;
    float total = 0;//这个顶点一共多少个面相邻
    for (int i = 0; i < 3; i++)
    {
        hv->normal_[i] = hv->normal_[i] + face_->normal_[i];//加上顶点相邻面的法向量
    }
    total++;
    HE_edge* nextedge = firstedge->ppair_->pnext_;//下一条边
    while (nextedge != firstedge)
    {
        face_ = nextedge->pface_;
        Mesh3D::ComputePerFaceNormal(face_); //调用函数计算这个面的法向量
        for (int i = 0; i < 3; i++)
        {
            hv->normal_[i] = hv->normal_[i] + face_->normal_[i];//加上顶点相邻面的法向量
        }
        total++;
        nextedge = nextedge->ppair_->pnext_;//下一条边
    }
    for (int i = 0; i < 3; i++)
    {
        hv->normal_[i] = hv->normal_[i] / total;//取平均数
    }
}

setup: 读取文件,梨材质设置:

void setup(void)
{
    bool is_open = ptr_mesh_->LoadFromOBJFile("gourd.obj");//读取obj文件
    glEnableClientState(GL_VERTEX_ARRAY);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST); // Enable depth testing.

    // Turn on OpenGL lighting.
    glEnable(GL_LIGHTING);

    // Material property vectors.
    float matAmbAndDif[] = { 1.0, 1.0, 0.0, 1.0 };//梨本身的颜色:黄色
    float matSpec[] = { 1.0, 1.0, 1,0, 1.0 };
    float matShine[] = { 50.0 };

    // Material properties of pair.
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matAmbAndDif);
    glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
    glMaterialfv(GL_FRONT, GL_SHININESS, matShine);

    // Cull back faces.
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);

 drawing:设置灯光,画图渲染

// Drawing routine.
void drawScene(void)
{
    // Light property vectors.
    float lightAmb[] = { 0.0, 0.0, 0.0, 1.0 };
    float lightDifAndSpec0[] = { d, d, d, 1.0 };
    float lightPos0[] = { 0.0, 0.0, 3.0, p };
    float lightDifAndSpec1[] = { 0.0, 1.0, 0.0, 1.0 };
    float lightPos1[] = { 1.0, 2.0, 0.0, 1.0 };
    float globAmb[] = { m, m, m, 1.0 };

    // Light0 properties.
    glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDifAndSpec0);
    glLightfv(GL_LIGHT0, GL_SPECULAR, lightDifAndSpec0);

    // Light1 properties.
    glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmb);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDifAndSpec1);
    glLightfv(GL_LIGHT1, GL_SPECULAR, lightDifAndSpec1);

    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globAmb); // Global ambient light.
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, localViewer); // Enable local viewpoint

    // Turn lights off/on.
    if (light0On) glEnable(GL_LIGHT0); else glDisable(GL_LIGHT0);
    if (light1On) glEnable(GL_LIGHT1); else glDisable(GL_LIGHT1);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();

    // Light quadratic attenuation factor.
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, t);
    glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, t);

    writeData();

    gluLookAt(0.0, 3.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    // Draw light source spheres (or arrow) after disabling lighting.
    glDisable(GL_LIGHTING);

    // Light0 positioned and sphere positioned in case of positional light
    // and arrow in case of directional light.
    glPushMatrix();
    glRotatef(xAngle, 1.0, 0.0, 0.0); // Rotation about x-axis.
    glRotatef(yAngle, 0.0, 1.0, 0.0); // Rotation about y-axis.
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
    glTranslatef(lightPos0[0], lightPos0[1], lightPos0[2]);
    glColor3f(d, d, d);
    if (light0On)
    {
        if (p) glutWireSphere(0.05, 8, 8); // Sphere at positional light source.
        else //按方向键旋转白光源
        {
            glLineWidth(3.0);
            glBegin(GL_LINES);
            glVertex3f(0.0, 0.0, 0.25);
            glVertex3f(0.0, 0.0, -0.25);
            glVertex3f(0.0, 0.0, -0.25);
            glVertex3f(0.05, 0.0, -0.2);
            glVertex3f(0.0, 0.0, -0.25);
            glVertex3f(-0.05, 0.0, -0.2);
            glEnd();
            glLineWidth(1.0);
        }
    }
    glPopMatrix();

    // Light1 and its sphere positioned.
    glPushMatrix();
    glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
    glTranslatef(lightPos1[0], lightPos1[1], lightPos1[2]);
    glColor3f(0.0, 1.0, 0.0);
    if (light1On) glutWireSphere(0.05, 8, 8);
    glPopMatrix();

    glEnable(GL_LIGHTING);

    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();
    gluLookAt(0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glColor3f(0.0, 0.7, 6.0);

    // Rotate scene.
    glRotatef(Zangle, 0.0, 0.0, 1.0);
    glRotatef(Yangle, 0.0, 1.0, 0.0);
    glRotatef(Xangle, 1.0, 0.0, 0.0);

    // Draw the object mesh.
    for (int i = 0; i < ptr_mesh_->num_of_face_list(); i = i++)
    {
        point first, second, third;
        first = ptr_mesh_->get_face(i)->pedge_->pvert_->position();//第一个顶点
        second = ptr_mesh_->get_face(i)->pedge_->pnext_->pvert_->position();//第二个点
        third = ptr_mesh_->get_face(i)->pedge_->pnext_->pnext_->pvert_->position();//第三个点
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glBegin(GL_TRIANGLES);//画三角形
        if (change == 0)
        {
            glNormal3fv(ptr_mesh_->get_face(i)->normal_);//平面光照
            glVertex3f(first[0], first[1], first[2]);
            glVertex3f(second[0], second[1], second[2]);
            glVertex3f(third[0], third[1], third[2]);
        }
        else if (change == 1)//平滑光照处理
        {
            glNormal3fv(ptr_mesh_->get_face(i)->pedge_->pvert_->normal_);
            glVertex3f(first[0], first[1], first[2]);
            glNormal3fv(ptr_mesh_->get_face(i)->pedge_->pnext_->pvert_->normal_);
            glVertex3f(second[0], second[1], second[2]);
            glNormal3fv(ptr_mesh_->get_face(i)->pedge_->pnext_->pnext_->pvert_->normal_);
            glVertex3f(third[0], third[1], third[2]);
        }
        glEnd();
    }

    glutSwapBuffers();

}

// Callback routine for non-ASCII key entry.
void specialKeyInput(int key, int x, int y)//根据方向键改变可移动白灯光的位置
{
    if (key == GLUT_KEY_DOWN)
    {
        xAngle++;
        if (xAngle > 360.0) xAngle -= 360.0;
    }
    if (key == GLUT_KEY_UP)
    {
        xAngle--;
        if (xAngle < 0.0) xAngle += 360.0;
    }
    if (key == GLUT_KEY_RIGHT)
    {
        yAngle++;
        if (yAngle > 360.0) yAngle -= 360.0;
    }
    if (key == GLUT_KEY_LEFT)
    {
        yAngle--;
        if (yAngle < 0.0) yAngle += 360.0;
    }
    if (key == GLUT_KEY_PAGE_UP) zMove -= 0.1;
    if (key == GLUT_KEY_PAGE_DOWN) if (zMove < 3.0) zMove += 0.1;
    glutPostRedisplay();
}
//
// OBJmodelViewer.cpp
//
// An object defined in an external Wavefront OBJ file is loaded and displayed. 
// Only vertex and face lines are read. All other lines are ignored. Vertex lines 
// are assumed to have only x, y and z coordinate values. The (optional) w value 
// is ignored if present. Within a face line only vertex indices are read. Texture 
// and normal indices are allowed but ignored. Face lines can have more than three 
// vertices. If a face line has more than three vertices the output is a fan 
// triangulation. Therefore, the mesh generated consists of only triangles.
//
// Interaction:
// Press x, X, y, Y, z, Z to turn the object.
//
// Sumanta Guha.
//

#include <iostream>
#include <sstream>    
#include <string> 
#include <fstream> 
#include <vector>
#include "Mesh3D.h"//头文件,引用Mesh3D.h
#include "Vec.h"//头文件,引用Vec.h
#include <GL/glew.h>
#include <GL/freeglut.h> 
using namespace std;
// Globals.
static std::vector<float> verticesVector; // Vector to read in vertex x, y and z values fromt the OBJ file.
static std::vector<int> facesVector; // Vector to read in face vertex indices from the OBJ file.
static float* vertices = NULL;  // Vertex array of the object x, y, z values.
static int* faces = NULL; // Face (triangle) vertex indices.
static int numIndices; // Number of face vertex indices.
static float Xangle = 0.0, Yangle = 0.0, Zangle = 0.0; // Angles to rotate the object.
int change = 0;//切换平滑着色和平面着色
static int light0On = 1; //白色可移动灯光开光
static int light1On = 1; //绿色灯光开光
static float d = 1.0; // 漫反射和镜面反射白光强度。
static float m = 0.2; // 全局环境白光强度
static int localViewer = 1; // 当地观点?
static float p = 1.0; // 定位灯
static float t = 0.0; // 二次衰减系数。
static float zMove = 0.0; // z方向分量。
static float xAngle = 0.0, yAngle = 0.0; // 白光的旋转角度。
static long font = (long)GLUT_BITMAP_8_BY_13; // 字体选择。
static char theStringBuffer[10]; //字符串缓冲区。

#include "Mesh3D.h"
#include <xutility>

#define SWAP(a,b,T) {T tmp=(a); (a)=(b); (b)=tmp;}
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
int w = 1000, h = 800;//视角高宽
Mesh3D* ptr_mesh_ = new Mesh3D();//新建Mesh3D对象(半边数据结构)

//用于绘制位图字符串的例程
void writeBitmapString(void* font, char* string)
{
    char* c;
    for (c = string; *c != '\0'; c++)
        glutBitmapCharacter(font, *c);
}

//将浮点转换为字符串的例程
void floatToString(char* destStr, int precision, float val)
{
    sprintf(destStr, "%f", val);
    destStr[precision] = '\0';
}

Mesh3D::Mesh3D(void)
{
    // intialization
    pvertices_list_ = NULL;
    pfaces_list_ = NULL;
    pedges_list_ = NULL;

    xmax_ = ymax_ = zmax_ = 1.f;
    xmin_ = ymin_ = zmin_ = -1.f;

    num_components_ = 0;
    average_edge_length_ = 1.f;
}

void Mesh3D::ClearData(void)
{
    ClearVertex();
    ClearEdges();
    ClearFaces();
    edgemap_.clear();

    xmax_ = ymax_ = zmax_ = 1.f;
    xmin_ = ymin_ = zmin_ = -1.f;
}

void Mesh3D::ClearVertex(void)
{

    if (pvertices_list_ == NULL)
    {
        return;
    }
    else
    {
        for (VERTEX_ITER viter = pvertices_list_->begin(); viter != pvertices_list_->end(); viter++)
        {
            if (*viter != NULL)
            {
                delete* viter;
                *viter = NULL;
            }
            else
            {
                // ERROR
            }
        }
        delete pvertices_list_;
        pvertices_list_ = NULL;
    }
}

void Mesh3D::ClearEdges(void)
{
    if (pedges_list_ == NULL)
    {
        return;
    }
    else
    {
        for (EDGE_ITER eiter = pedges_list_->begin(); eiter != pedges_list_->end(); eiter++)
        {
            if (*eiter != NULL)
            {
                delete* eiter;
                *eiter = NULL;
            }
            else
            {
                // ERROR
            }
        }
        delete pedges_list_;
        pedges_list_ = NULL;
    }
}

void Mesh3D::ClearFaces(void)
{
    if (pfaces_list_ == NULL)
    {
        return;
    }
    else
    {
        for (FACE_ITER fiter = pfaces_list_->begin(); fiter != pfaces_list_->end(); fiter++)
        {
            if (*fiter != NULL)
            {
                delete* fiter;
                *fiter = NULL;
            }
            else
            {
                // ERROR
            }
        }
        delete pfaces_list_;
        pfaces_list_ = NULL;
    }
}

HE_vert* Mesh3D::InsertVertex(const Vec3f& v)
{
    HE_vert* pvert = new HE_vert(v);
    if (pvertices_list_ == NULL)
    {
        pvertices_list_ = new std::vector<HE_vert*>;
    }
    pvert->id_ = static_cast<int>(pvertices_list_->size());
    pvertices_list_->push_back(pvert);
    return pvert;
}

HE_edge* Mesh3D::InsertEdge(HE_vert* vstart, HE_vert* vend)
{
    if (vstart == NULL || vend == NULL)
    {
        return NULL;
    }

    if (pedges_list_ == NULL)
    {
        pedges_list_ = new std::vector<HE_edge*>;
    }

    if (edgemap_[PAIR_VERTEX(vstart, vend)] != NULL)
    {
        return edgemap_[PAIR_VERTEX(vstart, vend)];
    }

    HE_edge* pedge = new HE_edge;
    pedge->pvert_ = vend;
    pedge->pvert_->degree_++;
    vstart->pedge_ = pedge;
    edgemap_[PAIR_VERTEX(vstart, vend)] = pedge;

    pedge->id_ = static_cast<int>(pedges_list_->size());
    pedges_list_->push_back(pedge);

    return pedge;
}

HE_face* Mesh3D::InsertFace(std::vector<HE_vert* >& vec_hv)
{
    int vsize = static_cast<int>(vec_hv.size());
    //if (vsize != 3)
    //{
    //    return NULL;
    //}

    if (pfaces_list_ == NULL)
    {
        pfaces_list_ = new std::vector<HE_face*>;
    }

    HE_face* pface = new HE_face;
    pface->valence_ = vsize;
    VERTEX_ITER viter = vec_hv.begin();
    VERTEX_ITER nviter = vec_hv.begin();
    nviter++;

    HE_edge* he1 = NULL, * he2 = NULL;
    std::vector<HE_edge*> vec_edges;
    int i = 0;
    for (i = 0; i < vsize - 1; i++)
    {
        he1 = InsertEdge(*viter, *nviter);
        he2 = InsertEdge(*nviter, *viter);

        if (pface->pedge_ == NULL)
            pface->pedge_ = he1;

        he1->pface_ = pface;
        he1->ppair_ = he2;
        he2->ppair_ = he1;
        vec_edges.push_back(he1);
        viter++, nviter++;
    }

    nviter = vec_hv.begin();

    he1 = InsertEdge(*viter, *nviter);
    he2 = InsertEdge(*nviter, *viter);
    he1->pface_ = pface;
    if (pface->pedge_ == NULL)
        pface->pedge_ = he1;

    he1->ppair_ = he2;
    he2->ppair_ = he1;
    vec_edges.push_back(he1);

    for (i = 0; i < vsize - 1; i++)
    {
        vec_edges[i]->pnext_ = vec_edges[i + 1];
        vec_edges[i + 1]->pprev_ = vec_edges[i];
    }
    vec_edges[i]->pnext_ = vec_edges[0];
    vec_edges[0]->pprev_ = vec_edges[i];

    pface->id_ = static_cast<int>(pfaces_list_->size());
    pfaces_list_->push_back(pface);

    return pface;
}

bool Mesh3D::LoadFromOBJFile(const char* fins)
{
    //    cout << "Loading......." << endl;
    FILE* pfile = fopen(fins, "r");

    char* tok;
    //char *tok_tok;
    char temp[128];

    try
    {
        ClearData();
        //read vertex
        fseek(pfile, 0, SEEK_SET);
        char pLine[512];

        while (fgets(pLine, 512, pfile))
        {
            if (pLine[0] == 'v' && pLine[1] == ' ')
            {
                Vec3f nvv;
                tok = strtok(pLine, " ");
                for (int i = 0; i < 3; i++)
                {
                    tok = strtok(NULL, " ");
                    strcpy(temp, tok);
                    temp[strcspn(temp, " ")] = 0;
                    nvv[i] = (float)atof(temp);
                }
                InsertVertex(nvv);
            }
        }

        //read facets
        fseek(pfile, 0, SEEK_SET);

        while (fgets(pLine, 512, pfile))
        {
            char* pTmp = pLine;
            if (pTmp[0] == 'f')
            {
                std::vector<HE_vert* > s_faceid;

                tok = strtok(pLine, " ");
                while ((tok = strtok(NULL, " ")) != NULL)
                {
                    strcpy(temp, tok);
                    temp[strcspn(temp, "/")] = 0;
                    int id = (int)strtol(temp, NULL, 10) - 1;
                    HE_vert* hv = get_vertex(id);
                    bool findit = false;
                    for (int i = 0; i < (int)s_faceid.size(); i++)
                    {
                        if (hv == s_faceid[i])    //remove redundant vertex id if it exists
                        {
                            //    cout << "remove redundant vertex" << endl;
                            findit = true;
                            break;
                        }
                    }
                    if (findit == false && hv != NULL)
                    {
                        s_faceid.push_back(hv);
                    }
                }
                if ((int)s_faceid.size() >= 3)
                {
                    InsertFace(s_faceid);
                }
            }
        }

        //read texture coords
        fseek(pfile, 0, SEEK_SET);
        std::vector<Vec3f> texCoordsTemp;
        while (fscanf(pfile, "%s", pLine) != EOF)
        {
            if (pLine[0] == 'v' && pLine[1] == 't')
            {
                Vec3f texTemp(0.f, 0.f, 0.f);
                fscanf(pfile, "%f %f", &texTemp[0], &texTemp[1]);
                texCoordsTemp.push_back(texTemp);
            }
        }
        //read texture index

        if (texCoordsTemp.size() > 0)
        {
            fseek(pfile, 0, SEEK_SET);

            int faceIndex = 0;
            while (fscanf(pfile, "%s", pLine) != EOF)
            {

                if (pLine[0] == 'f')
                {
                    int v, t;
                    fscanf(pfile, "%s", pLine);
                    if (sscanf(pLine, "%d/%d", &v, &t) == 2)
                    {
                        std::map<int, int> v2tex;
                        v2tex[v - 1] = t - 1;

                        fscanf(pfile, "%s", pLine);
                        sscanf(pLine, "%d/%d", &v, &t);
                        v2tex[v - 1] = t - 1;

                        fscanf(pfile, "%s", pLine);
                        sscanf(pLine, "%d/%d", &v, &t);
                        v2tex[v - 1] = t - 1;

                        HE_edge* edgeTemp = pfaces_list_->at(faceIndex)->pedge_;
                        edgeTemp->texCoord_ = texCoordsTemp.at(v2tex[edgeTemp->pvert_->id_]);
                        edgeTemp->pvert_->texCoord_ = edgeTemp->texCoord_;
                        edgeTemp = edgeTemp->pnext_;
                        edgeTemp->texCoord_ = texCoordsTemp.at(v2tex[edgeTemp->pvert_->id_]);
                        edgeTemp->pvert_->texCoord_ = edgeTemp->texCoord_;
                        edgeTemp = edgeTemp->pnext_;
                        edgeTemp->texCoord_ = texCoordsTemp.at(v2tex[edgeTemp->pvert_->id_]);
                        edgeTemp->pvert_->texCoord_ = edgeTemp->texCoord_;
                        faceIndex++;
                    }
                }
            }
        }

        //cout << vertex_list->size() << " vertex, " << faces_list->size() << " faces " << endl;

        UpdateMesh();
        Unify(2.f);
    }
    catch (...)
    {
        ClearData();
        xmax_ = ymax_ = zmax_ = 1.f;
        xmin_ = ymin_ = zmin_ = -1.f;

        fclose(pfile);
        return false;
    }

    fclose(pfile);

    return isValid();
}

void Mesh3D::WriteToOBJFile(const char* fouts)
{
    std::ofstream fout(fouts);

    fout << "g object\n";
    fout.precision(16);
    //output coordinates of each vertex
    VERTEX_ITER viter = pvertices_list_->begin();
    for (; viter != pvertices_list_->end(); viter++)
    {
        fout << "v " << std::scientific << (*viter)->position_.x()
            << " " << (*viter)->position_.y() << " " << (*viter)->position_.z() << "\n";
    }

    //         for (viter = pvertices_list_->begin();viter!=pvertices_list_->end(); viter++) 
    //         {
    //             fout<<"vn "<< std::scientific <<(*viter)->normal_.x() 
    //                 <<" "<<(*viter)->normal_.y() <<" "<<(*viter)->normal_.z() <<"\n";
    //         }
    //output the valence of each face and its vertices_list' id

    FACE_ITER fiter = pfaces_list_->begin();

    for (; fiter != pfaces_list_->end(); fiter++)
    {
        fout << "f";

        HE_edge* edge = (*fiter)->pedge_;

        do {
            fout << " " << edge->ppair_->pvert_->id_ + 1;
            edge = edge->pnext_;

        } while (edge != (*fiter)->pedge_);
        fout << "\n";
    }

    fout.close();
}

void Mesh3D::UpdateMesh(void)
{
    if (!isValid())
    {
        std::cout << "Invalid" << "\n";
        return;
    }
    SetBoundaryFlag();
    BoundaryCheck();
    UpdateNormal();
    ComputeBoundingBox();
    ComputeAvarageEdgeLength();
    SetNeighbors();
}

void Mesh3D::SetBoundaryFlag(void)
{
    for (EDGE_ITER eiter = pedges_list_->begin(); eiter != pedges_list_->end(); eiter++)
    {
        if ((*eiter)->pface_ == NULL)
        {
            (*eiter)->set_boundary_flag(BOUNDARY);
            (*eiter)->ppair_->set_boundary_flag(BOUNDARY);
            (*eiter)->pvert_->set_boundary_flag(BOUNDARY);
            (*eiter)->ppair_->pvert_->set_boundary_flag(BOUNDARY);
            (*eiter)->ppair_->pface_->set_boundary_flag(BOUNDARY);
        }
    }
}

void Mesh3D::BoundaryCheck()
{
    for (VERTEX_ITER viter = pvertices_list_->begin(); viter != pvertices_list_->end(); viter++)
    {
        if ((*viter)->isOnBoundary())
        {
            HE_edge* edge = (*viter)->pedge_;
            int deg = 0;
            while (edge->pface_ != NULL && deg < (*viter)->degree())
            {
                edge = edge->pprev_->ppair_;
                deg++;
            }
            (*viter)->pedge_ = edge;
        }
    }
}

void Mesh3D::UpdateNormal(void)
{
    ComputeFaceslistNormal();
    ComputeVertexlistNormal();
}

void Mesh3D::ComputeFaceslistNormal(void)
{
    for (FACE_ITER fiter = pfaces_list_->begin(); fiter != pfaces_list_->end(); fiter++)
    {
        ComputePerFaceNormal(*fiter);
    }
}

void Mesh3D::ComputePerFaceNormal(HE_face* hf)
{
    //图形学课程上机作业
    //请在此处添加计算面法向代码
    point a, b, c;
    a = hf->pedge_->pvert_->position();//得到三角形三点
    b = hf->pedge_->pnext_->pvert_->position();
    c = hf->pedge_->pnext_->pnext_->pvert_->position();
    point m1, m2;//得到两条向量
    m1 = b - a;
    m2 = c - a;
    hf->normal_[0] = m1[1] * m2[2] - m1[2] * m2[1];//叉乘得到面法向量
    hf->normal_[1] = m1[2] * m2[0] - m2[2] * m1[0];
    hf->normal_[2] = m1[0] * m2[1] - m2[0] * m1[1];
    hf->normal_[0] = hf->normal_[0] / (sqrt(hf->normal_[0] * hf->normal_[0] + hf->normal_[1] * hf->normal_[1] + hf->normal_[2] * hf->normal_[2]));//进行单位化
    hf->normal_[1] = hf->normal_[1] / (sqrt(hf->normal_[0] * hf->normal_[0] + hf->normal_[1] * hf->normal_[1] + hf->normal_[2] * hf->normal_[2]));
    hf->normal_[2] = hf->normal_[2] / (sqrt(hf->normal_[0] * hf->normal_[0] + hf->normal_[1] * hf->normal_[1] + hf->normal_[2] * hf->normal_[2]));
}

void Mesh3D::ComputeVertexlistNormal(void)
{
    for (VERTEX_ITER viter = pvertices_list_->begin(); viter != pvertices_list_->end(); viter++)
    {
        ComputePerVertexNormal(*viter);
    }
}

void Mesh3D::ComputePerVertexNormal(HE_vert* hv)
{
    //图形学课程上机作业
    //请在此处添加计算点法向代码
    HE_edge* firstedge = hv->pedge_;//第一条边
    HE_face* face_ = firstedge->pface_;//第一个面
    Mesh3D::ComputePerFaceNormal(face_);//调用函数计算这个面的法向量
    hv->normal_[0] = 0;//初始化为0
    hv->normal_[1] = 0;
    hv->normal_[2] = 0;
    float total = 0;//这个顶点一共多少个面相邻
    for (int i = 0; i < 3; i++)
    {
        hv->normal_[i] = hv->normal_[i] + face_->normal_[i];//加上顶点相邻面的法向量
    }
    total++;
    HE_edge* nextedge = firstedge->ppair_->pnext_;//下一条边
    while (nextedge != firstedge)
    {
        face_ = nextedge->pface_;
        Mesh3D::ComputePerFaceNormal(face_); //调用函数计算这个面的法向量
        for (int i = 0; i < 3; i++)
        {
            hv->normal_[i] = hv->normal_[i] + face_->normal_[i];//加上顶点相邻面的法向量
        }
        total++;
        nextedge = nextedge->ppair_->pnext_;//下一条边
    }
    for (int i = 0; i < 3; i++)
    {
        hv->normal_[i] = hv->normal_[i] / total;//取平均数
    }
}

void Mesh3D::ComputeBoundingBox(void)
{
    if (pvertices_list_->size() < 3)
    {
        return;
    }

#define MAX_FLOAT_VALUE (static_cast<float>(10e10))
#define MIN_FLOAT_VALUE    (static_cast<float>(-10e10))

    xmax_ = ymax_ = zmax_ = MIN_FLOAT_VALUE;
    xmin_ = ymin_ = zmin_ = MAX_FLOAT_VALUE;

    VERTEX_ITER viter = pvertices_list_->begin();
    for (; viter != pvertices_list_->end(); viter++)
    {
        xmin_ = min(xmin_, (*viter)->position_.x());
        ymin_ = min(ymin_, (*viter)->position_.y());
        zmin_ = min(zmin_, (*viter)->position_.z());
        xmax_ = max(xmax_, (*viter)->position_.x());
        ymax_ = max(ymax_, (*viter)->position_.y());
        zmax_ = max(zmax_, (*viter)->position_.z());
    }
}

void Mesh3D::Unify(float size)
{
    float scaleX = xmax_ - xmin_;
    float scaleY = ymax_ - ymin_;
    float scaleZ = zmax_ - zmin_;
    float scaleMax;

    if (scaleX < scaleY)
    {
        scaleMax = scaleY;
    }
    else
    {
        scaleMax = scaleX;
    }
    if (scaleMax < scaleZ)
    {
        scaleMax = scaleZ;
    }
    float scaleV = size / scaleMax;
    Vec3f centerPos((xmin_ + xmax_) / 2.f, (ymin_ + ymax_) / 2.f, (zmin_ + zmax_) / 2.f);
    for (size_t i = 0; i != pvertices_list_->size(); i++)
    {
        pvertices_list_->at(i)->position_ = (pvertices_list_->at(i)->position_ - centerPos) * scaleV;
    }
}

void Mesh3D::ComputeAvarageEdgeLength(void)
{
    if (!isValid())
    {
        average_edge_length_ = 0.f;
        return;
    }
    float aveEdgeLength = 0.f;
    for (int i = 0; i < num_of_half_edges_list(); i++)
    {
        HE_edge* edge = get_edges_list()->at(i);
        HE_vert* v0 = edge->pvert_;
        HE_vert* v1 = edge->ppair_->pvert_;
        aveEdgeLength += (v0->position() - v1->position()).length();
    }
    average_edge_length_ = aveEdgeLength / num_of_half_edges_list();
    //std::cout << "Average_edge_length = " << average_edge_length_ << "\n";
}

HE_face* Mesh3D::get_face(int vId0, int vId1, int vId2)
{
    HE_vert* v0 = get_vertex(vId0);
    HE_vert* v1 = get_vertex(vId1);
    HE_vert* v2 = get_vertex(vId2);
    if (!v0 || !v1 || !v2)
    {
        return NULL;
    }

    HE_face* face = NULL;

    // 由于对边界点的邻域遍历有bug,所以找到非边界点进行邻域遍历
    if (v0->isOnBoundary())
    {
        if (!v1->isOnBoundary())
        {
            SWAP(v0, v1, HE_vert*);
        }
        else if (!v2->isOnBoundary())
        {
            SWAP(v0, v2, HE_vert*);
        }
        else
        {
            // v0, v1, v2 都是边界点
            // 暂时先不处理
            return NULL;
        }
    }

    if (!v0->isOnBoundary())    // 对边界点的遍历有bug
    {
        HE_edge* edge = v0->pedge_;
        bool inFace = true;
        do
        {
            bool b1 = isFaceContainVertex(edge->pface_, v1);
            bool b2 = isFaceContainVertex(edge->pface_, v2);
            if (!b1 && !b1)
            {
                edge = edge->ppair_->pnext_;
            }
            else if (b1 && b2)
            {
                face = edge->pface_;
                break;
            }
            else
            {
                inFace = false;
                break;
            }
        } while (edge != v0->pedge_ && edge != NULL);
    }

    return face;
}

HE_face* Mesh3D::get_face(const std::vector<unsigned int>& ids)
{
    if (ids.size() < 3)
    {
        std::cout << "can not return face" << std::endl;
        return NULL;
    }
    // 首先找到一个非边界点
    HE_vert* v = NULL;
    for (unsigned int i = 0; i < ids.size(); i++)
    {
        if (!get_vertex(ids[i])->isOnBoundary())
        {
            v = get_vertex(ids[i]);
            break;
        }
    }
    if (!v)
    {
        // 所有点都是边界点
        // 暂不处理
        return NULL;
    }

    HE_edge* edge = v->pedge_;
    HE_face* face = NULL;
    do
    {
        face = edge->pface_;
        edge = edge->ppair_->pnext_;
        bool bInFace = isFaceContainVertex(face, get_vertex(ids[0]));
        if (!bInFace)
        {
            continue;
        }
        for (unsigned int i = 1; i < ids.size(); i++)
        {
            bool b = isFaceContainVertex(face, get_vertex(ids[i]));
            if (b != bInFace)
            {
                bInFace = false;
                break;
            }
        }
        if (bInFace)
        {
            return face;
        }
    } while (edge != v->pedge_ && edge != NULL);
    return NULL;
}

bool Mesh3D::isFaceContainVertex(HE_face* face, HE_vert* vert)
{
    HE_edge* edge = face->pedge_;
    do
    {
        if (edge->pvert_ == vert)
        {
            return true;
        }
        edge = edge->pnext_;
    } while (edge != face->pedge_ && edge != NULL);
    return false;
}

int Mesh3D::GetFaceId(HE_face* face)
{
    return !face ? -1 : face->id();
}

void Mesh3D::ResetFaceSelectedTags(int tag)
{
    for (int i = 0; i < num_of_face_list(); i++)
    {
        get_face(i)->set_selected(tag);
    }
}

void Mesh3D::ResetVertexSelectedTags(int tag)
{
    for (int i = 0; i < num_of_vertex_list(); i++)
    {
        get_vertex(i)->set_seleted(tag);
    }
}

bool Mesh3D::isNeighbors(HE_vert* v0, HE_vert* v1)
{
    if (!v0 || !v1)
    {
        return false;
    }

    HE_edge* edge = v0->pedge_;
    do
    {
        if (edge->pvert_ == v1)
        {
            return true;
        }
        edge = edge->ppair_->pnext_;
    } while (edge != v0->pedge_ && edge);
    return false;
}

int Mesh3D::GetSelectedVrtId()
{
    if (!isValid())
    {
        return -1;
    }
    for (int i = 0; i < num_of_vertex_list(); i++)
    {
        if (get_vertex(i)->selected() == SELECTED)
        {
            return i;
        }
    }
    return -1;
}

void Mesh3D::CreateMesh(const std::vector<Vec3f>& verts, const std::vector<int>& triIdx)
{
    ClearData();
    for (unsigned int i = 0; i < verts.size(); i++)
    {
        InsertVertex(verts[i]);
    }
    for (unsigned int i = 0; i < triIdx.size(); i = i + 3)
    {
        std::vector<HE_vert*> tri;
        HE_vert* v0 = get_vertex(triIdx[i]);
        HE_vert* v1 = get_vertex(triIdx[i + 1]);
        HE_vert* v2 = get_vertex(triIdx[i + 2]);
        if (!v0 || !v1 || !v2) continue;
        tri.push_back(v0);
        tri.push_back(v1);
        tri.push_back(v2);
        InsertFace(tri);
    }
    UpdateMesh();
}

void Mesh3D::CreateMesh(const std::vector<double>& verts, const std::vector<unsigned>& triIdx)
{
    ClearData();
    for (unsigned int i = 0; i < verts.size(); i = i + 3)
    {
        InsertVertex(Vec3f(verts[i], verts[i + 1], verts[i + 2]));
    }
    for (unsigned int i = 0; i < triIdx.size(); i = i + 3)
    {
        std::vector<HE_vert*> tri;
        HE_vert* v0 = get_vertex(triIdx[i]);
        HE_vert* v1 = get_vertex(triIdx[i + 1]);
        HE_vert* v2 = get_vertex(triIdx[i + 2]);
        if (!v0 || !v1 || !v2) continue;
        tri.push_back(v0);
        tri.push_back(v1);
        tri.push_back(v2);
        InsertFace(tri);
    }
    UpdateMesh();
}

int Mesh3D::GetBoundaryVrtSize()
{
    int count = 0;
    for (int i = 0; i < num_of_vertex_list(); i++)
    {
        if (get_vertex(i)->isOnBoundary())
        {
            count++;
        }
    }
    return count;
}

Mesh3D::~Mesh3D(void)
{
    ClearData();
}



void loadOBJ(std::string fileName)
{
    std::string line;
    int count, vertexIndex1, vertexIndex2, vertexIndex3;
    float coordinateValue;
    char currentCharacter, previousCharacter;

    // Open the OBJ file.
    std::ifstream inFile(fileName.c_str(), std::ifstream::in);

    // Read successive lines.
    while (getline(inFile, line))
    {
        // Line has vertex data.
        if (line.substr(0, 2) == "v ")
        {
            // Initialize a string from the character after "v " to the end.
            std::istringstream currentString(line.substr(2));

            // Read x, y and z values. The (optional) w value is not read. 
            for (count = 1; count <= 3; count++)
            {
                currentString >> coordinateValue;
                verticesVector.push_back(coordinateValue);
            }
        }

        // Line has face data.
        else if (line.substr(0, 2) == "f ")
        {
            // Initialize a string from the character after "f " to the end.
            std::istringstream currentString(line.substr(2));

            // Strategy in the following to detect a vertex index within a face line is based on the
            // fact that vertex indices are exactly those that follow a white space. Texture and
            // normal indices are ignored.
            // Moreover, from the third vertex of a face on output one triangle per vertex, that
            // being the next triangle in a fan triangulation of the face about the first vertex.
            previousCharacter = ' ';
            count = 0;
            while (currentString.get(currentCharacter))
            {
                // Stop processing line at comment.
                if ((previousCharacter == '#') || (currentCharacter == '#')) break;

                // Current character is the start of a vertex index.
                if ((previousCharacter == ' ') && (currentCharacter != ' '))
                {
                    // Move the string cursor back to just before the vertex index.
                    currentString.unget();

                    // Read the first vertex index, decrement it so that the index range is from 0, increment vertex counter.
                    if (count == 0)
                    {
                        currentString >> vertexIndex1;
                        vertexIndex1--;
                        count++;
                    }

                    // Read the second vertex index, decrement it, increment vertex counter.
                    else if (count == 1)
                    {
                        currentString >> vertexIndex2;
                        vertexIndex2--;
                        count++;
                    }

                    // Read the third vertex index, decrement it, increment vertex counter AND output the first triangle.
                    else if (count == 2)
                    {
                        currentString >> vertexIndex3;
                        vertexIndex3--;
                        count++;
                        facesVector.push_back(vertexIndex1);
                        facesVector.push_back(vertexIndex2);
                        facesVector.push_back(vertexIndex3);
                    }

                    // From the fourth vertex and on output the next triangle of the fan.
                    else
                    {
                        vertexIndex2 = vertexIndex3;
                        currentString >> vertexIndex3;
                        vertexIndex3--;
                        facesVector.push_back(vertexIndex1);
                        facesVector.push_back(vertexIndex2);
                        facesVector.push_back(vertexIndex3);
                    }

                    // Begin the process of detecting the next vertex index just after the vertex index just read.
                    currentString.get(previousCharacter);
                }

                // Current character is not the start of a vertex index. Move ahead one character.
                else previousCharacter = currentCharacter;
            }
        }

        // Nothing other than vertex and face data is processed.
        else
        {
        }
    }

    // Close the OBJ file.
    inFile.close();
}
vector<double> alpha;//计算法向量和光线投射方向点积的值
void getalpha(void)//计算出点积的函数
{
    for (int i = 0; i < facesVector.size(); i = i + 3)
    {
        double a1 = double(vertices[(faces[i + 1]) * 3]) - double(vertices[(faces[i]) * 3]);//第一个向量的 x y z为a1 b1 c1
        double b1 = double(vertices[(faces[i + 1]) * 3 + 1]) - double(vertices[(faces[i]) * 3 + 1]);
        double c1 = double(vertices[(faces[i + 1]) * 3 + 2]) - double(vertices[(faces[i]) * 3 + 2]);
        double a2 = double(vertices[(faces[i + 2]) * 3]) - double(vertices[(faces[i]) * 3]);//第二个向量的x y z 为a2 b2 c2
        double b2 = double(vertices[(faces[i + 2]) * 3 + 1]) - double(vertices[(faces[i]) * 3 + 1]);
        double c2 = double(vertices[(faces[i + 2]) * 3 + 2]) - double(vertices[(faces[i]) * 3 + 2]);
        double face[3] = { b1 * c2 - c1 * b2,c1 * a2 - c2 * a1,a1 * b2 - a2 * b1 };//叉乘得到这个面的法向量
        face[0] = face[0] / (sqrt(face[0] * face[0] + face[1] * face[1] + face[2] * face[2]));//进行单位化
        face[1] = face[1] / (sqrt(face[0] * face[0] + face[1] * face[1] + face[2] * face[2]));
        face[2] = face[2] / (sqrt(face[0] * face[0] + face[1] * face[1] + face[2] * face[2]));
        double k = (face[0] * 0 + face[1] * 0 + face[2] * 1);//点乘得到点积
        alpha.push_back(k);//加入数组

    }
}

// Initialization routine.
void writeData(void)
{
    glDisable(GL_LIGHTING); // Disable lighting.
    glColor3f(1.0, 1.0, 1.0);

    floatToString(theStringBuffer, 4, d);
    glRasterPos3f(-1.0, 1.05, -2.0);
    writeBitmapString((void*)font, "Diffuse and specular white light intensity: ");
    writeBitmapString((void*)font, theStringBuffer);

    floatToString(theStringBuffer, 4, m);
    glRasterPos3f(-1.0, 1.0, -2.0);
    writeBitmapString((void*)font, "Global ambient whitle light intensity: ");
    writeBitmapString((void*)font, theStringBuffer);

    floatToString(theStringBuffer, 4, t);
    glRasterPos3f(-1.0, 0.95, -2.0);
    writeBitmapString((void*)font, "Quadratic attenuation: ");
    writeBitmapString((void*)font, theStringBuffer);

    glRasterPos3f(-1.0, 0.9, -2.0);//指定像素运算的光栅位置。
    if (localViewer) writeBitmapString((void*)font, "Local viewpoint.");
    else writeBitmapString((void*)font, "Infinite viewpoint.");

    glEnable(GL_LIGHTING); // Re-enable lighting.
}

void setup(void)
{
    bool is_open = ptr_mesh_->LoadFromOBJFile("gourd.obj");//读取obj文件
    glEnableClientState(GL_VERTEX_ARRAY);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST); // Enable depth testing.

    // Turn on OpenGL lighting.
    glEnable(GL_LIGHTING);

    // Material property vectors.
    float matAmbAndDif[] = { 1.0, 1.0, 0.0, 1.0 };//梨本身的颜色:黄色
    float matSpec[] = { 1.0, 1.0, 1,0, 1.0 };
    float matShine[] = { 50.0 };

    // Material properties of pair.
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, matAmbAndDif);
    glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
    glMaterialfv(GL_FRONT, GL_SHININESS, matShine);

    // Cull back faces.
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
}

// Drawing routine.
void drawScene(void)
{
    // Light property vectors.
    float lightAmb[] = { 0.0, 0.0, 0.0, 1.0 };
    float lightDifAndSpec0[] = { d, d, d, 1.0 };
    float lightPos0[] = { 0.0, 0.0, 3.0, p };
    float lightDifAndSpec1[] = { 0.0, 1.0, 0.0, 1.0 };
    float lightPos1[] = { 1.0, 2.0, 0.0, 1.0 };
    float globAmb[] = { m, m, m, 1.0 };

    // Light0 properties.
    glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDifAndSpec0);
    glLightfv(GL_LIGHT0, GL_SPECULAR, lightDifAndSpec0);

    // Light1 properties.
    glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmb);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDifAndSpec1);
    glLightfv(GL_LIGHT1, GL_SPECULAR, lightDifAndSpec1);

    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globAmb); // Global ambient light.
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, localViewer); // Enable local viewpoint

    // Turn lights off/on.
    if (light0On) glEnable(GL_LIGHT0); else glDisable(GL_LIGHT0);
    if (light1On) glEnable(GL_LIGHT1); else glDisable(GL_LIGHT1);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();

    // Light quadratic attenuation factor.
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, t);
    glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, t);

    writeData();

    gluLookAt(0.0, 3.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    // Draw light source spheres (or arrow) after disabling lighting.
    glDisable(GL_LIGHTING);

    // Light0 positioned and sphere positioned in case of positional light
    // and arrow in case of directional light.
    glPushMatrix();
    glRotatef(xAngle, 1.0, 0.0, 0.0); // Rotation about x-axis.
    glRotatef(yAngle, 0.0, 1.0, 0.0); // Rotation about y-axis.
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
    glTranslatef(lightPos0[0], lightPos0[1], lightPos0[2]);
    glColor3f(d, d, d);
    if (light0On)
    {
        if (p) glutWireSphere(0.05, 8, 8); // Sphere at positional light source.
        else //按方向键旋转白光源
        {
            glLineWidth(3.0);
            glBegin(GL_LINES);
            glVertex3f(0.0, 0.0, 0.25);
            glVertex3f(0.0, 0.0, -0.25);
            glVertex3f(0.0, 0.0, -0.25);
            glVertex3f(0.05, 0.0, -0.2);
            glVertex3f(0.0, 0.0, -0.25);
            glVertex3f(-0.05, 0.0, -0.2);
            glEnd();
            glLineWidth(1.0);
        }
    }
    glPopMatrix();

    // Light1 and its sphere positioned.
    glPushMatrix();
    glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
    glTranslatef(lightPos1[0], lightPos1[1], lightPos1[2]);
    glColor3f(0.0, 1.0, 0.0);
    if (light1On) glutWireSphere(0.05, 8, 8);
    glPopMatrix();

    glEnable(GL_LIGHTING);

    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();
    gluLookAt(0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glColor3f(0.0, 0.7, 6.0);

    // Rotate scene.
    glRotatef(Zangle, 0.0, 0.0, 1.0);
    glRotatef(Yangle, 0.0, 1.0, 0.0);
    glRotatef(Xangle, 1.0, 0.0, 0.0);

    // Draw the object mesh.
    for (int i = 0; i < ptr_mesh_->num_of_face_list(); i = i++)
    {
        point first, second, third;
        first = ptr_mesh_->get_face(i)->pedge_->pvert_->position();//第一个顶点
        second = ptr_mesh_->get_face(i)->pedge_->pnext_->pvert_->position();//第二个点
        third = ptr_mesh_->get_face(i)->pedge_->pnext_->pnext_->pvert_->position();//第三个点
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glBegin(GL_TRIANGLES);//画三角形
        if (change == 0)
        {
            glNormal3fv(ptr_mesh_->get_face(i)->normal_);//平面光照
            glVertex3f(first[0], first[1], first[2]);
            glVertex3f(second[0], second[1], second[2]);
            glVertex3f(third[0], third[1], third[2]);
        }
        else if (change == 1)//平滑光照处理
        {
            glNormal3fv(ptr_mesh_->get_face(i)->pedge_->pvert_->normal_);
            glVertex3f(first[0], first[1], first[2]);
            glNormal3fv(ptr_mesh_->get_face(i)->pedge_->pnext_->pvert_->normal_);
            glVertex3f(second[0], second[1], second[2]);
            glNormal3fv(ptr_mesh_->get_face(i)->pedge_->pnext_->pnext_->pvert_->normal_);
            glVertex3f(third[0], third[1], third[2]);
        }
        glEnd();
    }

    glutSwapBuffers();

}


// OpenGL window reshape routine.
void resize(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, (float)w / (float)h, 1.0, 50.0);
    glMatrixMode(GL_MODELVIEW);
}

// Keyboard input processing routine.
void keyInput(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 27:
        exit(0);
        break;
    case 'x':
        Xangle += 5.0;
        if (Xangle > 360.0) Xangle -= 360.0;
        glutPostRedisplay();
        break;
    case 'X':
        Xangle -= 5.0;
        if (Xangle < 0.0) Xangle += 360.0;
        glutPostRedisplay();
        break;
    case 'y':
        Yangle += 5.0;
        if (Yangle > 360.0) Yangle -= 360.0;
        glutPostRedisplay();
        break;
    case 'Y':
        Yangle -= 5.0;
        if (Yangle < 0.0) Yangle += 360.0;
        glutPostRedisplay();
        break;
    case 'z':
        Zangle += 5.0;
        if (Zangle > 360.0) Zangle -= 360.0;
        glutPostRedisplay();
        break;
    case 'Z':
        Zangle -= 5.0;
        if (Zangle < 0.0) Zangle += 360.0;
        glutPostRedisplay();
        break;
    case'c':
        change = 1;//0切换为平面 1切换到平滑
        glutPostRedisplay();
        break;
    case'C':
        change = 0;
        glutPostRedisplay();
        break;
    case 'w':
            if (light0On) light0On = 0; else light0On = 1;
            glutPostRedisplay();
            break;
    case 'g':
            if (light1On) light1On = 0; else light1On = 1;
            glutPostRedisplay();
            break;
    case 'l':
            if (localViewer) localViewer = 0; else localViewer = 1;
            glutPostRedisplay();
            break;
    case 'L':
            if (localViewer) localViewer = 0; else localViewer = 1;
            glutPostRedisplay();
            break;
    case 'p':
            if (p) p = 0.0; else p = 1.0;
            glutPostRedisplay();
            break;
    case 'P':
            if (p) p = 0.0; else p = 1.0;
            glutPostRedisplay();
            break;
    case 'd':
            if (d > 0.0) d -= 0.05;
            glutPostRedisplay();
            break;
    case 'D':
            if (d < 1.0) d += 0.05;
            glutPostRedisplay();
            break;
    case 'm':
            if (m > 0.0) m -= 0.05;
            glutPostRedisplay();
            break;
    case 'M':
            if (m < 1.0) m += 0.05;
            glutPostRedisplay();
            break;
    case 't':
            if (t > 0.0) t -= 0.01;
            glutPostRedisplay();
            break;
    case 'T':
            t += 0.01;
            glutPostRedisplay();
            break;
    case 'r':
            zMove = 0.0; xAngle = 0.0, yAngle = 0.0;
            glutPostRedisplay();
            break;
    default:
        break;
    }
}

// Callback routine for non-ASCII key entry.
void specialKeyInput(int key, int x, int y)//根据方向键改变可移动白灯光的位置
{
    if (key == GLUT_KEY_DOWN)
    {
        xAngle++;
        if (xAngle > 360.0) xAngle -= 360.0;
    }
    if (key == GLUT_KEY_UP)
    {
        xAngle--;
        if (xAngle < 0.0) xAngle += 360.0;
    }
    if (key == GLUT_KEY_RIGHT)
    {
        yAngle++;
        if (yAngle > 360.0) yAngle -= 360.0;
    }
    if (key == GLUT_KEY_LEFT)
    {
        yAngle--;
        if (yAngle < 0.0) yAngle += 360.0;
    }
    if (key == GLUT_KEY_PAGE_UP) zMove -= 0.1;
    if (key == GLUT_KEY_PAGE_DOWN) if (zMove < 3.0) zMove += 0.1;
    glutPostRedisplay();
}


// Routine to output interaction instructions to the C++ window.
void printInteraction(void)
{
    std::cout << "Interaction:" << std::endl;
    std::cout << "Press x, X, y, Y, z, Z to turn the object." << std::endl;
    std::cout << "Press c to turn to smooth shading."<<std::endl;
    std::cout << "Press C to turn to flat shading"<<std::endl;
    std::cout << "Press 'w' to toggle the white light off/on." << std::endl
        << "Press 'g' to toggle the green light off/on." << std::endl
        << "Press 'd/D' to decrease/increase the white light's diffuse and specular intensity." << std::endl
        << "Press 'm/M' to decrease/increase global ambient white light intensity." << std::endl
        << "Press 't/T' to decrease/increase the quadratic attenuation parameter." << std::endl
        << "Press 'l' to toggle between infinite and local viewpoint." << std::endl
        << "Press 'p' to toggle between positional and directional white light." << std::endl
        << "Press the page up/down keys to move the ball." << std::endl
        << "Press arrow keys to rotate the white light about the original position of the ball." << std::endl
        << "Press 'r' to reset the ball and white light to their original positions." << std::endl;
}

// Main routine.
int main(int argc, char** argv)
{
    printInteraction();//操作提示信息
    glutInit(&argc, argv);

    glutInitContextVersion(4, 3);
    glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(600, 600);//显示图形的窗口大小
    glutInitWindowPosition(100, 100);
    glutCreateWindow("OBJmodelViewer.cpp");
    glutDisplayFunc(drawScene);
    glutReshapeFunc(resize);
    glutKeyboardFunc(keyInput);//一般按键调节
    glutSpecialFunc(specialKeyInput);//方向键调节可移动白色灯光的位置
    glewExperimental = GL_TRUE;
    glewInit();

    setup();

    glutMainLoop();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值