沉默的菜鸟 发表于 2019-9-7 21:41

关于OpenGL的一个小问题(2)

本帖最后由 沉默的菜鸟 于 2019-9-7 21:46 编辑

用OpenGL画了一个立方体,实现了鼠标手动旋转以及自动旋转等功能。
但碰到了一个棘手问题,就是当立方体自动旋转时,只有两面有颜色,另外的面为黑色,但我都设置了颜色的呀??
求大神帮助。。。

代码:

ObjLoader.h

#pragma once
#include <GL/glut.h>
#include <vector>
#include <array>
#include <string>
using namespace std;

class ObjLoader
{
public:
      ObjLoader() {};
      ObjLoader( const string& filepath);
      ~ObjLoader();
      void Paint();
private:
      vector<array<GLfloat, 3>> vertexContainer;
      vector<array<GLint, 3>> triangleContainer;
};



ObjLoader.cpp



#include "ObjLoader.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <direct.h>
ObjLoader::ObjLoader(const string& filepath)
{
      string line;
      ifstream f;
      f.open(filepath, ios::in);
      if (!f.is_open())
      {
                cout << "文件打开失败,请检查文件路径!" << endl;
                return;
      }
      while (!f.eof())
      {
                getline(f, line);
                cout << line << endl;
                istringstream sin(line);
                if (line=='v')
                {
                        char flag;
                        float x, y, z;
                        sin >> flag >> x >> y >> z;
                        this->vertexContainer.push_back(array<GLfloat, 3>{x, y, z});
                }
                else if (line=='f')
                {
                        char flag;
                        int p1, p2, p3;
                        sin >> flag >> p1 >> p2 >> p3;
                        this->triangleContainer.push_back(array<GLint, 3>{p1-1, p2-1, p3-1});
                        //因为顶点索引在obj文件中是从1开始的,而我们存放的顶点array是从0开始的,因此要减1
                }
      }

}

ObjLoader::~ObjLoader()
{
      char buffer;
      _getcwd(buffer,100);
      string path = string(buffer);
      string filename = "/data.obj";
      ofstream out;
      out.open(path+filename,ios::out);
      if (!out.is_open())
      {
                cout << "写入路径错误!" << endl;
                return;
      }
      for(auto vertex : this->vertexContainer)
      {
                out << "v " << vertex << " " << vertex << " " << vertex << endl;
      }
      for (auto triangle:this->triangleContainer)
      {
                out << "f " << triangle+1 << " " << triangle+1 << " " << triangle+1 << endl;
      }
      out.close();
      cout << "写入文件成功!" << endl;
}


void ObjLoader::Paint()
{
      glBegin(GL_TRIANGLES);                                                                                                                //开始绘制

      for (size_t i = 0; i < this->triangleContainer.size(); i++)
      {
                array<GLfloat, 3>VN;//三角形的单位法向量
                //三个顶点
                array<GLfloat, 3>Vertex1;
                array<GLfloat, 3>Vertex2;
                array<GLfloat, 3>Vertex3;
                if (this->triangleContainer.size() != 3)
                {
                        cout << "数据错误!" << endl;
                }
                else
                {
                        GLint firstVertexIndex = (triangleContainer);                              //取出顶点索引
                        GLint secondVertexIndex = (triangleContainer);
                        GLint thirdVertexIndex = (triangleContainer);

                        for (size_t j = 0; j < 3; j++)
                        {
                              Vertex1 = vertexContainer;                        //顶点一
                              Vertex2 = vertexContainer;                //顶点二
                              Vertex3 = vertexContainer;                        //顶点三
                        }

                        GLfloat vec1, vec2, vec3;//计算法向量
                        for (size_t z = 0; z < 3; z++)
                        {
                              vec1 = Vertex1 - Vertex2;//v1v2向量
                              vec2 = Vertex1 - Vertex3;//v1v3向量
                        }
                        //由v1v2向量与v1v3向量叉乘即可得平面的法向量
                        vec3 = vec1 * vec2 - vec1 * vec2;
                        vec3 = vec2 * vec1 - vec2 * vec1;
                        vec3 = vec2 * vec1 - vec2 * vec1;

                        //单位法向量
                        GLfloat D = sqrtf(pow(vec3, 2) + pow(vec3, 2) + pow(vec3, 2));
                        for (size_t n = 0; n < 3; n++)
                        {
                              VN = vec3 / D;
                        }

                        int p = 7;//扩大倍数

                        glColor3ub(163, 85, 104);
                        glNormal3f(VN, VN, VN);//绘制单位法向量
                        glColor3ub(163, 85, 104);
                        glVertex3f(Vertex1 *p, Vertex1 * p, Vertex1 * p);
                        glColor3ub(73,90,128);
                        glVertex3f(Vertex2 * p, Vertex2 * p, Vertex2 * p);
                        glColor3ub(221,240, 237);
                        glVertex3f(Vertex3 * p, Vertex3 * p, Vertex3 * p);
                }
      }
      glEnd();
}



