1 Star 0 Fork 0

wsw/Code

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
draw3d.cpp 16.54 KB
一键复制 编辑 原始数据 按行查看 历史
wsw 提交于 2024-01-03 23:35 . gl2
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
#include <iostream>
#include <fstream>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <GL/glut.h>
#include <math.h>
#include <string>
#include "structure.hpp"
#include <vector>
#define GLUT_WHEEL_UP 3 // 定义滚轮操作
#define GLUT_WHEEL_DOWN 4
using namespace std;
// 1. 读取obj文件
// 2. 读取obj文件中的顶点和面
// 3. 读取obj文件中的顶点和面的法向量
// 4. 读取obj文件中的顶点和面的纹理坐标
// 5. 读取obj文件中的顶点和面的颜色
// 6. 读取obj文件中的顶点和面的材质
// 显示obj文件
// 1. 显示顶点
// 2. 显示面
// 3. 显示顶点的法向量
// 4. 显示面的法向量
// 5. 显示顶点的纹理坐标
// 6. 显示面的纹理坐标
// 7. 显示顶点的颜色
// 8. 显示面的颜色
// 9. 显示顶点的材质
// 10. 显示面的材质
// 鼠标交互
// 1. 平移
// 2. 旋转
// 3. 缩放
struct MyTraits : public OpenMesh::DefaultTraits{
typedef OpenMesh::Vec3d Point;
typedef OpenMesh::Vec3d Normal;
typedef OpenMesh::Vec2d TexCoord2D;
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::TexCoord2D);
FaceAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::TexCoord2D);
};
// 定义一个Mymesh类,继承自OpenMesh::TriMesh_ArrayKernelT
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
struct PIC
{
vector<P3> vertex; // 顶点
vector<N> normal; // 法向量
vector<T> texture; // 纹理坐标
vector<F> face; // 面
};
// 定义文件名
string filename = "/home/wsw/code/GL2/model/bunny.obj";
// 相机参数
double distance_z = 0.0f;
GLuint showPointList, showWireList,showFaceList;
// 定义是否显示线框
bool showPoint = false;
bool showFace = true;
bool showWire = false;
bool myNorm = false; // 获取自己计算的法向量
vector<N> myNormal;
// 定义一个MyMesh对象
MyMesh mesh;
// 定义一个PIC对象
PIC pic;
// 定义鼠标控制的超参数
int mousestate;
GLfloat Oldx = 0.0f; // 鼠标按下时的坐标
GLfloat Oldy = 0.0f;
float xRot = 0.0f; // 旋转角度
float yRot = 0.0f;
float zRot = 0.0f;
float tx = 0.0f; // 平移距离
float ty = 0.0f;
float scale = 1.0f; // 缩放比例
vector<N> caledNorm;
void readObj(string file_name){
// 读取obj文件
OpenMesh::IO::Options opt;
if (!OpenMesh::IO::read_mesh(mesh, file_name, opt))
{
std::cout << "read error\n";
exit(1);
}
// 读取obj文件中的顶点和面
std::cout << "read " << file_name << " success\n";
std::cout << "vertex num: " << mesh.n_vertices() << endl;
std::cout << "face num: " << mesh.n_faces() << endl;
std::cout << "edge num: " << mesh.n_edges() << endl;
}
void readObjGL(string filename)
{
// cout << "Reaad" << endl;
ifstream ifs(filename);
string s;
while (ifs >> s)
{
if (s == "v")
{
double x, y, z;
ifs >> x >> y >> z;
pic.vertex.push_back({x / 1000, y / 1000, z / 1000});
}
else if (s == "vn")
{
double x, y, z;
ifs >> x >> y >> z;
pic.normal.push_back({x, y, z});
}
else if (s == "vt")
{
double x, y;
ifs >> x >> y;
pic.texture.push_back({x, y});
}
else if (s == "f")
{
int v[3], t[3], n[3];
char c;
for (int i = 0; i < 3; i++)
{
ifs >> v[i] >> c >> c >> n[i];
// cout << v[i] << c << c << n[i] << " ";
t[i] = 0;
}
// cout << endl;
pic.face.push_back(F(v, t, n));
}
}
}
GLdouble* myscale(MyMesh::Point data){
GLdouble* p;
p[0] = data[0] / 1000;
p[1] = data[1] / 1000;
p[2] = data[2] / 1000;
return p;
}
void GenList(){
cout << "Genlist " << endl;
mesh.request_vertex_normals();
// Add face normals as default property
mesh.request_face_normals();
// let the mesh update the normals
mesh.request_halfedge_normals();
mesh.update_normals();
cout << "Genlist" << endl;
glShadeModel(GL_SMOOTH);
showFaceList = glGenLists(1);
showWireList = glGenLists(1);
showPointList = glGenLists(1);
int temp = mesh.n_edges();
// SHOW WIRE
glNewList(showWireList, GL_COMPILE);
glDisable(GL_LIGHTING);
glLineWidth(1.0f);
glColor3f(0.5f, 0.5f, 0.5f);
glBegin(GL_LINES);
for (MyMesh::HalfedgeIter he_it = mesh.halfedges_begin(); he_it != mesh.halfedges_end(); ++he_it) {
glVertex3d(mesh.point(mesh.from_vertex_handle(*he_it))[0] / 1000, mesh.point(mesh.from_vertex_handle(*he_it))[1] / 1000, mesh.point(mesh.from_vertex_handle(*he_it))[2] / 1000);
glVertex3d(mesh.point(mesh.to_vertex_handle(*he_it))[0] / 1000, mesh.point(mesh.to_vertex_handle(*he_it))[1] / 1000, mesh.point(mesh.to_vertex_handle(*he_it))[2] / 1000);
}
glEnd();
glEnable(GL_LIGHTING);
glEndList();
// SHOW POINT
glNewList(showPointList, GL_COMPILE);
glDisable(GL_LIGHTING);
glLineWidth(1.0f);
glColor3f(0.5f, 0.5f, 0.5f);
glBegin(GL_POINTS);
for (MyMesh::VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it) {
glVertex3d(mesh.point(*v_it)[0] / 1000, mesh.point(*v_it)[1] / 1000, mesh.point(*v_it)[2] / 1000);
}
glEnd();
glEnable(GL_LIGHTING);
glEndList();
glNewList(showFaceList, GL_COMPILE);
static GLfloat Ambient[] = {0.33f, 0.22f, 0.03f, 1.0f};
static GLfloat Diffuse[] = {0.78f, 0.57f, 0.11f, 1.0f};
static GLfloat Specular[] = {0.99f, 0.91f, 0.81f, 1.0f};
static GLfloat Emission[] = {0.000f, 0.000f, 0.000f, 1.0f};
static GLfloat Shine = 10.800f;
// 指定属性
glMaterialfv(GL_FRONT, GL_AMBIENT, Ambient); // 环境光
glMaterialfv(GL_FRONT, GL_DIFFUSE, Diffuse); // 散射光
glMaterialfv(GL_FRONT, GL_SPECULAR, Specular); // 镜面反射光
glMaterialfv(GL_FRONT, GL_EMISSION, Emission); // 发射光
glMaterialf(GL_FRONT, GL_SHININESS, Shine); // 高光指数
for (MyMesh::FaceIter f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it) {
glBegin(GL_TRIANGLES);
MyMesh::FaceVertexIter fv_it = mesh.fv_iter(*f_it);
for (MyMesh::FaceVertexIter fv_it = mesh.fv_iter(*f_it); fv_it.is_valid(); ++fv_it) {
glNormal3f(mesh.normal(*fv_it)[0], mesh.normal(*fv_it)[1], mesh.normal(*fv_it)[2]);
glVertex3f(mesh.point(*fv_it)[0] / 1000, mesh.point(*fv_it)[1] / 1000, mesh.point(*fv_it)[2] / 1000);
}
glEnd();
}
glEndList();
}
// 生成显示列表
void GenListGL()
{
glShadeModel(GL_SMOOTH);
showFaceList = glGenLists(1);
showWireList = glGenLists(1);
showPointList = glGenLists(1);
// glPolygonMode(GL_FRONT, GL_FILL);
std::cout << "face num: " << pic.face.size() << endl;
glNewList(showPointList, GL_COMPILE);
glDisable(GL_LIGHTING);
glBegin(GL_POINTS);
glColor3f(0.5f, 0.5f, 0.5f);
glPointSize(2.0f);
for (int i = 0; i < pic.vertex.size(); i++)
{
// glNormal3dv(pic.normal[i].N);
// cout << "draw Point" << endl;
glVertex3dv(pic.vertex[i].P);
}
glEnd();
glEndList();
glNewList(showWireList, GL_COMPILE);
glColor3f(0.5f, 0.5f, 0.5f);
glLineWidth(0.5f);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
for (int i = 0; i < pic.face.size(); i++)
{
// cout << "draw face" << endl;
for (int j = 0; j < 2; j++)
{
glNormal3dv(pic.normal[pic.face[i].n[j] - 1].N);
glVertex3dv(pic.vertex[pic.face[i].v[j] - 1].P);
glNormal3dv(pic.normal[pic.face[i].n[j+1] - 1].N);
glVertex3dv(pic.vertex[pic.face[i].v[j+1] - 1].P);
}
}
glEnd();
glEndList();
glNewList(showFaceList, GL_COMPILE);
glEnable(GL_LIGHTING);
for (int i = 0; i < pic.face.size(); i++)
{
glBegin(GL_TRIANGLES);
// cout << "draw face" << endl;
for (int j = 0; j < 3; j++)
{
glNormal3dv(pic.normal[pic.face[i].n[j] - 1].N);
glVertex3dv(pic.vertex[pic.face[i].v[j] - 1].P);
}
glEnd();
}
glEndList();
}
// 初始化场景设置光源(材质)
void initScene()
{
void calNormFace();
// readObj(filename);
readObjGL(filename);
calNormFace();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// glShadeModel(GL_SMOOTH);
// 设置光源
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
// 设置多边形正面的环境光和散射光材料属性,追踪glColor
// glEnable(GL_COLOR_MATERIAL); 画蛇添足!!!
// 设置多边形正面的环境光和散射光材料属性,追踪glColor
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// 设置材质
static GLfloat Ambient[] = {0.33f, 0.22f, 0.03f, 1.0f};
static GLfloat Diffuse[] = {0.78f, 0.57f, 0.11f, 1.0f};
static GLfloat Specular[] = {0.99f, 0.91f, 0.81f, 1.0f};
static GLfloat Emission[] = {0.000f, 0.000f, 0.000f, 1.0f};
static GLfloat Shine = 27.800f;
// 指定属性
glMaterialfv(GL_FRONT, GL_AMBIENT, Ambient); // 环境光
glMaterialfv(GL_FRONT, GL_DIFFUSE, Diffuse); // 散射光
glMaterialfv(GL_FRONT, GL_SPECULAR, Specular); // 镜面反射光
glMaterialfv(GL_FRONT, GL_EMISSION, Emission); // 发射光
glMaterialf(GL_FRONT, GL_SHININESS, Shine); // 高光指数
// 生成显示列表
GenListGL();
// GenList();
}
// 使用gl绘制场景
void Display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// set camera
glTranslatef(0.0f, 0.0f, distance_z);
glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glTranslatef(tx, ty, 0.0f);
glScalef(scale, scale, scale); // 缩放
glEnable(GL_LIGHTING);
if(myNorm){
glBegin(GL_TRIANGLES);
// glEnable(GL_LIGHTING);
cout << "Draw my tri." << endl;
for (int i = 0; i < pic.face.size(); i++)
{
// cout << "draw face" << endl;
for (int j = 0; j < 3; j++)
{
glNormal3dv(myNormal[pic.face[i].v[j] - 1].N);
glVertex3dv(pic.vertex[pic.face[i].v[j] - 1].P);
}
}
glEnd();
}
// 显示列表
if (showFace && !myNorm)
{
// glPolygonMode(GL_FRONT, GL_FILL);
glCallList(showFaceList);
std::cout << "draw face" << endl;
}
if (showPoint && !myNorm)
{
// glPolygonMode(GL_FRONT, GL_POINT);
glCallList(showPointList);
std::cout << "draw point" << endl;
}
if(showWire && !myNorm){
glCallList(showWireList);
std::cout << "draw wire" << endl;
}
// 刷新屏幕
glFlush();
glutSwapBuffers();
}
// 鼠标交互
void myMouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
mousestate = 1;
Oldx = x;
Oldy = y;
std::cout << "Old x: " << x << " Old y" << y << endl;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
mousestate = 0;
// 滚轮事件
if (state == GLUT_UP && button == 3)
{
// 滑轮向上滑,则scale减小
std::cout << "scale += 0.01" << endl;
scale += 0.010;
}
if (state == GLUT_UP && button == 4)
{
// 滑轮向下滑,则scale增加
std::cout << "scale -= 0.01" << endl;
scale -= 0.010;
}
// 标记当前窗口需要重新绘制
glutPostRedisplay();
}
// 鼠标运动时
void onMouseMove(int x, int y)
{
if (mousestate)
{
// x对应y是因为对应的是法向量
yRot += x - Oldx;
glutPostRedisplay(); // 标记当前窗口需要重新绘制
Oldx = x;
xRot += y - Oldy;
glutPostRedisplay();
Oldy = y;
}
}
// 当窗体改变大小的时候,改变窗口大小时保持图形比例v
void myReshape(GLint w, GLint h)
{
glViewport(0, 0, static_cast<GLsizei>(w), static_cast<GLsizei>(h));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w > h)
glOrtho(-static_cast<GLdouble>(w) / h, static_cast<GLdouble>(w) / h, -1.0, 1.0, -100.0, 100.0);
else
glOrtho(-1.0, 1.0, -static_cast<GLdouble>(h) / w, static_cast<GLdouble>(h) / w, -100.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void KeyboardFunc(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_INSERT:
if (showFace == true)
{
showFace = false;
showPoint = true;
std::cout << "切换显示模式为Point" << endl;
}
else if (showPoint == true)
{
showPoint = false;
showWire = true;
std::cout << "切换显示模式为Wire" << endl;
}
else if(showWire == true)
{
showWire = false;
showFace = true;
std::cout << "切换显示模式为Face" << endl;
}
break;
case GLUT_KEY_LEFT:
tx -= 0.5;
break;
case GLUT_KEY_RIGHT:
tx += 0.5;
break;
case GLUT_KEY_UP:
ty -= 0.5;
break;
case GLUT_KEY_DOWN:
ty += 0.5;
case GLUT_KEY_PAGE_DOWN:
myNorm = true;
break;
case GLUT_KEY_PAGE_UP:
myNorm = false;
break;
default:
break;
}
glutPostRedisplay();
}
N cross(P3 v1, P3 v2, P3 v3){
N n;
P3 v12 = {v2.P[0] - v1.P[0], v2.P[1] - v1.P[1], v2.P[2] - v1.P[2]};
P3 v13 = {v3.P[0] - v1.P[0], v3.P[1] - v1.P[1], v3.P[2] - v1.P[2]};
n.N[0] = v12.P[1] * v13.P[2] - v12.P[2] * v13.P[1];
n.N[1] = v12.P[2] * v13.P[0] - v12.P[0] * v13.P[2];
n.N[2] = v12.P[0] * v13.P[1] - v12.P[1] * v13.P[0];
double len = sqrt(n.N[0] * n.N[0] + n.N[1] * n.N[1] + n.N[2] * n.N[2]);
n.N[0] = n.N[0] / len;
n.N[1] = n.N[1] / len;
n.N[2] = n.N[2] / len;
return n;
}
N mean(P3 v1, P3 v2, P3 v3){
N n;
n.N[0] = (v1.P[0] + v2.P[0] + v3.P[0]) / 3;
n.N[1] = (v1.P[1] + v2.P[1] + v3.P[1]) / 3;
n.N[2] = (v1.P[2] + v2.P[2] + v3.P[2]) / 3;
double len = sqrt(n.N[0] * n.N[0] + n.N[1] * n.N[1] + n.N[2] * n.N[2]);
n.N[0] = n.N[0] / len;
n.N[1] = n.N[1] / len;
n.N[2] = n.N[2] / len;
return n;
}
void calNormFace(){
cout << pic.vertex.size()<< endl;
cout << pic.normal.size()<< endl;
for(int i = 0; i < pic.face.size(); i++){
P3 v1 = pic.vertex[pic.face[i].n[0] - 1];
P3 v2 = pic.vertex[pic.face[i].n[1] - 1];
P3 v3 = pic.vertex[pic.face[i].n[2] - 1];
N n = cross(v1, v2, v3);
// N n = mean(v1, v2, v3);
caledNorm.push_back(n);
}
for(int i = 0; i < pic.vertex.size(); i++){
N n;
n.N[0] = 0;
n.N[1] = 0;
n.N[2] = 0;
int p1, p2, p3, n0;
n0 = 0;
for(int j = 0; j < pic.face.size(); j++){
p1 = pic.face[i].n[0] - 1;
p2 = pic.face[i].n[1] - 1;
p3 = pic.face[i].n[2] - 1;
if(p1 == i || p2 == i || p3 == i){
n0+=1;
n.N[0] += caledNorm[j].N[0];
n.N[1] += caledNorm[j].N[1];
n.N[2] += caledNorm[j].N[2];}
}
n.N[0] /= n0;
n.N[1] /= n0;
n.N[2] /= n0;
myNormal.push_back(n);
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH); // GLUT_Double 表示使用双缓存而非单缓存
glutInitWindowPosition(100, 100);
glutInitWindowSize(1000, 1000);
glutCreateWindow("Mesh Viewer");
initScene();
std::cout << "vertex.size " << pic.vertex.size() << endl; // 2588
std::cout << "calNorm.size " << caledNorm.size() << endl; // 5146
std::cout << "pic.face.size " << pic.face.size() << endl; // 5146
// for (int i = 0; i < pic.face.size(); i++){
// // cout << pic.normal[i].N[0] << " " << pic.normal[i].N[1] << " " << pic.normal[i].N[2] << endl;
// cout << pic.face[i].n[0] << " " << pic.face[i].n[1] << " " << pic.face[i].n[2] << endl;
// cout << pic.face[i].v[0] << " " << pic.face[i].v[1] << " " << pic.face[i].v[2] << endl;
// // cout << pic.normal[pic.face[i].n[0]].N[0] << " " << pic.normal[pic.face[i].n[0]].N[1] << " " << pic.normal[pic.face[i].n[0]-1].N[2] << endl;
// // }
// }
glutMouseFunc(myMouse);
glutSpecialFunc(KeyboardFunc);
glutMotionFunc(onMouseMove); // 鼠标移动的时候的函数
glutReshapeFunc(myReshape);
glutDisplayFunc(Display);
// readObj(filename);
glutMainLoop();
// valid the norm caled by calNorm
return 0;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/wswsw123/code.git
git@gitee.com:wswsw123/code.git
wswsw123
code
Code
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385