项目文件资源链接//download.csdn.net/download/H200102/12101806

一、OpenGL导入三维模型

1.期末的图形学作业要做三维机器人,要求:可以转换视角;光照;机器人可以移动(局部运动);
2.查看资料后发现,发现大部分都是采用画出机器人各部分(几何图形,正方形长方形圆柱体)后组装的方式,我采用导入现有模型(三维模型)的方式,这样的模型比我自己画出的模型更美观和好看,
3.之后再给机器人贴纹理,渲染环境,设置光照等,设置键盘响应函数移动机器人,使机器人身体运动,旋转观察机器人
4.总结:最终实现了能够立体观察机器人,机器人能够运动(左右上下移动),旋转,放大缩小机器人。
   但没有实现机器人的局部运动,比如只是机器人的手动或者脚动,机器人的纹理也没有贴(纹理部分自己没有学习,有空有心情再学,专门挑了一个不需要贴纹理的机器人)

二、实现步骤
方式一:使用deep exploration软件
1.先寻找一个obj模型,使用deep exploration将模型转换成cpp文件
2.将obj模型的cpp文件导入VS中,或者将cpp文件内容粘贴在VS中的项目中
3.deep exploration将模型转换成的cpp文件,是使用显示列表将模型画出来,显示列表存储了模型的顶点数据,光照材质等内容
4.在cpp文件中添加如下代码内容


