#include "Angel.h" #include #include #include #define PARAMS_DEBUG_PRINT true 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; // terrain altitude array float ter_alt[128][256]; // 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]; vec3 normals[NumVertices]; // plane light params GLuint plane_light; GLfloat light_on = 1.0f; // fog params GLuint fog; // is_foggy uniform GLuint eye_pos; int foggy = 1; GLuint fog_fac; float fogFac = 1.0f; // object (cow) params GLuint obj_shi; float objShi = 50.0f; // 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 //---------------------------------------------------------------------------- bool hit_check(GLfloat &x, GLfloat &y, GLfloat &z) { int x_idx = x * 256; int y_idx = y * 256; if (x_idx > 255 || x_idx < 0 || y_idx < 0 || y_idx > 127) { x = 0.0; y = 0.25; z = 0.1; return false; } if (PARAMS_DEBUG_PRINT) { printf("%f, %f\n", ter_alt[y_idx][x_idx], z); } if (ter_alt[y_idx][x_idx] >= z) { x = 0.0; y = 0.25; z = 0.1; return false; } return true; } void load_model(const std::string &file_name, bool not_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; int idx = 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); if (!not_tex) { *(reinterpret_cast(ter_alt) + idx) = y / 50.0f; idx++; } } else if (t == "vt") { s >> x >> y; tex_cods.emplace_back(x, y); } else if (t == "f") { s >> a >> b >> c; a--; b--; c--; vec3 normal = normalize( cross(vertices[b] - vertices[a], vertices[c] - vertices[b])); points[index] = vertices[a]; normals[index] = normal; if (not_tex) { tex_coords[index] = {20.0, 0.0}; } else { tex_coords[index] = tex_cods[a]; } index++; points[index] = vertices[b]; normals[index] = normal; if (not_tex) { tex_coords[index] = {20.0, 0.0}; } else { tex_coords[index] = tex_cods[b]; } index++; points[index] = vertices[c]; normals[index] = normal; if (not_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) + sizeof(normals), 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); offset += sizeof(tex_coords); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(normals), normals); // 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)); offset += sizeof(tex_coords); GLuint vNormal = glGetAttribLocation(program, "vNormal"); glEnableVertexAttribArray(vNormal); glVertexAttribPointer(vNormal, 3, 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"); plane_light = glGetUniformLocation(program, "plane_light_on"); fog_fac = glGetUniformLocation(program, "fog_fac"); obj_shi = glGetUniformLocation(program, "obj_shi"); 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); glUniform1f(plane_light, light_on); glUniform1f(fog_fac, fogFac); glUniform1f(obj_shi, objShi); 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 'l': if (light_on > 0.0) { light_on = 0.0; } else { light_on = 1.0; } break; case 'f': if (foggy > 0) { foggy = 0; } else { foggy = 1; } break; case 'k': objShi -= 1.0f; if (objShi < 0.0f) { objShi = 0.0f; } break; case 'K': objShi += 1.0f; break; case 'g': fogFac -= 0.1; if (fogFac < 0) { fogFac = 0; } break; case 'G': fogFac += 0.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 '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("obj_shi:%f\n", objShi); 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); } hit_check(eye_x, eye_y, eye_z); 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; }