From: Seth Long Date: Thu, 21 Nov 2024 05:08:44 +0000 (-0800) Subject: Added rolling spheres X-Git-Url: https://isoptera.lcsc.edu/gitweb/?a=commitdiff_plain;h=1648ebb494aa5351d030b5e0d030a8df0e590dd2;p=example_engine%2F.git Added rolling spheres --- diff --git a/carpet.jpg b/carpet.jpg new file mode 100644 index 0000000..1067016 Binary files /dev/null and b/carpet.jpg differ diff --git a/floor_fragment_shader.glsl b/floor_fragment_shader.glsl index ac6612a..6f7e078 100644 --- a/floor_fragment_shader.glsl +++ b/floor_fragment_shader.glsl @@ -4,5 +4,6 @@ in vec4 fcolor; out vec4 outcolor; void main(void) { - outcolor = vec4(fcolor.xyz, 1); + float brightness = 0.25 * (fcolor.x + fcolor.y + fcolor.z); + outcolor = vec4(brightness, brightness, brightness, 1); } diff --git a/game.h b/game.h index 8ba01d7..e49caab 100644 --- a/game.h +++ b/game.h @@ -124,3 +124,8 @@ EXTERN vehicle *current_vehicle INIT(0); EXTERN size_t vehicle_index INIT(0); +// Objects defined in other header files that need to be global anyway +#include "hud.h" +EXTERN hud main_hud; + + diff --git a/geometric_objects.cpp b/geometric_objects.cpp index afbe5bd..abf1543 100644 --- a/geometric_objects.cpp +++ b/geometric_objects.cpp @@ -99,3 +99,153 @@ void flat_panel::draw(glm::mat4 vp) { glDrawArraysInstanced(GL_TRIANGLES, 0, 6, models.size()); } + +int sphere::init() { + /* Note: These are not really interpreted literally! + * x = sideways + * y = foward + * z = up + * sideways is forward cross up + * color, for now, is the color of each corner, with -1 interpreted as 0 + */ + size = glm::vec3(10, 10, 10); + float vertices[] = { + // front + -1.0, -1.0, 1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, + // back + -1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, 1.0, -1.0, + -1.0, 1.0, -1.0, + }; + glGenBuffers(1, &vbuf); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbuf); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + GLushort cube_elements[] = { + // front + 0, 1, 2, + 2, 3, 0, + // top + 1, 5, 6, + 6, 2, 1, + // back + 7, 6, 5, + 5, 4, 7, + // bottom + 4, 0, 3, + 3, 7, 4, + // left + 4, 5, 1, + 1, 0, 4, + // right + 3, 2, 6, + 6, 7, 3, + }; + glGenBuffers(1, &ebuf); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW); + + program = make_program("sphere_vs.glsl", "sphere_tcs.glsl", "sphere_tes.glsl", "sphere_gs.glsl", "sphere_fs.glsl"); + if (!program) + return 1; + + + glGenBuffers(1, &models_buffer); + glGenBuffers(1, &ups_buffer); + glGenBuffers(1, &forwards_buffer); + glGenBuffers(1, &radii_buffer); + + v_attrib = glGetAttribLocation(program, "in_vertex"); + mvp_uniform = glGetUniformLocation(program, "vp"); + return 0; +} + +void sphere::draw(glm::mat4 vp){ + glUseProgram(program); + data_mutex.lock(); + + std::vector models; + models.reserve(locations.size()); + for(size_t i = 0; i < locations.size(); i++){ + glm::mat4 new_model = glm::mat4(1.0f); + new_model = glm::translate(new_model, locations[i]); + models.push_back(new_model); + } + + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, models_buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, models.size() * sizeof(glm::mat4), models.data(), GL_STATIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, models_buffer); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ups_buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, ups.size() * sizeof(ups[0]), ups.data(), GL_STATIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ups_buffer); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, forwards_buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, forwards.size() * sizeof(forwards[0]), forwards.data(), GL_STATIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, forwards_buffer); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, radii_buffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, radii.size() * sizeof(float), radii.data(), GL_STATIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, radii_buffer); + + + data_mutex.unlock(); + + glEnableVertexAttribArray(v_attrib); + glBindBuffer(GL_ARRAY_BUFFER, vbuf); + glVertexAttribPointer(v_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); + + glUniformMatrix4fv(mvp_uniform, 1, 0, glm::value_ptr(vp)); + + glPatchParameteri(GL_PATCH_VERTICES, 3); + glDrawElementsInstanced(GL_PATCHES, 36, GL_UNSIGNED_SHORT, 0, models.size()); +} + +void sphere::addsphere(glm::vec3 location, float radius, glm::vec3 up, glm::vec3 forward){ + locations.push_back(location); + radii.push_back(radius); + ups.push_back(glm::vec4(up, 1.0f)); + forwards.push_back(glm::vec4(forward, 1.0f)); +} + +void rollsphere::roll_to(size_t index, glm::vec3 new_location, float speed){ + speeds[index] = speed; + new_locations[index] = new_location; + new_locations[index].y = locations[index].y; + float angular_velocity = speed / radii[index]; + glm::vec3 axis = glm::cross(new_locations[index] - locations[index], glm::vec3(0, 1, 0)); + main_hud.lprintf(0, "Angular Velocity: %f, axis %f, %f, %f\n", angular_velocity, axis.x, axis.y, axis.z); + rotation_matrices[index] = glm::rotate(glm::mat4(1.0f), -angular_velocity, axis); +} + +void rollsphere::move(int elapsed_time){ + for(size_t i = 0; i < locations.size(); i++){ + if(speeds[i] > 0.0001){ + glm::vec3 direction = glm::normalize(new_locations[i] - locations[i]); + locations[i] += speeds[i] * direction; + ups[i] = rotation_matrices[i] * ups[i]; + forwards[i] = rotation_matrices[i] * forwards[i]; + if(glm::length(new_locations[i] - locations[i]) < 0.01) + speeds[i] = 0.0f; + } + } +} + +void rollsphere::addsphere(glm::vec3 location, float radius, glm::vec3 up, glm::vec3 forward){ + sphere::addsphere(location, radius, up, forward); + new_locations.push_back(location); + speeds.push_back(0); + rotation_matrices.push_back(glm::mat4(1.0)); +} + +void rollsphere::activate(size_t index){ + roll_to(index, locations[index] + glm::normalize(locations[index] - player_position) * 100.0f, 0.01); +} + diff --git a/geometric_objects.h b/geometric_objects.h index 107ec5d..4e5751c 100644 --- a/geometric_objects.h +++ b/geometric_objects.h @@ -52,3 +52,28 @@ public: set_normal(i, locations[i] - player_position); } }; + +class sphere : virtual public gameobject { +public: + std::vector radii; + std::vector ups; + std::vector forwards; + unsigned radii_buffer, ups_buffer, forwards_buffer; + const char* texturefile; + + int init() override; + void draw(glm::mat4 vp) override; + virtual void addsphere(glm::vec3 location, float radius, glm::vec3 up = glm::vec3(0, 1, 0), glm::vec3 forward = glm::vec3(0, 0, 1)); +}; + +class rollsphere : virtual public sphere, virtual public block_object { +public: + std::vector new_locations; + std::vector speeds; + std::vector rotation_matrices; + + void roll_to(size_t index, glm::vec3 new_location, float speed); + void move(int elapsed_time); + void addsphere(glm::vec3 location, float radius, glm::vec3 up = glm::vec3(0, 1, 0), glm::vec3 forward = glm::vec3(0, 0, 1)); + void activate(size_t index); // For testing, roll 30 units along -x +}; diff --git a/main.cpp b/main.cpp index b2e8fa6..0c2f507 100644 --- a/main.cpp +++ b/main.cpp @@ -12,14 +12,13 @@ #include "moving_platform.h" #include "turret.h" #include "geometric_objects.h" -#include "hud.h" #include "door.h" #include "vehicle.h" std::mutex grand_mutex; -float height = 1600; -float width = 2550; +float height = 2080 ; +float width = 3820 ; /* Global section */ int time_resolution = 10; @@ -30,7 +29,6 @@ std::vector objects; projectile ice_balls; wall_block spawned_blocks("cube.obj", "projectile.jpg", glm::vec3(2, 2, 2)); fragment brick_fragments; -hud main_hud; class target : public loaded_object, public block_object { public: @@ -432,6 +430,13 @@ int main(int argc, char** argv) { fc.addpanel(glm::vec3(30, -5, 450), glm::vec2(3.0, 3.0), glm::vec2(1, 1)); objects.push_back(&fc); + rollsphere test_sphere; + test_sphere.addsphere(glm::vec3(30, 0, 510), 5); + test_sphere.addsphere(glm::vec3(30, 40, 510), 20); + test_sphere.addsphere(glm::vec3(20, -2, 530), 3); + test_sphere.addsphere(glm::vec3(-30, 10, 530), 20); + objects.push_back(&test_sphere); + /* Initialize game objects */ for(gameobject* o : objects){ if(o->init()){ diff --git a/sphere_fs.glsl b/sphere_fs.glsl new file mode 100644 index 0000000..3072216 --- /dev/null +++ b/sphere_fs.glsl @@ -0,0 +1,8 @@ +#version 460 + +in vec4 gs_colorout; +out vec4 outcolor; + +void main(void) { + outcolor = vec4(gs_colorout.xyz, 1); +} diff --git a/sphere_gs.glsl b/sphere_gs.glsl new file mode 100644 index 0000000..f245b13 --- /dev/null +++ b/sphere_gs.glsl @@ -0,0 +1,23 @@ +#version 450 + +layout(triangles, invocations=1) in; +in vec4 tes_colorout[]; +layout(line_strip, max_vertices=6) out; +out vec4 gs_colorout; + +void main(void) { + + gl_Position = gl_in[0].gl_Position; + gs_colorout = tes_colorout[0]; + EmitVertex(); + gl_Position = gl_in[1].gl_Position; + gs_colorout = tes_colorout[1]; + EmitVertex(); + gl_Position = gl_in[2].gl_Position; + gs_colorout = tes_colorout[2]; + EmitVertex(); + gl_Position = gl_in[0].gl_Position; + gs_colorout = tes_colorout[0]; + EmitVertex(); + EndPrimitive(); +} diff --git a/sphere_tcs.glsl b/sphere_tcs.glsl new file mode 100644 index 0000000..262e02e --- /dev/null +++ b/sphere_tcs.glsl @@ -0,0 +1,18 @@ +#version 460 +layout(vertices=3) out; + +in int vs_id[]; +in vec4 v_colorout[]; +out vec4 tcs_colorout[]; +out int vs_id_tcs[]; + +void main(void) { + int tesslv = 12; + gl_TessLevelOuter[0] = tesslv; + gl_TessLevelOuter[1] = tesslv; + gl_TessLevelOuter[2] = tesslv; + gl_TessLevelInner[0] = tesslv; + gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; + tcs_colorout[gl_InvocationID] = v_colorout[gl_InvocationID]; + vs_id_tcs[gl_InvocationID] = vs_id[gl_InvocationID]; +} diff --git a/sphere_tes.glsl b/sphere_tes.glsl new file mode 100644 index 0000000..973f7aa --- /dev/null +++ b/sphere_tes.glsl @@ -0,0 +1,41 @@ +#version 460 +layout(triangles, equal_spacing, ccw) in; + + +layout(packed, binding=0) buffer model_list { + mat4 models[]; +}; +layout(packed, binding=1) buffer up_list { + vec3 ups[]; +}; +layout(packed, binding=2) buffer forward_list { + vec3 forwards[]; +}; +layout(packed, binding=3) buffer radii_list { + float radii[]; +}; + +uniform mat4 vp; +in vec4 tcs_colorout[]; +in int vs_id_tcs[]; +out vec4 tes_colorout; + +vec4 n4(vec4 p){ + vec3 offset = p.xyz;// - cntr[0].xyz; + return vec4(normalize(offset) * radii[vs_id_tcs[0]], 1); +} + +void main(){ + vec4 p = + gl_TessCoord.x * gl_in[0].gl_Position + + gl_TessCoord.y * gl_in[1].gl_Position + + gl_TessCoord.z * gl_in[2].gl_Position; + + gl_Position = vp * models[vs_id_tcs[0]] * n4(p); + + tes_colorout = + gl_TessCoord.x * tcs_colorout[0] + + gl_TessCoord.y * tcs_colorout[1] + + gl_TessCoord.z * tcs_colorout[2]; +} + diff --git a/sphere_vs.glsl b/sphere_vs.glsl new file mode 100644 index 0000000..d1bd307 --- /dev/null +++ b/sphere_vs.glsl @@ -0,0 +1,39 @@ +#version 460 + + +layout(packed, binding=0) buffer model_list { + mat4 models[]; +}; +layout(packed, binding=1) buffer up_list { + vec3 ups[]; +}; +layout(packed, binding=2) buffer forward_list { + vec3 forwards[]; +}; +layout(packed, binding=3) buffer radii_list { + float radii[]; +}; + + +in vec3 in_vertex; +uniform mat4 vp; +out vec4 v_colorout; +out int vs_id; + +void main(void) { + vec3 sideways = normalize(cross(ups[gl_InstanceID], forwards[gl_InstanceID])); + vec3 pos = in_vertex.x * sideways + + in_vertex.y * forwards[gl_InstanceID] + + in_vertex.z * ups[gl_InstanceID]; + + gl_Position = vec4(pos, 1.0); + v_colorout = vec4(in_vertex, 1.0); + if(v_colorout.r < 0) + v_colorout.r = 0; + if(v_colorout.g < 0) + v_colorout.g = 0; + if(v_colorout.b < 0) + v_colorout.b = 0; + vs_id = gl_InstanceID; + +} diff --git a/vehicle.h b/vehicle.h index 54829bb..92219e2 100644 --- a/vehicle.h +++ b/vehicle.h @@ -4,7 +4,7 @@ class flying_carpet : virtual public vehicle, virtual public flat_panel { public: - flying_carpet() : flat_panel("brick.jpg") { + flying_carpet() : flat_panel("carpet.jpg") { size = glm::vec3(10, 1, 10); }