#include <gl/glaux.h>
#include <gl/glu.h>
#include <GL/glut.h>
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
#include "math.h"
#include <stdio.h>int flag = 1;
double front_Point_x, front_Point_y, front_Point_z;
double pos_Up[3], pos_Down[3], pos_Motion[3];
double viewmatrix[16], modelviewmatrix[16];
#define GLUT_MIDDLE_UP_BUTTON 0x0003
#define GLUT_MIDDLE_DOWN_BUTTON 0x0004
float PI = 3.141592654;
int listnum;//导入变量
GLfloat xangle = 0.0;
GLfloat yangle = 0.0;
GLfloat oDistance = 5.0;
int cacheX = 0;
int cacheY = 0;
int xSpeed = 1;
int ySpeed = 1;
BOOL light = true; // 光源的开/关
BOOL lp = true; // L键按下了么?
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f }; //环境光参数
GLfloat LightDiffuse[] = { 0.5f, 0.5f, 0.5f, 1.0f }; // 漫射光参数,不要全设置为0
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f }; // 光源位置static GLfloat angle = 0.0;
static GLfloat movex = 0.0;
static GLfloat movey = 0.0;
static GLfloat len = 15.0;
static GLint x = 0.0, y = 0.0, z = 0.0;/*
该部分是cpp文件内容
*//*绘制*/
void motion(int x, int y) //鼠标响应事件
{if (x > cacheX){yangle = yangle - xSpeed;}if (x < cacheX){yangle = yangle + xSpeed;}if (y > cacheY){xangle = xangle + ySpeed;}if (y < cacheY){xangle = xangle - ySpeed;}glutPostRedisplay();cacheX = x;cacheY = y;
}
/*
void setView() //设置观察角度
{glRotatef(10, 1.0, 0.0, 0.0);   //设置opengl中绘制实体的自转方式,即物体如何旋转glRotatef(22, 0.0, 1.0, 0.0);glTranslatef(-20.5, -10.0, -55.0);/*沿X轴正方向平移x个单位(x是有符号数)沿Y轴正方向平移y个单位(y是有符号数)沿Z轴正方向平移z个单位(z是有符号数)glGetDoublev(GL_MODELVIEW_MATRIX, viewmatrix);
}
*/
void SetRC() //设置渲染
{glEnable(GL_LINE_SMOOTH);glEnable(GL_BLEND);glShadeModel(GL_SMOOTH);/*设置着色模式,解决实心图形内部空间颜色填充,平滑着色*/glFrontFace(GL_CW);glEnable(GL_LINE_SMOOTH);glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);/*设置颜色混合,透明度叠加*/glHint(GL_LINE_SMOOTH, GL_NICEST);    /* 设置反面为边缘绘制方式*/glEnable(GL_DEPTH_TEST);//glPolygonMode(GL_BACK, GL_FILL);     // 设置模型背面为实体//glPolygonMode(GL_BACK, GL_LINE);/*glPolygonMode(GL_FRONT, GL_FILL);           // 设置正面为填充方式glPolygonMode(GL_BACK, GL_LINE);            // 设置反面为边缘绘制方式glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式*/glEnable(GL_COLOR_MATERIAL);
}void renderWorld() //模拟场景
{glFrontFace(GL_CCW);     //逆时针表示正面//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);        设置多边形的正面和背面为实体,填充//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);       // 设置多边形的正面和背面为线性,不填充float oXhudu = PI / (180 / xangle); //沿着X轴旋转的角度float oYhudu = PI / (180 / yangle); //沿着Y轴旋转的角度//设置场景坐标GLfloat btm = oDistance * cos(oXhudu);GLfloat vpY = oDistance * sin(oXhudu);GLfloat vpX = btm * sin(oYhudu);GLfloat vpZ = btm * cos(oYhudu);if (fabs(xangle) < 90.0){gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  //观察}else{if (fabs(xangle) >= 270.0){if (fabs(xangle) >= 360.0){xangle = 0.0;}gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);}else{gluLookAt(vpX, vpY, vpZ, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);}}if (fabs(yangle) >= 360.0){yangle = 0;}//绘制场景坐标轴/*glLineWidth(1);glBegin(GL_LINES);glColor3f(1.0, 0.0, 0.0);glVertex3f(0.0, 0.0, 0.0);glVertex3f(200, 0, 0);glColor3f(0.0, 1.0, 0.0);glVertex3f(0.0, 0.0, 0.0);glVertex3f(0.0, 200, 0.0);glColor3f(0.0, 0.0, 1.0);glVertex3f(0.0, 0.0, 0.0);glVertex3f(0.0, 0.0, 200.0);glEnd();*/glColor3f(0.863, 0.863, 0.863);    //机器人的颜色glEnable(GL_LIGHTING);        //启用颜色混合glEnable(GL_LIGHT0);glGetDoublev(GL_MODELVIEW_MATRIX, modelviewmatrix);   //坐标变换glCallList(listnum);   // 执行显示列表
}//向上平移
void moveup()
{movey += 2.0;if (movey > 100.0)movey = 0.0;glutPostRedisplay();
}
//向下平移
void movedown()
{movey -= 2.0;if (movey < -100.0)movey = 0.0;glutPostRedisplay();
}
//向左平移
void moveleft()
{movex -= 2.0;if (movex < -100.0)movex = 0.0;glutPostRedisplay();
}
//向右平移
void moveright()
{movex += 2.0;if (movex > 100.0)movex = 0.0;glutPostRedisplay();
}
//放大
void zoom()
{len += 0.02;if (len > 20.0)len = 10.0;glutPostRedisplay();    /*glutPostRedisplay 标记当前窗口需要重新绘制*/
}
//收缩
void shrink()
{len -= 0.02;if (len < 1.0)len = 10.0;glutPostRedisplay();
}
//沿x轴旋转
void rotatex()
{z = 0.0;x = 1.0;y = 0.0;angle += 1.0;if (angle >= 360.0)angle = 0.0;glutPostRedisplay();
}
//沿y轴旋转
void rotatey()
{z = 0.0;y = 1.0;x = 0.0;angle += 5.0;if (angle >= 360.0)angle = 0.0;glutPostRedisplay();
}
//沿z轴旋转
void rotatez()
{z = 1.0;x = 0.0;y = 0.0;angle += 1.0;if (angle >= 360.0)angle = 0.0;glutPostRedisplay();
}
//沿xy轴旋转
void rotatexy()
{z = 0.0;y = 1.0;x = 1.0;angle += 1.0;if (angle >= 360.0)angle = 0.0;glutPostRedisplay();
}
//沿yz轴旋转
void rotateyz()
{z = 1.0;y = 1.0;x = 0.0;angle += 1.0;if (angle >= 360.0)angle = 0.0;glutPostRedisplay();
}
//沿xz轴旋转
void rotatexz()
{z = 1.0;y = 0.0;x = 1.0;angle += 1.0;if (angle >= 360.0)angle = 0.0;glutPostRedisplay();
}
//沿xyz轴旋转
void rotatexyz()
{z = 1.0;y = 1.0;x = 1.0;angle += 1.0;if (angle >= 360.0)angle = 0.0;glutPostRedisplay();
}void changeLine() {glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);       // 设置多边形的正面和背面为线性,不填充}
void changemodle() {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);       // 设置多边形的正面和背面为实体,填充}//定义键位
void specialKeyFunc(int key, int x, int y)
{switch (key){case GLUT_KEY_UP:moveup();break;case GLUT_KEY_DOWN:movedown();break;case GLUT_KEY_LEFT:moveleft();break;case GLUT_KEY_RIGHT:moveright();break;case GLUT_KEY_F1:zoom();break;case GLUT_KEY_F2:shrink();break;case GLUT_KEY_F3:rotatex();         //沿x轴旋转break;case GLUT_KEY_F4:rotatey();break;case GLUT_KEY_F5:rotatez();break;case GLUT_KEY_F6:rotatexy();break;case GLUT_KEY_F7:rotateyz();break;case GLUT_KEY_F8:rotatexz();break;case GLUT_KEY_F9:rotatexyz();break;case GLUT_KEY_F10:changeLine();break;case GLUT_KEY_F11:changemodle();break;default:break;}
}static void init()
{glClearColor(0.1f, 0.1f, 0.1f, 1.0f);   //设置窗体颜色}void Display(void)
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glColor3f(1.0, 1.0, 0.0);glPushMatrix();glTranslatef(movex, movey, 0.0);  //平移函数glScalef(9 * len, 9 * len, len);  //缩放函数glRotatef(angle, x, y, z);      //绘制实体的自转方式,即物体如何旋转renderWorld();glPopMatrix();glutSwapBuffers();  //该函数的功能是交换两个缓冲区指针,实现双缓冲
}void Reshape(int w, int h) //重新绘制场景
{GLfloat nRange = 100.0f;glViewport(0, 0, w, h);//表示这个视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。glMatrixMode(GL_PROJECTION);/*glMatrixMode()函数的参数,这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对“什么”进行操作了,这个“什么”在glMatrixMode的“()”里的选项(参数)有3种模式: GL_PROJECTION 投影, GL_MODELVIEW 模型视图, GL_TEXTURE 纹理.*/glLoadIdentity();if (w <= h)  //建立裁剪区域(左右下上近远){glOrtho(-nRange, nRange, -nRange * h / w, nRange*h / w, -100, 100);/*glOrtho(left, right, bottom, top, near, far), left表示视景体左面的坐标,right表示右面的坐标,bottom表示下面的,top表示上面的。*/}else{glOrtho(-nRange * w / h, nRange*w / h, -nRange, nRange, -100, 100);}glMatrixMode(GL_MODELVIEW);glLoadIdentity();
}void mouse(int btn, int state, int x, int y)
{if (btn == GLUT_RIGHT_BUTTON){if (state == GLUT_DOWN){if (light){glDisable(GL_LIGHT1); // 启用光源light = !light;}else{glEnable(GL_LIGHT1);light = !light;}}}glutPostRedisplay();//重新加载}//菜单
void menu() {cout << "-------------------------菜单-----------------------------------" << endl;cout << "----------------按住方向键左即向左运动------------------------" << endl;cout << "----------------按住方向键右即向右运动------------------------" << endl;cout << "----------------按住方向键上即向上运动------------------------" << endl;cout << "----------------按住方向键下即向下运动------------------------" << endl;cout << "----------------按住鼠标拖动即旋转----------------------------" << endl;cout << "----------------按住F1放大------------------------------------" << endl;cout << "----------------按住F2缩小------------------------------------" << endl;cout << "----------------按住F3绕x轴旋转------------------------------" << endl;cout << "----------------按住F4绕y轴旋转------------------------------" << endl;cout << "----------------按住F5绕z轴旋转------------------------------" << endl;cout << "----------------按住F6绕xy轴旋转------------------------------" << endl;cout << "----------------按住F7绕yz轴旋转------------------------------" << endl;cout << "----------------按住F8绕xz轴旋转------------------------------" << endl;cout << "----------------按住F9绕xyz轴旋转------------------------------" << endl;cout << "----------------按住F10后点击模型,变为线框图-----------------" << endl;cout << "----------------按住F11后点击模型,填充模型--------------------" << endl;}int main(int argc, char *argv[]) //主函数
{glutInit(&argc, argv);menu();   //打印控制台菜单glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);//定义窗口的显示模式,使用RGB染色的模式,双缓冲模式glutInitWindowPosition(10, 10);glutInitWindowSize(800, 800);glutCreateWindow("丑不拉几的机器人");glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // 设置环境光glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // 设置漫射光glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // 光源位置glEnable(GL_LIGHT1); // 启用光源init();listnum = Gen3DObjectList();  //glutDisplayFunc(&Display);glutReshapeFunc(&Reshape);glutSpecialFunc(specialKeyFunc);   //键盘响应SetRC();glutMouseFunc(mouse);glutMotionFunc(&motion);glutMainLoop();return 0;
}

5.cpp文件部分内容:

struct sample_MATERIAL
{GLfloat ambient[3];       //环境光颜色GLfloat diffuse[3];       //漫反射光GLfloat specular[3];      //镜面反射光GLfloat emission[3];      //自体发光的物体GLfloat alpha;            //描述物体在给定像素的不透明度GLfloat phExp;int texture;            //纹理
};
//材质结构体变量
static sample_MATERIAL materials[13] = {};
//存储所有顶点坐标
static GLfloat vertices[35125][3] = {};
存储所有法向量
static GLfloat normals[40950][3] = {};
存储所有纹理坐标
static GLfloat textures[10110][2] = {};
//材质索引,用于获取材质模型
static int material_ref[510][2] = {};
//使用OpenGL命令无定义(三角)面的颜色
void MyMaterial(GLenum mode, GLfloat * f, GLfloat alpha)
{}//根据模式选择材质结构体的相应变量
void SelectMaterial(int i)
{};
//显示列表
GLint Gen3DObjectList()
{int i;int j;GLint lid = glGenLists(1);    //1个空显示列表,生成显示类表int mcount = 0;int mindex = 0;glNewList(lid, GL_COMPILE);         //创建显示列表glBegin(GL_TRIANGLES);                //开始绘图//每3分坐标相连接for (i = 0; i < sizeof(face_indicies) / sizeof(face_indicies[0]); i++){if (!mcount){SelectMaterial(material_ref[mindex][0]);mcount = material_ref[mindex][1];mindex++;}mcount--;for (j = 0; j < 3; j++){//载入纹理、法线、顶点向量int vi = face_indicies[i][j];int ni = face_indicies[i][j + 3];//Normal indexint ti = face_indicies[i][j + 6];//Texture indexglNormal3f(normals[ni][0], normals[ni][1], normals[ni][2]);glTexCoord2f(textures[ti][0], textures[ti][1]);glVertex3f(vertices[vi][0], vertices[vi][1], vertices[vi][2]);}}glEnd();          //绘图结束glEndList();         //结束显示列表return lid;
};

6.运行结果
1)控制台菜单

2)机器人

3)机器人

4)按F10后点击模型,转换为线框图,按F11后点击模型,转换为实心形态

方式二:使用view 3DS软件
1.使用VIEW3DS软件将三维模型的MAX文件转换为gl文件和.h文件
2.其他内容和使用deep exploration软件一样,只是需要将gl文件和.h文件放在VS项目下,并在cpp文件中添加头文件#include"Robot.h" /*Robot.h文件是模型转换后的文件*/
在主函数中载入模型部分代码:
Robot robot; listnum = GL3DS_initialize_Robot(); //载入Robot

3.运行效果:

三、错误提示

1.VS2017利用fopen和fscanf读取文件时出现以下错误信息:
C4996 ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

解决办法:
项目——属性——C/C++——预处理器——预处理器定义——右侧下拉框中“编辑”——在第一个编辑框中添加_CRT_SECURE_NO_WARNINGS——大功告成


2.在vs中char类型的实参与LPCWSTR类型的形参类型不兼容怎么解决;
“char *” 类型的实参与 “LPCTSTR” 类型的形参不兼容

解决办法:
在 项目 - 属性 - 常规 中把字符集修改为“未设置”即可。

能将参数 1 从“const char [11]”转换为“LPCWSTR”

解决方法:
选中项目,然后点击属性——>配置属性——>常规——>项目默认值——>字符集,选为“使用多字节字符集"


3.复制粘贴代码时,可能出现错误,但找不到原因,比如提示main函数错误,
可以换一下粘贴的顺序,先粘贴main函数和头文件部分,在粘贴函数其他部分

OpenGL三维模型+常见错误相关推荐

  1. VS2019运行OpenGL时出现的常见错误及解决办法

    OpenGL程序在低版本的VS中运行成功,但在VS2019中运行却出现各种错误,以下是常见错误的解决办法.(文章结尾有库的链接哟~) 问题一:无法打开文件"glaux.lib" 解 ...

  2. Golang 要注意的陷阱和常见错误

    原文: 50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs 翻译: Go的50度灰:新Golang开发者要 ...

  3. Python运行的17个时新手常见错误小结

    Python运行的17个时新手常见错误小结 1 发布时间:『 2017-11-04 11:20 』     帖子类别:『人工智能』  阅读次数:8803 (本文『Python运行的17个时新手常见错误 ...

  4. 极客新闻——16、数据库设计中的5个常见错误

    本文笔记全部来自<极客新闻>--新鲜的技术资讯.权威的趋势剖析.别样的技术洞察 本文作者总结了数据库设计中的5个常见错误,以供开发人员参考. 1.糟糕的预规划 好的数据库是深思熟虑的结果, ...

  5. 构建微服务时的三大常见错误

      来自:分布式实验室 公众号,作者:解博 想在网上挨骂,最简单的方法就是写点关于微服务架构的东西.每个人对微服务都有自己的一套见解:无论我们是赞扬还是批评,总会有人跳出来强调"你错了&qu ...

  6. 稳定性专题 | Spring Boot 常见错误及解决方法

    导读 『StabilityGuide』是阿里多位阿里技术工程师共同发起的稳定性领域的知识库开源项目,涵盖性能压测.故障演练.JVM.应用容器.服务框架.流量调度.监控.诊断等多个技术领域,以更结构化的 ...

  7. 机器学习“七宗罪”:影响可信度的七个常见错误

    机器学习是一个伟大的工具,它正在改变我们的世界.在许多优秀的应用中,机器学习(尤其是深度学习)比传统方法优越得多.从用于图像分类的Alex-Net到用于图像分割的U-Net,人们看到了计算机视觉和医学 ...

  8. A/B测试中我们都会犯的十个常见错误

    2019-11-29 20:51:46 作者:Romain AYRES 编译:ronghuaiyang 导读 这篇博客文章的目的不是告诉你在运行A/B测试时应该做什么,而是告诉你不应该做什么. &qu ...

  9. ASP.NET常见错误,原因及解决方法(2003版)_不断更新.....

    [标题]             ASP.NET常见错误,原因及解决方法[错误提示]    异常详细信息: System.Net.WebException: 请求因 HTTP 状态 401 失败:Un ...

最新文章

  1. 前景背景分割——ostu算法的原理及实现 OpenCV (八)
  2. C#拉姆达(=)表达式
  3. 2019年工信部重点实验室名单公布 涵盖卫星导航及人工智能等多个领域
  4. android studio 自动try,Catch Try让我在Android Studio调试中感到困惑
  5. Spring Boot2.x-08Spring Boot2.1.2 整合 Mybatis1.3.2 + 通用Mapper2.1.4 + PageHelper1.2.10 + Druid 1.1.10
  6. 【MM模块】Procurement for Stock Material 库存型物料采购相关
  7. ffmpeg.exe 笔记
  8. 宜创科技:低代码技术赋能企业数字化
  9. es mysql in操作_es 常用操作
  10. oracle ebs 期间 打开,ORACLE EBS重新打开关闭库存期间
  11. visual studio code(vscode)的使用(快捷键)
  12. “领跑者”计划倒逼光伏产业升级效果显现
  13. 联通盒子系统服务器,联通IPTV盒子刷机方法,实现软件任意安装
  14. python批量tif文件转化jpg文件格式
  15. visual C#(二十五)实现UWP应用的用户界面
  16. 心酸的两天(1):Nacos 启动后输入默认密码后:“用户名或密码错误”
  17. 求原谅---好久没更新了
  18. 一口气带你学会Redis升级后的几种数据类型,效率daydayup
  19. python控制苹果手机触摸屏失灵怎么办_苹果手机触摸屏失灵怎么办
  20. android x86 5.1 微信,微信5.1终于来了!微信5.1安卓版正式发布

热门文章

  1. RGB,YUV的来历及其相互转换
  2. java jsp页面传值_JSP 页面传值方法总结
  3. GPGPU基础(二):GPGPU需要用到的OpenGL概念
  4. [转]git图解(3):分支操作
  5. 过年了!!年前最后一更,2017年总结
  6. 权威数据来了,中国到底有多少个程序员?
  7. 权证是什么意思?股票期权证是什么意思?
  8. 汽车材料QC/T 944-2013ELV中多溴联苯(PBBs)和多溴二苯醚(PBDEs)的检测
  9. 猫眼电影MySQL数据库怎么写_Python3爬取猫眼电影榜并将数据存入MySql
  10. L1 - Learn 8 Phrasal Verbs for opening: pop open, peel off, flip up…