吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1761|回复: 4
收起左侧

[已解决] 新手学OpenGL遇到的一个小问题

[复制链接]
沉默的菜鸟 发表于 2019-9-6 22:04
本帖最后由 沉默的菜鸟 于 2019-9-7 21:35 编辑

刚开始学OpenGL,做了一个小程序,即将obj文件读进内存并画出3D对象。
在这个过程中我碰到了一个小问题,当我读取一个为正方体的obj文件并显示到窗口时,这个正方体会充满画面并随着窗口变化而变化,我想让它不占据整个窗口,这样好看一点,不知道应该怎么改。
但是读取另外一个兔子的obj文件却是正常显示,没有占据整个窗口。
2 (1).jpg

2 (2).jpg

求大佬给个思路。。。
还有就是怎么给模型加颜色???
代码如下:
ObjLoader.h


[C++] 纯文本查看 复制代码
#pragma once
#include <GL/glut.h>
#include <vector>
#include <array>
#include <string>
using namespace std;

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



ObjLoader.cpp

[C++] 纯文本查看 复制代码
#include "ObjLoader.h"
#include <fstream>
#include <iostream>
#include <sstream>
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[0]=='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[0]=='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
                }
        }

}

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[i].size() != 3)
                {
                        cout << "数据错误!" << endl;
                }
                else
                {
                        GLint firstVertexIndex = (triangleContainer[i])[0];                                //取出顶点索引
                        GLint secondVertexIndex = (triangleContainer[i])[1];
                        GLint thirdVertexIndex = (triangleContainer[i])[2];

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

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

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

                        glNormal3f(VN[0], VN[1], VN[2]);//绘制单位法向量
                        glVertex3f(Vertex1[0] *5, Vertex1[1] * 5, Vertex1[2] * 5);
                        glVertex3f(Vertex2[0] * 5, Vertex2[1] * 5, Vertex2[2] * 5);
                        glVertex3f(Vertex3[0] * 5, Vertex3[1] * 5, Vertex3[2] * 5);
                }
        }
        glEnd();
}


main.cpp

[C++] 纯文本查看 复制代码
#include "ObjLoader.h"
#include <iostream>
using namespace std;

ObjLoader objModel;

//实现移动鼠标观察模型所需变量
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);
}

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, -5.0f);
        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 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);
        glutReshapeFunc(reshape);
        glutMouseFunc(moseMove);
        glutMotionFunc(changeViewPoint);
        glutIdleFunc(myIdle);
        glutMainLoop();
        return 0;
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

ihjun 发表于 2019-9-6 23:48
用glTranslatef()把z轴的深度坐标设定小一点,三维形体就不会占据整个窗口了
加普通颜色的话,应该针对不同的面设定glColor3f,然后在setLightRes中设置合适的光照。
如果是加纹理的话,就得准备好纹理贴图了。
紫寒秋 发表于 2019-9-7 00:13
你现在是视点离立方体太近了,所以立方体占据整个视窗。而兔子的尺寸可能远小于立方体的大小,所以能够看到它的全貌。
把r值设定大一点,比如5,就能看到立方体在视窗中间了。

首先使能颜色: glEnable(GL_COLOR_MATERIAL);
其次设定颜色值 glColor3f(1.0f, .0f, .0f);
 楼主| 沉默的菜鸟 发表于 2019-9-7 09:28
紫寒秋 发表于 2019-9-7 00:13
你现在是视点离立方体太近了,所以立方体占据整个视窗。而兔子的尺寸可能远小于立方体的大小,所以能够看到 ...

谢谢,颜色问题已经搞定了
 楼主| 沉默的菜鸟 发表于 2019-9-7 09:45
ihjun 发表于 2019-9-6 23:48
用glTranslatef()把z轴的深度坐标设定小一点,三维形体就不会占据整个窗口了
加普通颜色的话,应该针对不 ...

立方体搞定了,果然是离得太近了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-27 02:50

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表