main.cpp


#include "ObjLoader.h"
#include <iostream>
using namespace std;

ObjLoader objModel;

int angles = 0;      //转动角度
int xyz = { 0,1,0 };

//实现移动鼠标观察模型所需变量
static float c = 3.1415926f / 180.0f;
static float r = 1.0f;
static int degree = 90;
static int oldPosY = -1;
static int oldPosX = -1;

//安置光源
void setLightRes() {
      GLfloat lightPosition[] = { 0.0f, 0.0f, 1.0f, 0.0f };
      glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
      glEnable(GL_LIGHTING); //启用光源
      glEnable(GL_LIGHT0);   //使用指定灯光
}

//初始化
void init() {
      cout << "please input the path of the obj file:";
      string path;
      cin >> path;
      cout << endl;
      objModel = ObjLoader(path);
      glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
      glutInitWindowSize(500, 500);
      glutCreateWindow("ObjBuilder");
      glEnable(GL_DEPTH_TEST);
      glShadeModel(GL_SMOOTH);
      setLightRes();
      glEnable(GL_DEPTH_TEST);
      glColorMaterial(GL_FRONT, GL_DIFFUSE);
      glEnable(GL_COLOR_MATERIAL);

      glEnable(GL_LIGHTING);
      glEnable(GL_LIGHT0);
      glEnable(GL_AUTO_NORMAL);
      glEnable(GL_NORMALIZE);
}

void timerPoc(int id)
{
      angles += 20;
      angles %= 360;
      glutPostRedisplay();
      glutTimerFunc(200, timerPoc, 1);
}

void display()
{
      glColor3f(1.0, 1.0, 1.0);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslatef(0.0f, 0.0f, -20.0f);
      glRotatef(angles, xyz, xyz, xyz);
      setLightRes();
      glPushMatrix();

      gluLookAt(r * cos(c * degree), 0, r * sin(c * degree), 0.0f, 0.0f, 0.0f, 0.0f,1.0f, 0.0f);

      objModel.Paint();//绘制obj模型
      glPopMatrix();
      glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y)
{
      if (key == 114) {
                glutTimerFunc(200, timerPoc, 1);
                cout << "Unhandled key press r" << endl;
      }
}

void reshape(int width, int height)
{
      glViewport(0, 0, width, height);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(60.0f, (GLdouble)width / (GLdouble)height, 1.0f, 200.0f);
      glMatrixMode(GL_MODELVIEW);
}

//移动鼠标360观察模型
void moseMove(int button, int state, int x, int y)
{
      if (state == GLUT_DOWN) {
                oldPosX = x; oldPosY = y;
      }
}
void changeViewPoint(int x, int y)
{
      int temp = x - oldPosX;
      degree += temp;
      oldPosX = x;
      oldPosY = y;
}

void myIdle()
{
      glutPostRedisplay();
}

int main(int argc, char* argv[])
{
      glutInit(&argc, argv);
      init();
      glutDisplayFunc(display);
      glutKeyboardFunc(keyboard);
      glutReshapeFunc(reshape);
      glutMouseFunc(moseMove);
      glutMotionFunc(changeViewPoint);
      glutIdleFunc(myIdle);
      glutMainLoop();
      return 0;
}


效果:




我觉得可能是光源的问题,但不知道怎么解决。。。

okxiaobo 发表于 2019-9-7 21:47

okxiaobo 发表于 2019-9-7 21:48

沉默的菜鸟 发表于 2019-9-7 22:22

okxiaobo 发表于 2019-9-7 21:47
牛逼,高手啊

汗颜了,我才敢刚学{:1_924:}

沉默的菜鸟 发表于 2019-9-7 22:23

okxiaobo 发表于 2019-9-7 21:48
这是光照问题

应该怎么改呢???
页: [1]
查看完整版本: 关于OpenGL的一个小问题(2)