#include "Angel.h" #include #include #include const int NumTriangles = 64770; // (6 faces)(2 triangles/face) 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]; // Array of rotation angles (in degrees) for each coordinate axis enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 }; int Axis = Xaxis; GLfloat Theta[NumAxes] = {0.0, 0.0, 0.0}; GLuint theta; //---------------------------------------------------------------------------- void load_model(const std::string &file_name) { std::vector vertices; std::vector tex_cods; std::fstream s(file_name, std::fstream::in); if (!s.is_open()) { std::cerr << "failed to open" << file_name << std::endl; } else { int index = 0; 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, z / 50.0f, y / 50.0f, 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]; tex_coords[index] = tex_cods[a]; index++; points[index] = vertices[b]; tex_coords[index] = tex_cods[b]; index++; points[index] = vertices[c]; tex_coords[index] = tex_cods[c]; index++; num++; } } 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"); // 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_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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); theta = glGetUniformLocation(program, "theta"); glEnable(GL_DEPTH_TEST); glClearColor(1.0, 1.0, 1.0, 1.0); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUniform3fv(theta, 1, Theta); glDrawArrays(GL_TRIANGLES, 0, NumVertices); glutSwapBuffers(); } //---------------------------------------------------------------------------- void mouse(int button, int state, int x, int y) { if (state == GLUT_DOWN) { switch (button) { case GLUT_LEFT_BUTTON: Axis = Xaxis; break; case GLUT_MIDDLE_BUTTON: Axis = Yaxis; break; case GLUT_RIGHT_BUTTON: Axis = Zaxis; break; } } } //---------------------------------------------------------------------------- void idle(void) { Theta[Axis] += 0.5; if (Theta[Axis] > 360.0) { Theta[Axis] -= 360.0; } glutPostRedisplay(); } //---------------------------------------------------------------------------- void keyboard(unsigned char key, int mousex, int mousey) { switch (key) { case 033: // Escape Key case 'q': case 'Q': exit(EXIT_SUCCESS); break; case 'b': case 'B': glutIdleFunc(idle); break; case 'e': case 'E': glutIdleFunc(NULL); break; } 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; }