#include <GL\glut.h>\n#include \n#include \n#include \n\nusing namespace std;\n\nstruct Vertex {\n float x, y, z;\n};\n\nstruct Normal {\n float x, y, z;\n};\n\nstruct Face {\n int a, b, c;\n};\n\nvector vertices;\nvector normals;\nvector faces;\n\nvoid loadMesh(const char* filename) {\n ifstream file(filename);\n if (!file) {\n cerr << "Error opening file: " << filename << endl;\n exit(1);\n }\n\n string line;\n while (getline(file, line)) {\n if (line.substr(0, 2) == "v ") {\n Vertex vertex;\n sscanf(line.c_str(), "v %f %f %f", &vertex.x, &vertex.y, &vertex.z);\n vertices.push_back(vertex);\n }\n else if (line.substr(0, 2) == "vn") {\n Normal normal;\n sscanf(line.c_str(), "vn %f %f %f", &normal.x, &normal.y, &normal.z);\n normals.push_back(normal);\n }\n else if (line.substr(0, 2) == "f ") {\n Face face;\n sscanf(line.c_str(), "f %d//%*d %d//%d %d//%d", &face.a, &face.b, &face.c);\n faces.push_back(face);\n }\n }\n}\n\nvoid calculateNormals() {\n vector<vector> adjacency(vertices.size());\n vector vertexNormals(vertices.size(), {0.0f, 0.0f, 0.0f});\n\n for (const auto& face : faces) {\n adjacency[face.a - 1].push_back(face.b - 1);\n adjacency[face.a - 1].push_back(face.c - 1);\n adjacency[face.b - 1].push_back(face.a - 1);\n adjacency[face.b - 1].push_back(face.c - 1);\n adjacency[face.c - 1].push_back(face.a - 1);\n adjacency[face.c - 1].push_back(face.b - 1);\n }\n\n for (int i = 0; i < vertices.size(); i++) {\n const auto& vertex = vertices[i];\n const auto& adj = adjacency[i];\n Normal normal = {0.0f, 0.0f, 0.0f};\n\n for (const auto& neighborIndex : adj) {\n const auto& neighbor = vertices[neighborIndex];\n normal.x += neighbor.y - vertex.y;\n normal.y += neighbor.z - vertex.z;\n normal.z += neighbor.x - vertex.x;\n }\n\n float length = sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z);\n normal.x /= length;\n normal.y /= length;\n normal.z /= length;\n\n vertexNormals[i] = normal;\n }\n\n normals = move(vertexNormals);\n}\n\nvoid display() {\n glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n glLoadIdentity();\n gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);\n\n glRotatef(15, 1.0, 0.0, 0.0);\n glRotatef(30, 0.0, 1.0, 0.0);\n\n glBegin(GL_TRIANGLES);\n for (const auto& face : faces) {\n const auto& vertexA = vertices[face.a - 1];\n const auto& vertexB = vertices[face.b - 1];\n const auto& vertexC = vertices[face.c - 1];\n\n const auto& normalA = normals[face.a - 1];\n const auto& normalB = normals[face.b - 1];\n const auto& normalC = normals[face.c - 1];\n\n glNormal3f(normalA.x, normalA.y, normalA.z);\n glVertex3f(vertexA.x, vertexA.y, vertexA.z);\n\n glNormal3f(normalB.x, normalB.y, normalB.z);\n glVertex3f(vertexB.x, vertexB.y, vertexB.z);\n\n glNormal3f(normalC.x, normalC.y, normalC.z);\n glVertex3f(vertexC.x, vertexC.y, vertexC.z);\n }\n glEnd();\n\n glColor3f(0.0, 0.0, 0.0);\n glBegin(GL_LINES);\n for (const auto& face : faces) {\n const auto& vertexA = vertices[face.a - 1];\n const auto& vertexB = vertices[face.b - 1];\n const auto& vertexC = vertices[face.c - 1];\n\n glVertex3f(vertexA.x, vertexA.y, vertexA.z);\n glVertex3f(vertexB.x, vertexB.y, vertexB.z);\n\n glVertex3f(vertexB.x, vertexB.y, vertexB.z);\n glVertex3f(vertexC.x, vertexC.y, vertexC.z);\n\n glVertex3f(vertexC.x, vertexC.y, vertexC.z);\n glVertex3f(vertexA.x, vertexA.y, vertexA.z);\n }\n glEnd();\n\n glutSwapBuffers();\n}\n\nvoid reshape(int width, int height) {\n glViewport(0, 0, width, height);\n glMatrixMode(GL_PROJECTION);\n glLoadIdentity();\n gluPerspective(45.0, (GLfloat) width / (GLfloat) height, 0.1, 100.0);\n glMatrixMode(GL_MODELVIEW);\n}\n\nint main(int argc, char argv) {\n if (argc < 2) {\n cerr << "Usage: " << argv[0] << " [mesh.obj]" << endl;\n return 1;\n }\n\n loadMesh(argv[1]);\n calculateNormals();\n\n glutInit(&argc, argv);\n glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);\n glutInitWindowSize(800, 600);\n glutCreateWindow("Mesh Viewer");\n glEnable(GL_DEPTH_TEST);\n glClearColor(1.0, 1.0, 1.0, 1.0);\n glShadeModel(GL_SMOOTH);\n glEnable(GL_LIGHTING);\n glEnable(GL_LIGHT0);\n GLfloat lightPosition[] = {0.0, 0.0, 5.0, 1.0};\n glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);\n glutDisplayFunc(display);\n glutReshapeFunc(reshape);\n glutMainLoop();\n\n return 0;\n