#include "Angel.h" #include #include #include #define PARAMS_DEBUG_PRINT false const int texNumTriangles = 64770; const int cowNumTriangles = 5804; const int NumTriangles = texNumTriangles + cowNumTriangles; const int NumVertices = 3 * NumTriangles; const int TextureWidth = 256; const int TextureHeight = 128; typedef Angel::vec4 point4; typedef Angel::vec4 color4; // Texture objects and storage for texture image GLuint textures[1]; GLubyte image[TextureWidth][TextureHeight][3]; // Vertex data arrays point4 points[NumVertices]; vec2 tex_coords[NumVertices]; // fog params GLuint fog; // is_foggy uniform GLuint eye_pos; int foggy = 1; // Viewing transformation parameters GLfloat theta = 0.0; GLfloat phi = 0.0; GLfloat tau = 0.0; GLfloat eye_x = 0.0; GLfloat eye_y = 0.25; GLfloat eye_z = 0.1; GLfloat eye_w = 1.0; GLfloat at_x; GLfloat at_y; GLfloat at_z; GLfloat at_w; GLuint model_view; // model-view matrix uniform shader variable location // Projection transformation parameters GLfloat left = -0.01, right = 0.01; GLfloat bottom = -0.01, top = 0.01; GLfloat zNear = 0.1, zFar = 2.0; GLuint projection; // projection matrix uniform shader variable location //---------------------------------------------------------------------------- void load_model(const std::string &file_name, bool no_tex = false, float x_offset = 0.0f, float y_offset = 0.0f, float z_offset = 0.0f) { std::vector vertices; std::vector tex_cods; std::fstream s(file_name, std::fstream::in); static int index = 0; if (!s.is_open()) { std::cerr << "failed to open" << file_name << std::endl; } else { std::string t; float x, y, z; int a, b, c; int num = 0; while (s >> t) { if (t == "v") { // vertices s >> x >> y >> z; vertices.emplace_back(x / 50.0f + x_offset, z / 50.0f + z_offset, y / 50.0f + y_offset, 1.0); } else if (t == "vt") { s >> x >> y; tex_cods.emplace_back(x, y); } else if (t == "f") { s >> a >> b >> c; a--; b--; c--; points[index] = vertices[a]; if (no_tex) { tex_coords[index] = {20.0, 0.0}; } else { tex_coords[index] = tex_cods[a]; } index++; points[index] = vertices[b]; if (no_tex) { tex_coords[index] = {20.0, 0.0}; } else { tex_coords[index] = tex_cods[b]; } index++; points[index] = vertices[c]; if (no_tex) { tex_coords[index] = {20.0, 0.0}; } else { tex_coords[index] = tex_cods[c]; } index++; num++; } } std::cout << "Load model:" << file_name << std::endl; std::cout << "There are " << vertices.size() << "vertice(s)" << ", " << tex_cods.size() << "tex cor(s)" << std::endl << "There are " << num << "fragment(s)" << std::endl; s.close(); } } //---------------------------------------------------------------------------- void load_tex(const std::string &file_name) { char cline[1024]; char p6[10]; int width; int height; int depth; FILE *fp = fopen(file_name.data(), "rb"); fgets(cline, sizeof(cline), fp); sscanf(cline, "%s %d %d %d", p6, &width, &height, &depth); std::cout << p6 << "," << width << "," << height << "," << depth << std::endl; fread(image, sizeof(GLubyte), width * height * 3, fp); fclose(fp); } void init() { load_tex("gc_tex.ppm"); load_model("gc_tex.obj"); load_model("cow.obj", true, 0.90, 0.05, 0.25); // no tex data in cow obj // Initialize texture objects glGenTextures(1, textures); glBindTexture(GL_TEXTURE_2D, textures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TextureWidth, TextureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures[0]); // Create a vertex array object GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // Create and initialize a buffer object GLuint buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(tex_coords), NULL, GL_STATIC_DRAW); // Specify an offset to keep track of where we're placing data in our // vertex array buffer. We'll use the same technique when we // associate the offsets with vertex attribute pointers. GLintptr offset = 0; glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(points), points); offset += sizeof(points); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(tex_coords), tex_coords); // Load shaders and use the resulting shader program GLuint program = InitShader("vshader71.glsl", "fshader71.glsl"); glUseProgram(program); // set up vertex arrays offset = 0; GLuint vPosition = glGetAttribLocation(program, "vPosition"); glEnableVertexAttribArray(vPosition); glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset)); offset += sizeof(points); GLuint vTexCoord = glGetAttribLocation(program, "vTexCoord"); glEnableVertexAttribArray(vTexCoord); glVertexAttribPointer(vTexCoord, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset)); // Set the value of the fragment shader texture sampler variable // ("texture") to the the appropriate texture unit. In this case, // zero, for GL_TEXTURE0 which was previously set by calling // glActiveTexture(). glUniform1i(glGetUniformLocation(program, "tex"), 0); model_view = glGetUniformLocation(program, "model_view"); projection = glGetUniformLocation(program, "projection"); fog = glGetUniformLocation(program, "foggy"); eye_pos = glGetUniformLocation(program, "eye_pos"); glEnable(GL_DEPTH_TEST); glClearColor(1, 1, 1, 1); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); point4 eye(eye_x, eye_y, eye_z, 1.0); at_x = cos(theta) * cos(phi) * 100.0; at_y = sin(theta) * cos(phi) * 100.0; at_z = sin(phi) * 100.0; point4 at(at_x, at_y, at_z, 1.0); vec4 up(0.0, 100 * sin(tau), 100 * cos(tau), 0.0); mat4 mv = LookAt(eye, at, up); glUniformMatrix4fv(model_view, 1, GL_TRUE, mv); mat4 p = Frustum(left, right, bottom, top, zNear, zFar); glUniformMatrix4fv(projection, 1, GL_TRUE, p); glUniform3f(eye_pos, eye_x, eye_y, eye_z); glUniform1i(fog, foggy); glDrawArrays(GL_TRIANGLES, 0, NumVertices); glutSwapBuffers(); } //---------------------------------------------------------------------------- void mouse(int button, int state, int x, int y) {} //---------------------------------------------------------------------------- void idle(void) { glutPostRedisplay(); } //---------------------------------------------------------------------------- void keyboard(unsigned char key, int mousex, int mousey) { switch (key) { case 033: // Escape Key exit(0); break; case 'f': if (foggy > 0) { foggy = 0; } else { foggy = 1; } break; case '1': tau += 0.01; break; case '3': tau -= 0.01; break; case 'q': theta += 0.01; break; case 'e': theta -= 0.01; break; case 'A': at_x += 0.01; break; case 'D': at_x -= 0.001; break; case 'w': eye_x += 0.01; break; case 's': eye_x -= 0.01; break; case 'd': eye_y -= 0.01; break; case 'a': eye_y += 0.01; break; case '9': eye_z -= 0.01; break; case '6': eye_z += 0.01; break; case '8': phi -= 0.01; break; case '5': phi += 0.01; break; } if (PARAMS_DEBUG_PRINT) { printf("eye_x,y,z:%f, %f, %f, %f\n", eye_x, eye_y, eye_z, eye_w); printf("at_x,y,z:%f, %f, %f, %f\n", at_x, at_y, at_z, at_w); } glutPostRedisplay(); } //---------------------------------------------------------------------------- int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(512, 512); glutInitContextVersion(3, 1); glutInitContextProfile(GLUT_CORE_PROFILE); glutCreateWindow("flying"); if (glewInit() != GLEW_OK) { std::cerr << "Failed to initialize GLEW ... exiting" << std::endl; exit(EXIT_FAILURE); } init(); glutDisplayFunc(display); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); // glutIdleFunc(idle); glutMainLoop(); return 0; }