#include "engine.h" // initialization: Texture and vertices into memory bool StoneBlock::init(){ solid = true; hostile = true; GLfloat cube_vertices[] = { // front -0.25, -0.25, 0.25, 0.25, -0.25, 0.25, 0.25, 0.25, 0.25, -0.25, 0.25, 0.25, // top -0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, -0.25, -0.25, 0.25, -0.25, // back 0.25, -0.25, -0.25, -0.25, -0.25, -0.25, -0.25, 0.25, -0.25, 0.25, 0.25, -0.25, // bottom -0.25, -0.25, -0.25, 0.25, -0.25, -0.25, 0.25, -0.25, 0.25, -0.25, -0.25, 0.25, // left -0.25, -0.25, -0.25, -0.25, -0.25, 0.25, -0.25, 0.25, 0.25, -0.25, 0.25, -0.25, // right 0.25, -0.25, 0.25, 0.25, -0.25, -0.25, 0.25, 0.25, -0.25, 0.25, 0.25, 0.25, }; for(float &n : cube_vertices) n *= cube_size; glGenBuffers(1, &vbuf); glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbuf); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW); GLushort cube_elements[] = { // front 0, 1, 2, 2, 3, 0, // top 4, 5, 6, 6, 7, 4, // back 8, 9, 10, 10, 11, 8, // bottom 12, 13, 14, 14, 15, 12, // left 16, 17, 18, 18, 19, 16, // right 20, 21, 22, 22, 23, 20, }; element_count = sizeof(cube_elements) / sizeof(GLushort); glGenBuffers(1, &ebuf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW); GLfloat cube_texcoords[2*4*6] = { // front 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, }; for (int i = 1; i < 6; i++) memcpy(&cube_texcoords[i*4*2], &cube_texcoords[0], 2*4*sizeof(GLfloat)); glGenBuffers(1, &tbuf); glBindBuffer(GL_ARRAY_BUFFER, tbuf); glBufferData(GL_ARRAY_BUFFER, sizeof(cube_texcoords), cube_texcoords, GL_STATIC_DRAW); setup_locations(); setup_texture(texfile); setup_standard_shaders(); return true; } bool StoneBlock::in_contact_location(float x, float y, float z, int i){ const float margin = 0.25 * cube_size + 0.1; if(abs(x - locations[i].x) < margin && abs(y - locations[i].y) < margin && abs(z - locations[i].z) < margin){ return true; } return false; } void StoneBlock::draw(mat4 vp) { if(location_refresh){ update_locations(); location_refresh = false; } glUseProgram(program); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); glUniform1i(tex_uniform, 0); glUniformMatrix4fv(mvp_uniform, 1, 0, glm::value_ptr(vp)); glEnableVertexAttribArray(vertex_attrib); glBindBuffer(GL_ARRAY_BUFFER, vbuf); glVertexAttribPointer(vertex_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(tex_attrib); glBindBuffer(GL_ARRAY_BUFFER, tbuf); glVertexAttribPointer(tex_attrib, 2, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, lbuf); glDrawElementsInstanced(GL_TRIANGLES, element_count, GL_UNSIGNED_SHORT, 0, locations.size()); } // movement: for falling calculations // Returns the effective floor level float StoneBlock::find_floor(){ float efloor = -1000; for(vec3 l : locations){ if(abs(player_x - l.x) < 0.25 * cube_size && abs(player_z - l.z) < 0.25 * cube_size){ if(l.y < player_y - 0.2 && l.y > efloor) efloor = l.y + 1; } } return efloor; } bool StoneBlock::dangerous_at(vec4 loc){ for(int i = 0; i < locations.size(); i++) { vec4 mbl = locations[i]; if(fabs(loc.x - mbl.x) < 0.5 * cube_size && fabs(loc.y - mbl.y) < 0.5 * cube_size && fabs(loc.z - mbl.z) < 0.5 * cube_size){ locations[i] = locations[locations.size() - 1]; locations.pop_back(); location_refresh = true; return true; } } return false; } void StoneBlock::activate(float x, float y, float z){ int i = in_contact(x, y, z); if(i != -1){ locations[i].z += 10; location_refresh = true; } }